UNPKG

autotel-cloudflare

Version:

The #1 OpenTelemetry package for Cloudflare Workers - complete bindings coverage, native CF OTel integration, advanced sampling

106 lines (96 loc) 3.48 kB
/** * Queue producer binding instrumentation */ import { trace, SpanKind, SpanStatusCode, } from '@opentelemetry/api'; import type { WorkerTracer } from 'autotel-edge'; import { wrap, setAttr } from './common'; /** * Instrument Queue producer binding */ export function instrumentQueueProducer<T extends Queue>(queue: T, queueName?: string): T { const name = queueName || 'queue'; const handler: ProxyHandler<T> = { get(target, prop) { const value = Reflect.get(target, prop); if (prop === 'send' && typeof value === 'function') { return new Proxy(value, { apply: (fnTarget, _thisArg, args) => { const tracer = trace.getTracer('autotel-edge') as WorkerTracer; return tracer.startActiveSpan( `Queue ${name}: send`, { kind: SpanKind.PRODUCER, attributes: { 'messaging.system': 'cloudflare-queues', 'messaging.operation.type': 'publish', 'messaging.operation': 'send', 'messaging.destination.name': name, }, }, async (span) => { try { const result = await Reflect.apply(fnTarget, target, args); setAttr(span, 'messaging.message.id', (result as any)?.messageId); span.setStatus({ code: SpanStatusCode.OK }); return result; } catch (error) { span.recordException(error as Error); span.setStatus({ code: SpanStatusCode.ERROR, message: error instanceof Error ? error.message : String(error), }); throw error; } finally { span.end(); } }, ); }, }); } if (prop === 'sendBatch' && typeof value === 'function') { return new Proxy(value, { apply: (fnTarget, _thisArg, args) => { const [messages] = args as [{ body: unknown }[]]; const tracer = trace.getTracer('autotel-edge') as WorkerTracer; return tracer.startActiveSpan( `Queue ${name}: sendBatch`, { kind: SpanKind.PRODUCER, attributes: { 'messaging.system': 'cloudflare-queues', 'messaging.operation.type': 'publish', 'messaging.operation': 'sendBatch', 'messaging.destination.name': name, 'messaging.batch.message_count': Array.isArray(messages) ? messages.length : 0, }, }, async (span) => { try { const result = await Reflect.apply(fnTarget, target, args); span.setStatus({ code: SpanStatusCode.OK }); return result; } catch (error) { span.recordException(error as Error); span.setStatus({ code: SpanStatusCode.ERROR, message: error instanceof Error ? error.message : String(error), }); throw error; } finally { span.end(); } }, ); }, }); } return value; }, }; return wrap(queue, handler); }