Skip to content

Commit 11c5ac2

Browse files
committed
Improvements for the cf-workers package
1 parent a391811 commit 11c5ac2

File tree

8 files changed

+100
-158
lines changed

8 files changed

+100
-158
lines changed

.changeset/wide-women-happen.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@pydantic/logfire-cf-workers": patch
3+
---
4+
5+
Embed microlabs as a dependency

README.md

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -58,59 +58,37 @@ Run the script above with `node hello.js`, and you should see the span being log
5858

5959
### Cloudflare Workers
6060

61-
First, install the `@microlabs/otel-cf-workers` [NPM package](https://github.com/evanderkoogh/otel-cf-workers) and the `@pydantic/logfire-cf-workers @pydantic/logfire-api` NPM package:
61+
First, install the `@pydantic/logfire-cf-workers @pydantic/logfire-api` NPM packages:
6262

6363
```sh
64-
npm install @microlabs/otel-cf-workers @opentelemetry/api @pydantic/logfire-cf-workers @pydantic/logfire-api
64+
npm install @pydantic/logfire-cf-workers @pydantic/logfire-api
6565
```
66-
As per the otel-cf-workers package instructions, add `compatibility_flags = [ "nodejs_compat" ]` to your wrangler.toml or `"compatibility_flags": ["nodejs_compat"]` if you're using `wrangler.jsonc`.
66+
Next, add `compatibility_flags = [ "nodejs_compat" ]` to your wrangler.toml or `"compatibility_flags": ["nodejs_compat"]` if you're using `wrangler.jsonc`.
6767

68-
Add your [Logfire write token](https://logfire.pydantic.dev/docs/how-to-guides/create-write-tokens/) to your Wrangler file:
68+
Add your [Logfire write token](https://logfire.pydantic.dev/docs/how-to-guides/create-write-tokens/) to your `.dev.vars` file. Check the [Cloudflare documentation for further details on how to manage and deploy the secrets](https://developers.cloudflare.com/workers/configuration/secrets/).
6969

70-
`wrangler.jsonc`:
71-
72-
```json
73-
"vars": {
74-
"LOGFIRE_TOKEN": "your-write-token",
75-
},
76-
```
77-
78-
`wrangler.toml`:
79-
80-
```toml
81-
[vars]
82-
LOGFIRE_WRITE_TOKEN="your-write-token"
70+
```sh
71+
LOGFIRE_TOKEN=your-write-token
8372
```
8473

8574
Next, add the necessary instrumentation around your handler. The `tracerConfig` function will extract your write token from the `env` object and provide the necessary configuration for the instrumentation:
8675

8776
```ts
88-
import { instrument, ResolveConfigFn } from '@microlabs/otel-cf-workers';
89-
import { tracerConfig } from '@pydantic/logfire-cf-workers';
90-
// Optional, if you want to manually create spans. Regular OTel API can be used as well.
9177
import * as logfire from '@pydantic/logfire-api';
92-
93-
export interface Env {
94-
LOGFIRE_TOKEN: string;
95-
LOGFIRE_BASE_URL: string;
96-
OTEL_TEST: KVNamespace;
97-
}
78+
import { instrument } from '@pydantic/logfire-cf-workers';
9879

9980
const handler = {
100-
async fetch(): Promise<Response> {
101-
logfire.info('Logfire: info from inside the worker body');
102-
return new Response('Hello World!');
103-
},
104-
} satisfies ExportedHandler<Env>;
105-
106-
const config: ResolveConfigFn = (env: Env, _trigger) => {
107-
return {
108-
service: { name: 'cloudflare-worker', namespace: '', version: '1.0.0' },
109-
...tracerConfig(env),
110-
};
111-
};
112-
113-
export default instrument(handler, config);
81+
async fetch(): Promise<Response> {
82+
logfire.info('info span from inside the worker body');
83+
return new Response('Hello World!');
84+
},
85+
} satisfies ExportedHandler;
86+
87+
export default instrument(handler, {
88+
serviceName: 'cloudflare-worker',
89+
serviceNamespace: '',
90+
serviceVersion: '1.0.0',
91+
});
11492
```
11593

11694
A working example can be found in the `examples/cloudflare-worker` directory.

examples/cloudflare-worker/src/index.ts

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,18 @@
1010
*
1111
* Learn more at https://developers.cloudflare.com/workers/
1212
*/
13-
import { instrument, ResolveConfigFn } from '@microlabs/otel-cf-workers';
14-
import { tracerConfig } from '@pydantic/logfire-cf-workers';
1513
import * as logfire from '@pydantic/logfire-api';
16-
17-
export interface Env {
18-
LOGFIRE_TOKEN: string;
19-
LOGFIRE_BASE_URL: string;
20-
OTEL_TEST: KVNamespace;
21-
}
14+
import { instrument } from '@pydantic/logfire-cf-workers';
2215

2316
const handler = {
2417
async fetch(): Promise<Response> {
2518
logfire.info('info span from inside the worker body');
2619
return new Response('Hello World!');
2720
},
28-
} satisfies ExportedHandler<Env>;
29-
30-
const config: ResolveConfigFn = (env: Env, _trigger) => {
31-
return {
32-
service: { name: 'cloudflare-worker', namespace: '', version: '1.0.0' },
33-
...tracerConfig(env),
34-
};
35-
};
21+
} satisfies ExportedHandler;
3622

37-
export default instrument(handler, config);
23+
export default instrument(handler, {
24+
serviceName: 'cloudflare-worker',
25+
serviceNamespace: '',
26+
serviceVersion: '1.0.0',
27+
});

examples/cloudflare-worker/wrangler.jsonc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@
2828
* Environment Variables
2929
* https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
3030
*/
31-
"vars": {
32-
"LOGFIRE_TOKEN": "your-token",
33-
},
31+
"vars": {},
3432
/**
3533
* Note: Use secrets to store sensitive data.
3634
* https://developers.cloudflare.com/workers/configuration/secrets/

package-lock.json

Lines changed: 16 additions & 69 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/logfire-cf-workers/package.json

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@
4848
"prepack": "cp ../../LICENSE .",
4949
"postpack": "rm LICENSE"
5050
},
51+
"dependencies": {
52+
"@microlabs/otel-cf-workers": "^1.0.0-rc.49"
53+
},
5154
"devDependencies": {
52-
"@microlabs/otel-cf-workers": "^1.0.0-rc.49",
53-
"@opentelemetry/exporter-trace-otlp-proto": "^0.57.2",
55+
"@cloudflare/workers-types": "4.20250311.0",
5456
"@opentelemetry/sdk-trace-base": "^1.30.1",
5557
"@pydantic/logfire-tooling-config": "*",
5658
"eslint": "^9.22.0",
@@ -60,11 +62,6 @@
6062
"vite-plugin-dts": "^4.5.3",
6163
"vitest": "^3.0.8"
6264
},
63-
"peerDependencies": {
64-
"@microlabs/otel-cf-workers": "^1.0.0-rc.49",
65-
"@opentelemetry/exporter-trace-otlp-proto": "^0.57.2",
66-
"@opentelemetry/sdk-trace-base": "^1.30.1"
67-
},
6865
"files": [
6966
"dist",
7067
"LICENSE"

packages/logfire-cf-workers/src/index.ts

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,63 @@
1-
import type { OTLPExporterConfig, PostProcessorFn } from '@microlabs/otel-cf-workers'
2-
1+
import { KVNamespace } from '@cloudflare/workers-types'
2+
import { instrument as microlabsInstrument } from '@microlabs/otel-cf-workers'
33
import { ReadableSpan } from '@opentelemetry/sdk-trace-base'
44

55
export interface CloudflareConfigOptions {
66
baseUrl?: string
77
token: string
88
}
99

10+
interface Env {
11+
LOGFIRE_BASE_URL: string
12+
LOGFIRE_TOKEN: string
13+
OTEL_TEST: KVNamespace
14+
}
15+
16+
export interface LogfireCloudflareConfigOptions {
17+
serviceName?: string
18+
serviceNamespace?: string
19+
serviceVersion?: string
20+
}
21+
1022
const DEFAULT_LOGFIRE_BASE_URL = 'https://logfire-api.pydantic.dev/'
1123

12-
export function cloudflareExporterConfig({ baseUrl = DEFAULT_LOGFIRE_BASE_URL, token }: CloudflareConfigOptions): OTLPExporterConfig {
13-
if (!baseUrl.endsWith('/')) {
14-
baseUrl += '/'
15-
}
16-
return {
17-
headers: { Authorization: token },
18-
url: `${baseUrl}v1/traces`,
24+
function getConfig(config: LogfireCloudflareConfigOptions) {
25+
return (env: Env) => {
26+
let { LOGFIRE_BASE_URL: baseUrl = DEFAULT_LOGFIRE_BASE_URL, LOGFIRE_TOKEN: token } = env
27+
28+
if (!baseUrl.endsWith('/')) {
29+
baseUrl += '/'
30+
}
31+
32+
return {
33+
exporter: {
34+
headers: { Authorization: token },
35+
url: `${baseUrl}v1/traces`,
36+
},
37+
postProcessor: filterEmptyAttributes,
38+
service: {
39+
name: config.serviceName ?? 'cloudflare-worker',
40+
namespace: config.serviceNamespace ?? '',
41+
version: config.serviceVersion ?? '0.0.0',
42+
},
43+
}
1944
}
2045
}
2146

22-
export function filterEmptyAttributes(spans: ReadableSpan[]) {
47+
export function instrument<T>(handler: T, config: LogfireCloudflareConfigOptions): T {
48+
return microlabsInstrument(handler, getConfig(config))
49+
}
50+
51+
// ATM this is broken in microlabs,
52+
/*
53+
function instrumentDO<T>(doClass: T, config: LogfireCloudflareConfigOptions): T {
54+
// the d.ts bundler choked on this
55+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
56+
return microlabsInstrumentDO(doClass as unknown as any, getConfig(config)) as T
57+
}
58+
*/
59+
60+
function filterEmptyAttributes(spans: ReadableSpan[]) {
2361
for (const span of spans) {
2462
for (const attrKey of Object.keys(span.attributes)) {
2563
const attrVal = span.attributes[attrKey]
@@ -32,14 +70,3 @@ export function filterEmptyAttributes(spans: ReadableSpan[]) {
3270
}
3371
return spans
3472
}
35-
36-
export function tracerConfig(env: { LOGFIRE_BASE_URL?: string; LOGFIRE_TOKEN: string }): {
37-
exporter: OTLPExporterConfig
38-
postProcessor: PostProcessorFn
39-
} {
40-
const { LOGFIRE_BASE_URL: baseUrl = DEFAULT_LOGFIRE_BASE_URL, LOGFIRE_TOKEN: token } = env
41-
return {
42-
exporter: cloudflareExporterConfig({ baseUrl, token }),
43-
postProcessor: filterEmptyAttributes,
44-
}
45-
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import defineConfig from '@pydantic/logfire-tooling-config/vite-config'
22
import { resolve } from 'node:path'
33

4-
export default defineConfig(resolve(__dirname, 'src/index.ts'))
4+
export default defineConfig(resolve(__dirname, 'src/index.ts'), ['@microlabs/otel-cf-workers'])

0 commit comments

Comments
 (0)