replicate/otel-cf-workers
forked from pydantic/otel-cf-workers
Captured source
source ↗replicate/otel-cf-workers
Description: An OpenTelemetry compatible library for instrumenting and exporting traces for Cloudflare Workers
License: BSD-3-Clause
Stars: 0
Forks: 0
Open issues: 0
Created: 2025-10-03T15:11:16Z
Pushed: 2025-10-06T15:48:55Z
Default branch: main
Fork: yes
Parent repository: pydantic/otel-cf-workers
Archived: no
README:
otel-cf-workers
An OpenTelemetry compatible library for instrumenting and exporting traces from Cloudflare Workers.
Getting started
npm install @microlabs/otel-cf-workers @opentelemetry/api
> [!IMPORTANT] > To be able to use the Open Telemetry library you have to add the NodeJS compatibility flag in your wrangler.toml file.
compatibility_flags = [ "nodejs_compat" ]
For a simple setup example with configuration examples, have a look at the Quickstart Example
Code example
import { trace } from '@opentelemetry/api'
import { instrument, ResolveConfigFn } from '@microlabs/otel-cf-workers'
export interface Env {
HONEYCOMB_API_KEY: string
OTEL_TEST: KVNamespace
}
const handler = {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise {
await fetch('https://cloudflare.com')
const greeting = "G'day World"
trace.getActiveSpan()?.setAttribute('greeting', greeting)
ctx.waitUntil(fetch('https://workers.dev'))
return new Response(`${greeting}!`)
},
}
const config: ResolveConfigFn = (env: Env, _trigger) => {
return {
exporter: {
url: 'https://api.honeycomb.io/v1/traces',
headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY },
},
service: { name: 'greetings' },
}
}
export default instrument(handler, config)Auto-instrumentation
Workers
Wrapping your exporter handler with the instrument function is all you need to do to automatically have not just the functions of you handler auto-instrumented, but also the global fetch and caches and all of the supported bindings in your environment such as KV.
See the quick start code sample for an example of how it works.
Durable Objects
Instrumenting Durable Objects work very similar to the regular Worker auto-instrumentation. Instead of wrapping the handler in an instrument call, you wrap the Durable Object class with the instrumentDO function.
import { instrumentDO, PartialTraceConfig } from '@microlabs/otel-cf-workers'
const config: ResolveConfigFn = (env: Env, _trigger) => {
return {
exporter: {
url: 'https://api.honeycomb.io/v1/traces',
headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY },
},
service: { name: 'greetings-do' },
}
}
class OtelDO implements DurableObject {
async fetch(request: Request): Promise {
return new Response('Hello World!')
}
}
const TestOtelDO = instrumentDO(OtelDO, doConfig)
export { TestOtelDO }Creating custom spans
While auto-instrumenting should take care of a lot of the information that you would want to add, there will always be application specific information you want to send along.
You can get the current active span by doing:
import {trace} from '@opentelemetry/api'
const handler = {
async fetch(request: Request) {
const span = trace.getActiveSpan()
if(span) span.setAttributes('name', 'value')
....
}
}Or if you want to create a new span:
import { trace } from '@opentelemetry/api'
const handler = {
async fetch(request: Request) {
const tracer = trace.getTracer('my_own_tracer_name')
return tracer.startActiveSpan('name', (span) => {
const response = await doSomethingAwesome
span.end()
return response
})
},
}Configuration
For configuration you can either pass in a TraceConfig or a function that takes the Environment and the trigger for this particular trace and returns a TraceConfig.
Because the configuration function is run separately for every new invocation, it is possible to tailor your configuration for every type of request. So it is for example possible to have a much lower sampling ratio for your healthchecks than actual API requests.
Exporter
In the exporter, you need to configure where to send spans to. It can take either an instance of a class that implements the standard Open Telemetry SpanExporterinterface, or an object with the properties url and optionally headers to configure an exporter for the Open Telemetry format.
Examples:
const exporter = new ConsoleSpanExporter()
const exporter = {
url: 'https://api.honeycomb.io/v1/traces',
headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY },
}Fetch
includeTraceContext is used to specify if outgoing requests should include the TraceContext so that the other service can participate in a distributed trace. The default is true for all outgoing requests, but you can turn it off for all requests with false, or specify a method that takes the outgoing Request method and return a boolean on whether to include the tracing context.
Example:
const fetchConf = (request: Request): boolean => {
return new URL(request.url).hostname === 'example.com'
}Handlers
The handlers field of the configuration overrides the way in which event handlers, such as fetch or queue, are instrumented.
Fetch Handler
acceptTraceContext is used to specify if incoming requests handled by fetch should accept a TraceContext and participate in a distributed trace. The default is true for all incoming requests, but you can turn it off for all requests with false or specify a method that takes the incoming Request and returns a boolean indicating whether to accept the tracing context.
Example:
const fetchConf = (request: Request): boolean => {
return new URL(request.url).hostname === 'example.com'
}PostProcessor
The PostProcessor function is called just before exporting the spans and allows you to make any changes to the spans before sending this. For example to remove entire spans, or to remove or redact security or privacy sensitive data.
Example:
const postProcessor = (spans: ReadableSpan[]): ReadableSpan[] => {
spans[0].attributes['http.url'] = 'REDACTED'
return spans
}Sampling
One of the challenges of tracing is that for sites and applications with a lot of traffic it becomes prohibitively…
Excerpt shown — open the source for the full document.
Notability
notability 2.0/10Routine fork, no significant traction