ForkReplicateReplicatepublished Oct 3, 2025seen 5d

replicate/otel-cf-workers

forked from pydantic/otel-cf-workers

Open original ↗

Captured source

source ↗
published Oct 3, 2025seen 5dcaptured 14hhttp 200method plain

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/10

Routine fork, no significant traction