### with() Method Example Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/context-and-async-storage.md Demonstrates activating a context, starting a span within it, and then executing an asynchronous operation where the span is available. ```typescript import { context as api_context } from '@opentelemetry/api' import { trace } from '@opentelemetry/api' const currentContext = api_context.active() const newContext = api_context.with(currentContext, () => { const span = trace.getTracer('app').startSpan('operation') const updatedContext = trace.setSpan(currentContext, span) return updatedContext }) api_context.with(newContext, async () => { const span = trace.getActiveSpan() // span is available here await doWork() }) ``` -------------------------------- ### Service Configuration Example Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/configuration.md Example of configuring the 'service' field, which is required to identify your service in traces. It includes name, version, and namespace. ```typescript service: { name: 'api-gateway', version: '1.2.3', namespace: 'production', } ``` -------------------------------- ### Example: Configuring MultiSpanExporterAsync Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/multi-span-exporter.md Demonstrates how to configure the MultiSpanExporterAsync with multiple OTLP exporters for different backends like Honeycomb and Datadog. This setup is typically used within a Cloudflare Worker. ```typescript import { MultiSpanExporterAsync, OTLPExporter, instrument, ResolveConfigFn, } from '@microlabs/otel-cf-workers' interface Env { HONEYCOMB_API_KEY: string DATADOG_API_KEY: string } const config: ResolveConfigFn = (env: Env, trigger) => { const honeycomb = new OTLPExporter({ url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY }, }) const datadog = new OTLPExporter({ url: 'https://api.datadoghq.com/api/v2/spans', headers: { 'dd-api-key': env.DATADOG_API_KEY }, }) const multiExporter = new MultiSpanExporterAsync([honeycomb, datadog]) return { exporter: multiExporter, service: { name: 'my-worker' }, } } export default instrument(handler, config) ``` -------------------------------- ### Example Usage Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/batch-trace-span-processor.md Demonstrates how to initialize and use the BatchTraceSpanProcessor with an OTLPExporter. ```APIDOC ```typescript import { BatchTraceSpanProcessor, OTLPExporter } from '@microlabs/otel-cf-workers' const exporter = new OTLPExporter({ url: '...' }) const processor = new BatchTraceSpanProcessor(exporter) const config: ResolveConfigFn = (env, trigger) => ({ spanProcessors: processor, service: { name: 'my-worker' }, }) export default instrument(handler, config) ``` ``` -------------------------------- ### Example Usage Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/otlp-exporter.md Demonstrates how to instantiate and configure the OTLPExporter with basic and custom backend configurations. ```APIDOC ### Example Usage ```typescript import { OTLPExporter } from '@microlabs/otel-cf-workers' const exporter = new OTLPExporter({ url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': 'your-api-key', }, }) ``` ### Example with Custom Backend ```typescript const exporter = new OTLPExporter({ url: 'http://localhost:4318/v1/traces', headers: { Authorization: 'Bearer token-123', }, }) ``` ``` -------------------------------- ### Install otel-cf-workers Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/README.md Install the necessary packages for OpenTelemetry instrumentation in Cloudflare Workers. ```bash npm install @microlabs/otel-cf-workers @opentelemetry/api ``` -------------------------------- ### Basic Setup for Cloudflare Workers Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/README.md This snippet shows the basic setup for instrumenting a Cloudflare Worker. It requires importing the `instrument` function and configuring the exporter and service name. ```typescript import { instrument } from '@microlabs/otel-cf-workers' const config = { exporter: { url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': 'your-key' }, }, service: { name: 'my-worker' }, } export default instrument(handler, config) ``` -------------------------------- ### Install Dependencies and Set Secret Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/examples/quickstart/QUICKSTART_GUIDE.md Install the necessary OpenTelemetry packages and set your Honeycomb API key as a secret using Wrangler. ```bash npm install @microlabs/otel-cf-workers @opentelemetry/api npx wrangler secret put HONEYCOMB_API_KEY ``` -------------------------------- ### Example with Multiple Exporters Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/batch-trace-span-processor.md Shows how to configure BatchTraceSpanProcessor with multiple exporters using MultiSpanExporter. ```APIDOC ```typescript import { BatchTraceSpanProcessor, OTLPExporter, MultiSpanExporter } from '@microlabs/otel-cf-workers' const honeycomb = new OTLPExporter({ url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY }, }) const datadog = new OTLPExporter({ url: 'https://api.datadoghq.com/api/v2/spans', headers: { 'dd-api-key': env.DATADOG_API_KEY }, }) const multiExporter = new MultiSpanExporter([honeycomb, datadog]) const processor = new BatchTraceSpanProcessor(multiExporter) const config: ResolveConfigFn = (env, trigger) => ({ spanProcessors: processor, service: { name: 'my-worker' }, }) export default instrument(handler, config) ``` ``` -------------------------------- ### Example with Custom Backend Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/otlp-exporter.md Shows how to configure the OTLPExporter to send traces to a custom backend, such as a local OTLP collector. ```typescript const exporter = new OTLPExporter({ url: 'http://localhost:4318/v1/traces', headers: { Authorization: 'Bearer token-123', }, }) ``` -------------------------------- ### Basic Example Usage Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/batch-trace-span-processor.md Demonstrates basic usage of BatchTraceSpanProcessor with a single OTLPExporter. Ensure the exporter is correctly configured with a URL. ```typescript import { BatchTraceSpanProcessor, OTLPExporter } from '@microlabs/otel-cf-workers' const exporter = new OTLPExporter({ url: '...' }) const processor = new BatchTraceSpanProcessor(exporter) const config: ResolveConfigFn = (env, trigger) => ({ spanProcessors: processor, service: { name: 'my-worker' }, }) export default instrument(handler, config) ``` -------------------------------- ### Full Cloudflare Worker Instrumentation Example Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/worker-tracer.md A complete example demonstrating how to instrument a Cloudflare Worker with OpenTelemetry, including request handling, data fetching spans, and configuration. ```typescript import { trace, SpanKind } from '@opentelemetry/api' import { instrument } from '@microlabs/otel-cf-workers' const handler = { async fetch(request: Request) { const tracer = trace.getTracer('my-app') return await tracer.startActiveSpan('handle-request', { kind: SpanKind.SERVER, attributes: { 'http.method': request.method }, }, async (rootSpan) => { const data = await tracer.startActiveSpan('fetch-data', { kind: SpanKind.CLIENT, }, async (childSpan) => { const response = await fetch('https://api.example.com/data') childSpan.setAttribute('http.status_code', response.status) return response.json() }) return new Response(JSON.stringify(data)) }) } } const config = (env) => ({ exporter: { url: '...' }, service: { name: 'my-worker' }, }) export default instrument(handler, config) ``` -------------------------------- ### Example Usage of OTLPExporter Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/otlp-exporter.md Demonstrates how to instantiate and configure the OTLPExporter with a Honeycomb endpoint and API key. ```typescript import { OTLPExporter } from '@microlabs/otel-cf-workers' const exporter = new OTLPExporter({ url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': 'your-api-key', }, }) ``` -------------------------------- ### Custom Integration Example Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/worker-tracer-provider.md Demonstrates how to manually instantiate and register the WorkerTracerProvider for custom integration scenarios. ```APIDOC ## Example: Custom Integration ```typescript import { WorkerTracerProvider } from '@microlabs/otel-cf-workers' import { BatchTraceSpanProcessor, OTLPExporter } from '@microlabs/otel-cf-workers' import { resourceFromAttributes } from '@opentelemetry/resources' const resource = resourceFromAttributes({ 'service.name': 'my-worker', 'service.version': '1.0.0', }) const exporter = new OTLPExporter({ url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': 'your-key' }, }) const processor = new BatchTraceSpanProcessor(exporter) const provider = new WorkerTracerProvider([processor], resource) provider.register() // Now use the global trace API import { trace } from '@opentelemetry/api' const tracer = trace.getTracer('my-module') ``` ``` -------------------------------- ### Queue Handler Instrumentation Example Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/handler-instrumentation.md This example demonstrates how to instrument a queue handler. The instrumentation automatically creates a root span for the batch, tracks message acknowledgments and retries as events, and records batch statistics upon completion. Ensure your handler function is correctly structured to leverage these features. ```typescript const handler = { async queue(batch: MessageBatch, env: Env, ctx: ExecutionContext) { // Automatic root span created // span.name === "queueHandler {batch.queue}" for (const msg of batch.messages) { try { const data = JSON.parse(msg.body) await processData(data) msg.ack() // Event "messageAck" recorded } catch (error) { msg.retry() // Event "messageRetry" recorded } } // On completion, span includes batch statistics } } ``` -------------------------------- ### Example PostProcessorFn Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/types.md An example implementation of PostProcessorFn that filters out spans with a duration shorter than 1ms. ```typescript const postProcessor: PostProcessorFn = (spans) => { // Remove spans shorter than 1ms return spans.filter(s => { const duration = s.duration return duration[0] > 0 || duration[1] > 1000000 // seconds or nanoseconds }) } ``` -------------------------------- ### Tail Sampling Configuration Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/batch-trace-span-processor.md Example configuration for tail sampling. This allows dynamic filtering of traces based on post-execution metrics like errors or latency. The provided example keeps traces that ended with errors. ```typescript const config: ResolveConfigFn = (env, trigger) => ({ exporter: { url: '...' }, service: { name: 'my-worker' }, sampling: { tailSampler: (traceInfo) => { // Keep traces with errors const rootSpan = traceInfo.localRootSpan return rootSpan.status.code === SpanStatusCode.ERROR }, }, }) ``` -------------------------------- ### Complete Production OpenTelemetry Setup Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/configuration.md A comprehensive configuration for production, including Honeycomb exporter, service naming, and custom sampling and post-processing logic. ```typescript import { instrument, ResolveConfigFn } from '@microlabs/otel-cf-workers' import { isRootErrorSpan } from '@microlabs/otel-cf-workers' interface Env { HONEYCOMB_API_KEY: string ENVIRONMENT: string } const config: ResolveConfigFn = (env: Env, trigger) => { // Sample errors at 100%, other traces at 10% return { exporter: { url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY }, }, service: { name: 'my-worker', namespace: env.ENVIRONMENT, version: env.VERSION || 'unknown', }, sampling: { headSampler: { ratio: 0.1 }, tailSampler: isRootErrorSpan, }, postProcessor: (spans) => { // Redact sensitive headers spans.forEach(span => { const auth = span.attributes['http.request.header.authorization'] if (auth) span.attributes['http.request.header.authorization'] = 'REDACTED' }) return spans }, } } export default instrument(handler, config) ``` -------------------------------- ### Example with Multiple Exporters Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/batch-trace-span-processor.md Shows how to use BatchTraceSpanProcessor with multiple exporters, such as Honeycomb and Datadog, using MultiSpanExporter. Ensure API keys and URLs are correctly set. ```typescript import { BatchTraceSpanProcessor, OTLPExporter, MultiSpanExporter } from '@microlabs/otel-cf-workers' const honeycomb = new OTLPExporter({ url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY }, }) const datadog = new OTLPExporter({ url: 'https://api.datadoghq.com/api/v2/spans', headers: { 'dd-api-key': env.DATADOG_API_KEY }, }) const multiExporter = new MultiSpanExporter([honeycomb, datadog]) const processor = new BatchTraceSpanProcessor(multiExporter) const config: ResolveConfigFn = (env, trigger) => ({ spanProcessors: processor, service: { name: 'my-worker' }, }) export default instrument(handler, config) ``` -------------------------------- ### bind() Method Example Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/context-and-async-storage.md Shows how to bind a callback function to a context, ensuring it executes within that context when called later, such as in a setTimeout. ```typescript const boundFn = api_context.bind(myContext, myCallback) setTimeout(boundFn, 1000) // myCallback executes in myContext ``` -------------------------------- ### Fetch Handler Instrumentation Example Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/handler-instrumentation.md Demonstrates automatic root span creation for fetch requests, adding custom attributes, and making automatically traced outbound requests. The span name is updated after route detection. ```typescript const handler = { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { // Automatic root span created const span = trace.getActiveSpan() // span.name === "fetchHandler GET" // span.kind === SpanKind.SERVER // Add custom attributes const userId = new URL(request.url).searchParams.get('user_id') span?.setAttribute('user.id', userId) // Make outbound request (automatically traced) const result = await fetch('https://api.example.com/data') // http.response.status_code is automatically added return new Response('OK') } } // Registered with http.route attribute export default instrument(handler, config) ``` -------------------------------- ### startSpan() Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/worker-tracer.md Creates a new span with a given name and optional configuration. This span can be further configured with attributes, kind, links, and start time. It is returned as an active span for subsequent operations. ```APIDOC ## startSpan() ### Description Creates a new span with a given name and optional configuration. This span can be further configured with attributes, kind, links, and start time. It is returned as an active span for subsequent operations. ### Method `startSpan(name: string, options?: SpanOptions, context?: Context): Span` ### Parameters #### Path Parameters - **name** (string) - Required - Span display name - **options** (SpanOptions) - Optional - Span configuration - **context** (Context) - Optional - Parent context; use `undefined` for new root span #### Options (SpanOptions) - **attributes** (Attributes) - Initial key-value pairs - **kind** (SpanKind) - `INTERNAL`, `SERVER`, `CLIENT`, `PRODUCER`, `CONSUMER` - **links** (Link[]) - Links to other spans - **startTime** (TimeInput) - Start timestamp (default: now) - **root** (boolean) - If `true`, creates a new trace (ignores parent context) ### Returns `Span` — an active span that can have attributes set and events added ### Example ```typescript const span = tracer.startSpan('database-query', { attributes: { 'db.statement': 'SELECT * FROM users', 'db.system': 'postgresql', }, kind: SpanKind.CLIENT, }) span.end() ``` ``` -------------------------------- ### Basic Instrumented Cloudflare Worker Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/examples/quickstart/QUICKSTART_GUIDE.md This example shows a basic Cloudflare Worker that is instrumented to send traces to Honeycomb. Ensure your `wrangler.toml` includes `compatibility_flags = [ "nodejs_compat" ]`. ```typescript import { instrument, ResolveConfigFn } from '@microlabs/otel-cf-workers' import { trace } from '@opentelemetry/api' export interface Env { HONEYCOMB_API_KEY: string } const handler = { await fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { // Get the URL of the origin server const url = new URL(request.url) const originUrl = `https://${url.hostname}${url.pathname}${url.search}` // Create a new request to the origin server const originRequest = new Request(originUrl, { method: request.method, headers: request.headers, body: request.body, }) // Add tracing information trace.getActiveSpan()?.setAttribute('origin_url', originUrl) // Fetch from the origin server // Return the response from the origin server return await fetch(originRequest) } } const config: ResolveConfigFn = (env: Env, _trigger: any) => { return { exporter: { url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY }, }, service: { name: 'my-service-name' }, } } export default instrument(handler, config) ``` -------------------------------- ### Per-Route Configuration with Custom Handlers Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/configuration.md Configure tracing differently for specific URL path prefixes. This example shows distinct configurations for AI and database API endpoints, including custom trace context acceptance logic for database requests. A default configuration is provided for all other routes. ```typescript const config: ResolveConfigFn = (env, trigger) => { if (trigger instanceof Request) { const url = new URL(trigger.url) // Sample AI endpoints differently if (url.pathname.startsWith('/api/ai/')) { return { exporter: { url: '...' }, service: { name: 'my-worker' }, sampling: { headSampler: { ratio: 0.5 } }, } } // Sample database endpoints with high fidelity if (url.pathname.startsWith('/api/db/')) { return { exporter: { url: '...' }, service: { name: 'my-worker' }, sampling: { headSampler: { ratio: 1.0 } }, handlers: { fetch: { acceptTraceContext: (req) => { return new URL(req.url).hostname.endsWith('.example.com') }, }, }, } } } // Default config return { exporter: { url: '...' }, service: { name: 'my-worker' }, sampling: { headSampler: { ratio: 0.1 } }, } } ``` -------------------------------- ### Instantiate and Use MultiSpanExporter Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/multi-span-exporter.md Instantiate MultiSpanExporter with an array of SpanExporter instances. This example shows configuring exporters for Honeycomb and a local OTLP collector, then integrating MultiSpanExporter into a Cloudflare Worker using the instrument function. ```typescript import { MultiSpanExporter, OTLPExporter, instrument, } from '@microlabs/otel-cf-workers' const honeycomb = new OTLPExporter({ url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': env.HONEYCOMB_API_KEY }, }) const otelCollector = new OTLPExporter({ url: 'http://localhost:4318/v1/traces', }) const multiExporter = new MultiSpanExporter([honeycomb, otelCollector]) const config: ResolveConfigFn = (env, trigger) => ({ exporter: multiExporter, service: { name: 'my-worker' }, }) export default instrument(handler, config) ``` -------------------------------- ### Custom WorkerTracerProvider Integration Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/worker-tracer-provider.md Example of manually instantiating and configuring WorkerTracerProvider for custom integrations. This involves setting up exporters, processors, and resources before registering the provider. ```typescript import { WorkerTracerProvider } from '@microlabs/otel-cf-workers' import { BatchTraceSpanProcessor, OTLPExporter } from '@microlabs/otel-cf-workers' import { resourceFromAttributes } from '@opentelemetry/resources' const resource = resourceFromAttributes({ 'service.name': 'my-worker', 'service.version': '1.0.0', }) const exporter = new OTLPExporter({ url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': 'your-key' }, }) const processor = new BatchTraceSpanProcessor(exporter) const provider = new WorkerTracerProvider([processor], resource) provider.register() // Now use the global trace API import { trace } from '@opentelemetry/api' const tracer = trace.getTracer('my-module') ``` -------------------------------- ### Configure Replit Run Command for Persistent Data Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/examples/queue/README.md Update the 'replit-run-command' key in your 'package.json' file to 'npm run start-persist'. This ensures that the 'Run' button in Replit always starts your Worker in persistent mode. ```json { "replit-run-command": "npm run start-persist" } ``` -------------------------------- ### Handler Configuration: Accept Trace Context Conditionally Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/configuration.md Example of configuring the 'fetch' handler to conditionally accept W3C Trace Context headers based on the request's hostname. This allows for selective trace context propagation. ```typescript handlers: { fetch: { // Only accept trace context from internal APIs acceptTraceContext: (request: Request) => { const url = new URL(request.url) return url.hostname === 'internal.example.com' }, }, } ``` -------------------------------- ### Configure Batch Span Processor with Head and Tail Sampling Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/batch-trace-span-processor.md Configure the Batch Span Processor to use both head and tail sampling. Head sampling controls the initial sampling ratio, while tail sampling allows for custom logic to retain specific traces, such as error traces, regardless of the head sampler's decision. This example demonstrates setting a 10% head sampling ratio and a tail sampler that preserves all error traces. ```typescript const config: ResolveConfigFn = (env, trigger) => ({ exporter: { url: '...' }, service: { name: 'my-worker' }, sampling: { headSampler: { ratio: 0.1 }, // Sample 10% of requests tailSampler: (traceInfo) => { // But keep ALL error traces regardless of head sampling return traceInfo.localRootSpan.status.code === SpanStatusCode.ERROR }, }, }) ``` -------------------------------- ### Conditional Trace Context Inclusion for Outgoing Requests Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/README.md Specify which outgoing requests should include trace context. This example includes trace context only for requests to 'example.com'. ```typescript const fetchConf = (request: Request): boolean => { return new URL(request.url).hostname === 'example.com' } ``` -------------------------------- ### Tail Sampling: Combine Multiple Samplers Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/configuration.md Combines multiple tail sampling strategies using a multiTailSampler. This example includes keeping head-sampled traces and error traces. ```typescript import { isHeadSampled, isRootErrorSpan, multiTailSampler } from '@microlabs/otel-cf-workers' sampling: { tailSampler: multiTailSampler([isHeadSampled, isRootErrorSpan]), } ``` -------------------------------- ### Create Child Spans Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/README.md This example demonstrates how to create child spans for nested operations within a Cloudflare Worker. It uses `startActiveSpan` to automatically manage the span lifecycle. ```typescript import { trace } from '@opentelemetry/api' const handler = { async fetch(request: Request) { const tracer = trace.getTracer('my-app') const data = await tracer.startActiveSpan('fetch-data', async (span) => { span.setAttribute('service', 'api') return await fetch('https://api.example.com/data') }) return new Response(JSON.stringify(data)) } } ``` -------------------------------- ### Static and Dynamic Configuration Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/configuration.md Demonstrates how to provide configuration either statically as a TraceConfig object or dynamically using a ResolveConfigFn function that is called per request. ```typescript // Static config const config: TraceConfig = { exporter: { url: '...' }, service: { name: 'my-worker' }, } // Dynamic config const config: ResolveConfigFn = (env, trigger) => ({ exporter: { url: '...' }, service: { name: 'my-worker' }, }) export default instrument(handler, config) ``` -------------------------------- ### Proxy Get Trap Helper Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/instrumentation-utilities.md A helper function for proxy 'get' traps that forwards property access to the target. It correctly handles function binding and supports RPC properties, while unwrapping the target and thisArg. ```typescript export function passthroughGet(target: any, prop: string | symbol, thisArg?: any) ``` ```typescript const handler: ProxyHandler = { get(target, prop) { if (shouldIntercept(prop)) { return interceptedValue } else { return passthroughGet(target, prop) } }, } ``` -------------------------------- ### Create a sampler from a ratio with createSampler() Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/instrumentation-utilities.md Creates an OpenTelemetry Sampler instance from a ratio-based configuration. Allows specifying a sampling ratio and whether to accept remote parent trace context. ```typescript const sampler = createSampler({ ratio: 0.1, acceptRemote: false }) ``` -------------------------------- ### Modify Spans Before Export Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/README.md A post-processor function to modify spans before they are exported. This example redacts the http.url attribute of the first span. ```typescript const postProcessor = (spans: ReadableSpan[]): ReadableSpan[] => { spans[0].attributes['http.url'] = 'REDACTED' return spans } ``` -------------------------------- ### Integration with instrument() Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/otlp-exporter.md Shows how to integrate the OTLPExporter with the `instrument` function, either by providing configuration or an exporter instance directly. ```APIDOC ### Integration with instrument() ```typescript 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: 'my-worker' }, } } export default instrument(handler, config) ``` Or provide an instance directly: ```typescript const exporter = new OTLPExporter({ url: '...' }) const config: ResolveConfigFn = (env: Env, trigger) => { return { exporter, service: { name: 'my-worker' }, } } export default instrument(handler, config) ``` ``` -------------------------------- ### Console Span Exporter Configuration Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/README.md Use this to export spans to the console. No additional setup is required beyond instantiating the exporter. ```typescript const exporter = new ConsoleSpanExporter() ``` -------------------------------- ### createSampler() Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/INDEX.md Create a ratio-based sampler. ```APIDOC ## createSampler() ### Description Create a ratio-based sampler. ### Method Function ### Endpoint N/A (SDK utility) ### Parameters N/A (See [Instrumentation Utilities](api-reference/instrumentation-utilities.md) for details) ### Request Example N/A ### Response N/A ``` -------------------------------- ### Span Name Update Example Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/handler-instrumentation.md Illustrates how the span name is updated from a generic fetch handler name to a more specific route after detection. ```typescript // Original name "fetchHandler GET" // After route detection "GET /api/users" ``` -------------------------------- ### Head Sampling with Custom Sampler Instance Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/configuration.md Demonstrates using a custom sampler instance, specifically TraceIdRatioBasedSampler, for head sampling. This allows for more granular control over sampling logic. ```typescript import { TraceIdRatioBasedSampler } from '@opentelemetry/sdk-trace-base' sampling: { headSampler: new TraceIdRatioBasedSampler(0.1), } ``` -------------------------------- ### createSampler() Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/instrumentation-utilities.md Creates an OpenTelemetry Sampler instance from a ratio-based configuration. ```APIDOC ## createSampler(conf: ParentRatioSamplingConfig): Sampler ### Description Creates a sampler from a ratio-based config. ### Parameters #### Path Parameters - **conf** (ParentRatioSamplingConfig) - Required - Configuration object for ratio-based sampling ##### ParentRatioSamplingConfig | Field | Type | Default | Description | |-------|------|---------|-------------| | ratio | `number` | — | Sampling ratio (0-1) | | acceptRemote | `boolean` | `true` | Accept trace context from remote parent | ### Returns An OpenTelemetry `Sampler` instance ### Example ```typescript const sampler = createSampler({ ratio: 0.1, acceptRemote: false }) // Samples 10% of local traces, ignores remote sampling decisions ``` ``` -------------------------------- ### Add Event to Span Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/span-impl.md Add an event to the span with a name and optional attributes or a start time. This method supports method chaining. ```typescript span.addEvent('cache_miss', { 'cache.key': 'user-123' }) span.addEvent('retry', { 'retry.attempt': 2 }, Date.now() + 100) ``` -------------------------------- ### Post-process Spans Before Export Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/auto-instrumentation.md Configure a post-processor function to modify spans before they are exported. This example demonstrates redacting URLs and dropping short-lived spans. ```typescript const config: ResolveConfigFn = (env, trigger) => ({ exporter: { url: '...' }, service: { name: 'my-worker' }, postProcessor: (spans) => { // Example: redact URLs spans.forEach(span => { if (span.attributes['http.url']) { const url = new URL(span.attributes['http.url']) span.attributes['http.url'] = `${url.protocol}//${url.host}${url.pathname}` } }) // Example: drop short-lived spans return spans.filter(s => { const duration = s.duration return duration[0] > 0 || duration[1] > 1_000_000 // > 1ms }) }, }) ``` -------------------------------- ### Span Processors with Custom Exporter Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/configuration.md Example of using custom span processors with a BatchTraceSpanProcessor and a custom SpanExporter. This is useful for advanced span processing scenarios. ```typescript import { BatchTraceSpanProcessor } from '@microlabs/otel-cf-workers' import { SpanExporter } from '@opentelemetry/sdk-trace-base' const myExporter: SpanExporter = { export(spans, callback) { console.log(`Exporting ${spans.length} spans`) callback({ code: ExportResultCode.SUCCESS }) }, async shutdown() {}, } const processor = new BatchTraceSpanProcessor(myExporter) export default instrument(handler, { spanProcessors: processor, service: { name: 'my-worker' }, }) ``` -------------------------------- ### onStart Method Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/batch-trace-span-processor.md Called when a span is created. Registers the span in its trace's state. The parentContext parameter is unused in the current implementation. ```typescript onStart(span: Span, parentContext: Context): void ``` -------------------------------- ### Exporter Configuration with OTLPExporter Instance Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/configuration.md Shows how to configure the exporter by providing an instance of OTLPExporter. This is an alternative to configuring the exporter URL and headers directly. ```typescript import { OTLPExporter } from '@microlabs/otel-cf-workers' const exporter = new OTLPExporter({ url: '...' }) export default instrument(handler, { exporter, service: { name: 'my-worker' }, }) ``` -------------------------------- ### Filter Out Sensitive Data Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/README.md Implement a `postProcessor` function to filter or redact sensitive data from spans before they are exported. This example shows how to remove authorization headers. ```typescript const config = { exporter: { url: '...' }, service: { name: 'my-worker' }, postProcessor: (spans) => { spans.forEach(span => { // Redact authorization headers const auth = span.attributes['http.request.header.authorization'] if (auth) { span.attributes['http.request.header.authorization'] = 'REDACTED' } }) return spans }, } export default instrument(handler, config) ``` -------------------------------- ### passthroughGet() Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/instrumentation-utilities.md A helper function for proxy `get` traps that forwards property access to the target object, correctly handling function binding and RPC properties. ```APIDOC ## passthroughGet() ### Description Helper for proxy `get` traps that forwards property access to the target. ### Signature ```typescript export function passthroughGet(target: any, prop: string | symbol, thisArg?: any) ``` ### Behavior - Handles function binding correctly - Supports RPC properties - Unwraps target and thisArg ### Example (in proxy handler) ```typescript const handler: ProxyHandler = { get(target, prop) { if (shouldIntercept(prop)) { return interceptedValue } else { return passthroughGet(target, prop) } }, } ``` ``` -------------------------------- ### with() Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/context-and-async-storage.md Executes a function within a specific context, activating the given context for the duration of the function and restoring the previous context afterward. It properly handles both sync and async functions and is used by `tracer.startActiveSpan()`. ```APIDOC #### with() Executes a function within a specific context. ```typescript with( context: Context, fn: (...args: A) => R, thisArg?: any, ...args: A ): R ``` **Parameters:** | Parameter | Type | Description | |-----------|------|-------------| | context | `Context` | Context to activate | | fn | `(...args: A) => R` | Function to execute | | thisArg | `any` | `this` context for function (optional) | | args | `A` | Arguments to pass to function | **Returns:** Return value of `fn` **Behavior:** - Activates the given context for the duration of `fn` - Restores previous context after `fn` completes - Properly handles both sync and async functions - Used by `tracer.startActiveSpan()` to set the span in context **Example:** ```typescript import { context as api_context } from '@opentelemetry/api' import { trace } from '@opentelemetry/api' const currentContext = api_context.active() const newContext = api_context.with(currentContext, () => { const span = trace.getTracer('app').startSpan('operation') const updatedContext = trace.setSpan(currentContext, span) return updatedContext }) api_context.with(newContext, async () => { const span = trace.getActiveSpan() // span is available here await doWork() }) ``` ``` -------------------------------- ### wrap() Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/INDEX.md Wrap objects in proxies to enable instrumentation. ```APIDOC ## wrap() ### Description Wrap objects in proxies to enable instrumentation. ### Method Function ### Endpoint N/A (SDK utility) ### Parameters N/A (See [Instrumentation Utilities](api-reference/instrumentation-utilities.md) for details) ### Request Example N/A ### Response N/A ``` -------------------------------- ### Get and Set Attributes on Active Span Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/README.md Retrieve the current active span using `trace.getActiveSpan()` and set attributes on it. This is useful for adding context to existing spans. ```typescript import {trace} from '@opentelemetry/api' const handler = { await fetch(request: Request): Promise { const span = trace.getActiveSpan() if(span) span.setAttributes('name', 'value') // ... } } ``` -------------------------------- ### SpanImpl Constructor Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/span-impl.md Initializes a new SpanImpl instance with the provided configuration. ```APIDOC ### Constructor #### Parameters ```typescript interface SpanInit { attributes: unknown name: string onEnd: OnSpanEnd resource: Resource spanContext: SpanContext parentSpanContext?: SpanContext links?: Link[] parentSpanId?: string spanKind?: SpanKind startTime?: TimeInput } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | attributes | `unknown` | Yes | Initial attributes (sanitized on construction) | | name | `string` | Yes | Display name of the span | | onEnd | `OnSpanEnd` | Yes | Callback invoked when span ends | | resource | `Resource` | Yes | Resource that produced this span | | spanContext | `SpanContext` | Yes | Span ID, trace ID, and flags | | parentSpanContext | `SpanContext` | No | Parent span's context (for distributed tracing) | | links | `Link[]` | No | Links to other spans | | parentSpanId | `string` | No | String representation of parent span ID | | spanKind | `SpanKind` | No | `INTERNAL`, `SERVER`, `CLIENT`, `PRODUCER`, `CONSUMER` | | startTime | `TimeInput` | No | Start timestamp; defaults to `Date.now()` | ``` -------------------------------- ### Get and Set Attributes on Active Span Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/worker-tracer.md Retrieve the currently active span within a request handler and set attributes on it. Ensure the OpenTelemetry API is imported. ```typescript import { trace } from '@opentelemetry/api' const span = trace.getActiveSpan() if (span) { span.setAttribute('custom.field', 'value') } ``` -------------------------------- ### WorkerTracer Class Signature Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/worker-tracer.md Defines the WorkerTracer class, implementing the OpenTelemetry Tracer interface. It includes methods for starting spans, managing their lifecycle, and flushing traces. ```typescript class WorkerTracer implements Tracer { constructor(spanProcessors: SpanProcessor[], resource: Resource) startSpan(name: string, options?: SpanOptions, context?: Context): Span startActiveSpan(name: string, fn: F): ReturnType startActiveSpan(name: string, options: SpanOptions, fn: F): ReturnType startActiveSpan(name: string, options: SpanOptions, context: Context, fn: F): ReturnType async forceFlush(traceId?: string): Promise addToResource(extra: Resource): void } ``` -------------------------------- ### Configure Ratio-Based Head Sampler Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/README.md Configure head sampling with a specific ratio of requests to sample. `acceptRemote` controls whether to accept incoming trace contexts. ```typescript const headSampler = { acceptRemote: false, //Whether to accept incoming trace contexts ratio: 0.5 //number between 0 and 1 that represents the ratio of requests to sample. 0 is none and 1 is all requests. } ``` -------------------------------- ### Integrating Tracing with Span Creation Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/context-and-async-storage.md Demonstrates how to use `tracer.startActiveSpan` to create and activate a new span within the current context. Any code executed within the callback of `startActiveSpan` can access the active span using `trace.getActiveSpan()`. ```typescript const tracer = trace.getTracer('app') await tracer.startActiveSpan('operation', async (span) => { // Inside: api_context.active() contains this span const activeSpan = trace.getActiveSpan() // returns span await helper() // helper also sees span in context }) async function helper() { const span = trace.getActiveSpan() // same span span?.setAttribute('helper.called', true) } ``` -------------------------------- ### Context Propagation with startActiveSpan Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/worker-tracer.md Demonstrates how `startActiveSpan` ensures the span's context is propagated, making it available in nested or called functions. The active span can be retrieved using `trace.getActiveSpan()`. ```typescript async function helper() { const span = trace.getActiveSpan() // span is available here even though helper() didn't create it span?.setAttribute('helper.called', true) } tracer.startActiveSpan('operation', async (span) => { await helper() // span is active here }) ``` -------------------------------- ### Export to Multiple Backends Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/README.md This snippet demonstrates how to export traces to multiple backends simultaneously using `MultiSpanExporterAsync`. It configures two OTLP exporters for Honeycomb and Datadog. ```typescript import { MultiSpanExporterAsync, OTLPExporter } from '@microlabs/otel-cf-workers' const config = { exporter: new MultiSpanExporterAsync([ new OTLPExporter({ url: 'https://api.honeycomb.io/v1/traces', headers: { 'x-honeycomb-team': env.HONEYCOMB_KEY }, }), new OTLPExporter({ url: 'https://api.datadoghq.com/api/v2/spans', headers: { 'dd-api-key': env.DATADOG_KEY }, }), ]), service: { name: 'my-worker' }, } export default instrument(handler, config) ``` -------------------------------- ### HandlerInstrumentation Interface Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/types.md Interface for instrumenting a specific handler type. It defines methods for getting initial span information, attributes from results, instrumenting triggers, and handling execution success or failure. ```typescript interface HandlerInstrumentation { getInitialSpanInfo: (trigger: T) => InitialSpanInfo getAttributesFromResult?: (result: Awaited) => Attributes instrumentTrigger?: (trigger: T) => T executionSucces?: (span: Span, trigger: T, result: Awaited) => void executionFailed?: (span: Span, trigger: T, error?: any) => void } ``` -------------------------------- ### Enable Node.js Compatibility Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/README.md Configure your wrangler.toml to enable Node.js compatibility, which is required for the OpenTelemetry library. ```json compatibility_flags = [ "nodejs_compat" ] ``` -------------------------------- ### Nested Spans with Context Propagation Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/context-and-async-storage.md Demonstrates creating nested spans within a Cloudflare Worker's fetch handler. Shows how `startActiveSpan` correctly propagates context, allowing `trace.getActiveSpan()` to retrieve the correct span at different points in the asynchronous chain. ```typescript import { trace, context as api_context } from '@opentelemetry/api' const handler = { async fetch(request: Request) { const tracer = trace.getTracer('my-app') return await tracer.startActiveSpan('handle-request', async (rootSpan) => { // rootSpan is active here const root = trace.getActiveSpan() // === rootSpan const result = await tracer.startActiveSpan('db-query', async (dbSpan) => { // dbSpan is now active, rootSpan is parent const db = trace.getActiveSpan() // === dbSpan const response = await fetch('https://db.example.com') dbSpan.setAttribute('http.status', response.status) return response.json() }) // Back in rootSpan context const back = trace.getActiveSpan() // === rootSpan again rootSpan.setAttribute('result.rows', result.length) return new Response(JSON.stringify(result)) }) } } ``` -------------------------------- ### Dynamic Sampling per Route Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/README.md Configure dynamic sampling ratios for different routes in your Cloudflare Worker. This example shows how to adjust sampling based on the request path, like reducing sampling for health checks. ```typescript const config = (env, trigger) => { if (trigger instanceof Request) { const url = new URL(trigger.url) // Low sampling for health checks if (url.pathname === '/health') { return { exporter: { url: '...' }, service: { name: 'my-worker' }, sampling: { headSampler: { ratio: 0.01 } }, } } // Normal sampling otherwise return { exporter: { url: '...' }, service: { name: 'my-worker' }, sampling: { headSampler: { ratio: 0.1 } }, } } return { exporter: { url: '...' }, service: { name: 'my-worker' }, } } export default instrument(handler, config) ``` -------------------------------- ### register() Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/worker-tracer-provider.md Registers this provider as the global OpenTelemetry tracer provider and context manager. This is often called automatically by instrumentation functions. ```APIDOC ## Method register() ### Description Registers this provider as the global OpenTelemetry tracer provider and context manager. It sets the global tracer provider and registers `AsyncLocalStorageContextManager` as the global context manager. This method is called automatically by `instrument()` and `instrumentDO()`. ### Signature ```typescript register(): void ``` ### Behavior - Sets this provider as the global tracer provider via `trace.setGlobalTracerProvider()` - Registers `AsyncLocalStorageContextManager` as the global context manager - Called automatically by `instrument()` and `instrumentDO()` ``` -------------------------------- ### Integration with instrument() - Config Function Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/otlp-exporter.md Illustrates integrating the OTLPExporter into a Cloudflare Worker using the instrument function with a configuration resolver. ```typescript 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: 'my-worker' }, } } export default instrument(handler, config) ``` -------------------------------- ### AsyncLocalStorage Context Propagation Source: https://github.com/evanderkoogh/otel-cf-workers/blob/main/_autodocs/api-reference/context-and-async-storage.md Illustrates how AsyncLocalStorage maintains separate storage for each asynchronous execution context within a Cloudflare Worker. Each handler (fetch, scheduled, queue) gets its own context, and all async operations within that handler inherit the context. ```text Main execution context ├─ fetch() handler │ ├─ AsyncLocalStorage slot A (active span, config) │ ├─ async operation 1 │ │ └─ AsyncLocalStorage inherits from parent │ └─ async operation 2 │ └─ AsyncLocalStorage inherits from parent ├─ scheduled() handler │ └─ AsyncLocalStorage slot B (different slot) └─ queue() handler └─ AsyncLocalStorage slot C (different slot) ```