@sentry/cloudflare 11.0.0-alpha.2 → 11.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/dev/client.js +2 -1
- package/build/cjs/dev/client.js.map +1 -1
- package/build/cjs/dev/durableobject.js +3 -77
- package/build/cjs/dev/durableobject.js.map +1 -1
- package/build/cjs/dev/index.js +5 -4
- package/build/cjs/dev/index.js.map +1 -1
- package/build/cjs/dev/instrumentations/agents/instrumentAgentCallableRpc.js +3 -1
- package/build/cjs/dev/instrumentations/agents/instrumentAgentCallableRpc.js.map +1 -1
- package/build/cjs/dev/instrumentations/instrumentDurableObjectHandlers.js +123 -0
- package/build/cjs/dev/instrumentations/instrumentDurableObjectHandlers.js.map +1 -0
- package/build/cjs/dev/instrumentations/instrumentDurableObjectStorage.js +3 -1
- package/build/cjs/dev/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
- package/build/cjs/dev/instrumentations/instrumentDurableObjectSyncKvStorage.js +3 -1
- package/build/cjs/dev/instrumentations/instrumentDurableObjectSyncKvStorage.js.map +1 -1
- package/build/cjs/dev/instrumentations/instrumentSqlStorage.js +6 -3
- package/build/cjs/dev/instrumentations/instrumentSqlStorage.js.map +1 -1
- package/build/cjs/dev/instrumentations/instrumentWorkerEntrypoint.js +2 -1
- package/build/cjs/dev/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
- package/build/cjs/dev/instrumentations/worker/instrumentD1.js +6 -3
- package/build/cjs/dev/instrumentations/worker/instrumentD1.js.map +1 -1
- package/build/cjs/dev/instrumentations/worker/instrumentEnv.js +0 -7
- package/build/cjs/dev/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/cjs/dev/instrumentations/worker/instrumentQueueProducer.js +3 -2
- package/build/cjs/dev/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
- package/build/cjs/dev/sdk.js +0 -1
- package/build/cjs/dev/sdk.js.map +1 -1
- package/build/cjs/dev/utils/isBinding.js +0 -4
- package/build/cjs/dev/utils/isBinding.js.map +1 -1
- package/build/cjs/dev/vendor/stacktrace.js +2 -1
- package/build/cjs/dev/vendor/stacktrace.js.map +1 -1
- package/build/cjs/dev/wrapRequestHandlerWithInit.js +2 -1
- package/build/cjs/dev/wrapRequestHandlerWithInit.js.map +1 -1
- package/build/cjs/prod/client.js +2 -1
- package/build/cjs/prod/client.js.map +1 -1
- package/build/cjs/prod/durableobject.js +3 -77
- package/build/cjs/prod/durableobject.js.map +1 -1
- package/build/cjs/prod/index.js +5 -4
- package/build/cjs/prod/index.js.map +1 -1
- package/build/cjs/prod/instrumentations/agents/instrumentAgentCallableRpc.js +3 -1
- package/build/cjs/prod/instrumentations/agents/instrumentAgentCallableRpc.js.map +1 -1
- package/build/cjs/prod/instrumentations/instrumentDurableObjectHandlers.js +123 -0
- package/build/cjs/prod/instrumentations/instrumentDurableObjectHandlers.js.map +1 -0
- package/build/cjs/prod/instrumentations/instrumentDurableObjectStorage.js +3 -1
- package/build/cjs/prod/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
- package/build/cjs/prod/instrumentations/instrumentDurableObjectSyncKvStorage.js +3 -1
- package/build/cjs/prod/instrumentations/instrumentDurableObjectSyncKvStorage.js.map +1 -1
- package/build/cjs/prod/instrumentations/instrumentSqlStorage.js +6 -3
- package/build/cjs/prod/instrumentations/instrumentSqlStorage.js.map +1 -1
- package/build/cjs/prod/instrumentations/instrumentWorkerEntrypoint.js +2 -1
- package/build/cjs/prod/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
- package/build/cjs/prod/instrumentations/worker/instrumentD1.js +6 -3
- package/build/cjs/prod/instrumentations/worker/instrumentD1.js.map +1 -1
- package/build/cjs/prod/instrumentations/worker/instrumentEnv.js +0 -7
- package/build/cjs/prod/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/cjs/prod/instrumentations/worker/instrumentQueueProducer.js +3 -2
- package/build/cjs/prod/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
- package/build/cjs/prod/sdk.js +0 -1
- package/build/cjs/prod/sdk.js.map +1 -1
- package/build/cjs/prod/utils/isBinding.js +0 -4
- package/build/cjs/prod/utils/isBinding.js.map +1 -1
- package/build/cjs/prod/vendor/stacktrace.js +2 -1
- package/build/cjs/prod/vendor/stacktrace.js.map +1 -1
- package/build/cjs/prod/wrapRequestHandlerWithInit.js +2 -1
- package/build/cjs/prod/wrapRequestHandlerWithInit.js.map +1 -1
- package/build/esm/dev/client.js +2 -1
- package/build/esm/dev/client.js.map +1 -1
- package/build/esm/dev/durableobject.js +5 -79
- package/build/esm/dev/durableobject.js.map +1 -1
- package/build/esm/dev/index.js +3 -2
- package/build/esm/dev/index.js.map +1 -1
- package/build/esm/dev/instrumentations/agents/instrumentAgentCallableRpc.js +4 -2
- package/build/esm/dev/instrumentations/agents/instrumentAgentCallableRpc.js.map +1 -1
- package/build/esm/dev/instrumentations/instrumentDurableObjectHandlers.js +121 -0
- package/build/esm/dev/instrumentations/instrumentDurableObjectHandlers.js.map +1 -0
- package/build/esm/dev/instrumentations/instrumentDurableObjectStorage.js +3 -1
- package/build/esm/dev/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
- package/build/esm/dev/instrumentations/instrumentDurableObjectSyncKvStorage.js +3 -1
- package/build/esm/dev/instrumentations/instrumentDurableObjectSyncKvStorage.js.map +1 -1
- package/build/esm/dev/instrumentations/instrumentSqlStorage.js +5 -2
- package/build/esm/dev/instrumentations/instrumentSqlStorage.js.map +1 -1
- package/build/esm/dev/instrumentations/instrumentWorkerEntrypoint.js +2 -1
- package/build/esm/dev/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
- package/build/esm/dev/instrumentations/worker/instrumentD1.js +6 -3
- package/build/esm/dev/instrumentations/worker/instrumentD1.js.map +1 -1
- package/build/esm/dev/instrumentations/worker/instrumentEnv.js +1 -8
- package/build/esm/dev/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/esm/dev/instrumentations/worker/instrumentQueueProducer.js +4 -3
- package/build/esm/dev/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
- package/build/esm/dev/package.json +1 -1
- package/build/esm/dev/sdk.js +0 -1
- package/build/esm/dev/sdk.js.map +1 -1
- package/build/esm/dev/utils/isBinding.js +1 -4
- package/build/esm/dev/utils/isBinding.js.map +1 -1
- package/build/esm/dev/vendor/stacktrace.js +2 -1
- package/build/esm/dev/vendor/stacktrace.js.map +1 -1
- package/build/esm/dev/wrapRequestHandlerWithInit.js +4 -3
- package/build/esm/dev/wrapRequestHandlerWithInit.js.map +1 -1
- package/build/esm/prod/client.js +2 -1
- package/build/esm/prod/client.js.map +1 -1
- package/build/esm/prod/durableobject.js +5 -79
- package/build/esm/prod/durableobject.js.map +1 -1
- package/build/esm/prod/index.js +3 -2
- package/build/esm/prod/index.js.map +1 -1
- package/build/esm/prod/instrumentations/agents/instrumentAgentCallableRpc.js +4 -2
- package/build/esm/prod/instrumentations/agents/instrumentAgentCallableRpc.js.map +1 -1
- package/build/esm/prod/instrumentations/instrumentDurableObjectHandlers.js +121 -0
- package/build/esm/prod/instrumentations/instrumentDurableObjectHandlers.js.map +1 -0
- package/build/esm/prod/instrumentations/instrumentDurableObjectStorage.js +3 -1
- package/build/esm/prod/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
- package/build/esm/prod/instrumentations/instrumentDurableObjectSyncKvStorage.js +3 -1
- package/build/esm/prod/instrumentations/instrumentDurableObjectSyncKvStorage.js.map +1 -1
- package/build/esm/prod/instrumentations/instrumentSqlStorage.js +5 -2
- package/build/esm/prod/instrumentations/instrumentSqlStorage.js.map +1 -1
- package/build/esm/prod/instrumentations/instrumentWorkerEntrypoint.js +2 -1
- package/build/esm/prod/instrumentations/instrumentWorkerEntrypoint.js.map +1 -1
- package/build/esm/prod/instrumentations/worker/instrumentD1.js +6 -3
- package/build/esm/prod/instrumentations/worker/instrumentD1.js.map +1 -1
- package/build/esm/prod/instrumentations/worker/instrumentEnv.js +1 -8
- package/build/esm/prod/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/esm/prod/instrumentations/worker/instrumentQueueProducer.js +4 -3
- package/build/esm/prod/instrumentations/worker/instrumentQueueProducer.js.map +1 -1
- package/build/esm/prod/package.json +1 -1
- package/build/esm/prod/sdk.js +0 -1
- package/build/esm/prod/sdk.js.map +1 -1
- package/build/esm/prod/utils/isBinding.js +1 -4
- package/build/esm/prod/utils/isBinding.js.map +1 -1
- package/build/esm/prod/vendor/stacktrace.js +2 -1
- package/build/esm/prod/vendor/stacktrace.js.map +1 -1
- package/build/esm/prod/wrapRequestHandlerWithInit.js +4 -3
- package/build/esm/prod/wrapRequestHandlerWithInit.js.map +1 -1
- package/build/types/client.d.ts +1 -1
- package/build/types/client.d.ts.map +1 -1
- package/build/types/durableobject.d.ts.map +1 -1
- package/build/types/index.d.ts +3 -2
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instrumentations/agents/instrumentAgentCallableRpc.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentDurableObjectHandlers.d.ts +28 -0
- package/build/types/instrumentations/instrumentDurableObjectHandlers.d.ts.map +1 -0
- package/build/types/instrumentations/instrumentDurableObjectStorage.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentDurableObjectSyncKvStorage.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentSqlStorage.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentWorkerEntrypoint.d.ts.map +1 -1
- package/build/types/instrumentations/worker/instrumentD1.d.ts.map +1 -1
- package/build/types/instrumentations/worker/instrumentEnv.d.ts +0 -1
- package/build/types/instrumentations/worker/instrumentEnv.d.ts.map +1 -1
- package/build/types/instrumentations/worker/instrumentQueueProducer.d.ts.map +1 -1
- package/build/types/utils/isBinding.d.ts +1 -9
- package/build/types/utils/isBinding.d.ts.map +1 -1
- package/build/types/vendor/stacktrace.d.ts.map +1 -1
- package/build/types/wrapRequestHandlerWithInit.d.ts.map +1 -1
- package/package.json +4 -4
- package/build/cjs/dev/instrumentations/worker/instrumentRateLimit.js +0 -34
- package/build/cjs/dev/instrumentations/worker/instrumentRateLimit.js.map +0 -1
- package/build/cjs/prod/instrumentations/worker/instrumentRateLimit.js +0 -34
- package/build/cjs/prod/instrumentations/worker/instrumentRateLimit.js.map +0 -1
- package/build/esm/dev/instrumentations/worker/instrumentRateLimit.js +0 -32
- package/build/esm/dev/instrumentations/worker/instrumentRateLimit.js.map +0 -1
- package/build/esm/prod/instrumentations/worker/instrumentRateLimit.js +0 -32
- package/build/esm/prod/instrumentations/worker/instrumentRateLimit.js.map +0 -1
- package/build/types/instrumentations/worker/instrumentRateLimit.d.ts +0 -6
- package/build/types/instrumentations/worker/instrumentRateLimit.d.ts.map +0 -1
package/build/cjs/dev/client.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
|
+
const server = require('@sentry/core/server');
|
|
4
5
|
const debugBuild = require('./debug-build.js');
|
|
5
6
|
const invocationContext = require('./utils/invocationContext.js');
|
|
6
7
|
|
|
7
|
-
class CloudflareClient extends
|
|
8
|
+
class CloudflareClient extends server.ServerRuntimeClient {
|
|
8
9
|
/**
|
|
9
10
|
* Creates a new Cloudflare SDK instance.
|
|
10
11
|
* @param options Configuration options for this SDK.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sources":["../../../src/client.ts"],"sourcesContent":["import type { ClientOptions, Options, ServerRuntimeClientOptions, TracePropagationTargets } from '@sentry/core';\nimport {\n _INTERNAL_clearAiProviderSkips,\n _INTERNAL_flushLogsBuffer,\n _INTERNAL_flushMetricsBuffer,\n applySdkMetadata,\n debug,\n ServerRuntimeClient,\n spanIsSampled,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport type { ExecutionContextCompat } from './executionContext';\nimport type { makeFlushLock } from './flush';\nimport type { CloudflareTransportOptions } from './transport';\nimport { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext';\n\n/**\n * The Sentry Cloudflare SDK Client.\n *\n * @see CloudflareClientOptions for documentation on configuration options.\n * @see ServerRuntimeClient for usage documentation.\n */\nexport class CloudflareClient extends ServerRuntimeClient {\n private readonly _flushLock: ReturnType<typeof makeFlushLock> | void;\n private _pendingSpans: Set<string> = new Set();\n private _spanCompletionPromise: Promise<void> | null = null;\n private _resolveSpanCompletion: (() => void) | null = null;\n\n private _unsubscribeSpanStart: (() => void) | null = null;\n private _unsubscribeSpanEnd: (() => void) | null = null;\n\n // True while a boundary `flush()` is draining; envelopes created by that drain ride it\n // and must not each start their own eager transport flush.\n private _inBoundaryFlush = false;\n\n /**\n * Whether this client is a cached, cross-invocation client (`cacheClient`).\n * Cached clients are never disposed at an invocation boundary, so their spans/events\n * are delivered eagerly instead of waiting for a per-invocation flush.\n */\n public readonly isCachedClient: boolean;\n\n /**\n * Creates a new Cloudflare SDK instance.\n * @param options Configuration options for this SDK.\n */\n public constructor(options: CloudflareClientOptions) {\n applySdkMetadata(options, 'cloudflare');\n options._metadata = options._metadata || {};\n const { flushLock, ...serverOptions } = options;\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...serverOptions,\n platform: 'javascript',\n // TODO: Grab version information\n runtime: { name: 'cloudflare' },\n // TODO: Add server name\n _flushInterval: 0,\n };\n\n super(clientOptions);\n this._flushLock = flushLock;\n this.isCachedClient = options.cacheClient === true;\n\n // Track span lifecycle to know when to flush. Skipped for cached clients\n // (`cacheClient`): they are never disposed, so spans that end after\n // a flush are still delivered. Per-invocation clients are disposed right after\n // the boundary flush, so the flush must wait for open spans to end otherwise\n // their transaction never gets emitted.\n if (!this.isCachedClient) {\n this._unsubscribeSpanStart = this.on('spanStart', span => {\n const spanId = span.spanContext().spanId;\n DEBUG_BUILD && debug.log('[CloudflareClient] Span started:', spanId);\n\n // Negatively sampled spans never emit spanEnd,\n // so tracking them would cause _pendingSpans to grow unboundedly.\n // We should fix the inconsistent behavior for NonRecordingSpans in the future but\n // for now, we just ignore them.\n if (!spanIsSampled(span)) {\n return;\n }\n\n this._pendingSpans.add(spanId);\n\n if (!this._spanCompletionPromise) {\n this._spanCompletionPromise = new Promise(resolve => {\n this._resolveSpanCompletion = resolve;\n });\n }\n });\n\n this._unsubscribeSpanEnd = this.on('spanEnd', span => {\n const spanId = span.spanContext().spanId;\n DEBUG_BUILD && debug.log('[CloudflareClient] Span ended:', spanId);\n this._pendingSpans.delete(spanId);\n\n // If no more pending spans, resolve the completion promise\n if (this._pendingSpans.size === 0 && this._resolveSpanCompletion) {\n DEBUG_BUILD && debug.log('[CloudflareClient] All spans completed, preparing to flush');\n this._resolveSpanCompletion();\n this._resetSpanCompletionPromise();\n }\n });\n }\n }\n\n /**\n * Flushes pending operations and ensures all data is processed.\n * If a timeout is provided, the operation will be completed within the specified time limit.\n *\n * It will wait for all pending spans to complete before flushing.\n *\n * @param {number} [timeout] - Optional timeout in milliseconds to force the completion of the flush operation.\n * @return {Promise<boolean>} A promise that resolves to a boolean indicating whether the flush operation was successful.\n */\n public async flush(timeout?: number): Promise<boolean> {\n // Wait for user waitUntil-registered work to settle before draining, so events\n // captured in that work are still in the buffer. Without this the final flush\n // can drain (and the client be disposed) before background captures land.\n if (this._flushLock) {\n await this._flushLock.finalize();\n }\n\n if (this._pendingSpans.size > 0 && this._spanCompletionPromise) {\n DEBUG_BUILD &&\n debug.log('[CloudflareClient] Waiting for', this._pendingSpans.size, 'pending spans to complete...');\n\n const timeoutMs = timeout ?? 5000;\n const spanCompletionRace = Promise.race([\n this._spanCompletionPromise,\n new Promise(resolve =>\n setTimeout(() => {\n DEBUG_BUILD &&\n debug.log('[CloudflareClient] Span completion timeout after', timeoutMs, 'ms, flushing anyway');\n resolve(undefined);\n }, timeoutMs),\n ),\n ]);\n\n await spanCompletionRace;\n }\n\n // Envelopes created while this flush drains (log/metric/span buffers turning into\n // envelopes on the `flush` emit) ride its own transport drain; without the flag each\n // of them would also start an eager drain and a `waitUntil` registration.\n this._inBoundaryFlush = true;\n try {\n return await super.flush(timeout);\n } finally {\n this._inBoundaryFlush = false;\n }\n }\n\n /**\n * Disposes of the client and releases all resources.\n *\n * This method clears all Cloudflare-specific state in addition to the base client cleanup.\n * It unsubscribes from span lifecycle events and clears pending span tracking.\n *\n * Call this method after flushing to allow the client to be garbage collected.\n * After calling dispose(), the client should not be used anymore.\n */\n public override dispose(): void {\n DEBUG_BUILD && debug.log('[CloudflareClient] Disposing client...');\n\n super.dispose();\n\n if (this._unsubscribeSpanStart) {\n this._unsubscribeSpanStart();\n this._unsubscribeSpanStart = null;\n }\n if (this._unsubscribeSpanEnd) {\n this._unsubscribeSpanEnd();\n this._unsubscribeSpanEnd = null;\n }\n\n this._resetSpanCompletionPromise();\n (this as unknown as { _flushLock: ReturnType<typeof makeFlushLock> | void })._flushLock = undefined;\n }\n\n /** @inheritDoc */\n protected override _setupIntegrations(): void {\n // Clear AI provider skip registrations before setting up integrations.\n // The registry is module-global and Cloudflare calls `init()` per request, so without this a\n // single `ai` SDK call would suppress direct `env.AI.run` spans for the rest of the isolate's\n // life. Mirrors the same reset in the Node client.\n _INTERNAL_clearAiProviderSkips();\n super._setupIntegrations();\n\n // Registered after the integrations on purpose: the flush-point marker must run\n // after core and the span buffer have turned their buffers into envelopes on the\n // same `flush` emit (so those envelopes ride the boundary drain instead of starting\n // eager ones), and the eager span handler relies on `spanStreamingIntegration`\n // having already buffered the span that triggers it.\n if (this.isCachedClient) {\n // Marks the invocation's natural flush point: anything captured from now on\n // (post-response `waitUntil` work, detached continuations) has no later flush\n // to ride and is delivered eagerly by the hooks below.\n this.on('flush', () => {\n const invocationState = getInvocationState();\n if (invocationState) {\n invocationState.flushPointReached = true;\n }\n });\n this._setupEagerEnvelopeDelivery();\n this._setupEagerBufferDelivery();\n }\n }\n\n /**\n * Resets the span completion promise and resolve function.\n */\n private _resetSpanCompletionPromise(): void {\n this._pendingSpans.clear();\n this._spanCompletionPromise = null;\n this._resolveSpanCompletion = null;\n }\n\n /**\n * Drains the transport after an envelope has been accepted past the invocation's\n * flush point. The transport queues request producers until `flush()`; before the\n * flush point the boundary `flush()` drains everything, but envelopes created after\n * it (post-response `waitUntil` work, detached continuations) have no later flush to\n * ride. The drain is registered with the invocation's `waitUntil` to keep the fetch\n * alive; outside any instrumented invocation it always runs.\n */\n private _setupEagerEnvelopeDelivery(): void {\n this.on('afterEnvelope', () => {\n const transport = this.getTransport();\n const invocationState = getInvocationState();\n\n if (!transport || this._inBoundaryFlush || (invocationState && !invocationState.flushPointReached)) {\n return;\n }\n\n this._registerWithInvocationWaitUntil(transport.flush(2000));\n });\n }\n\n /**\n * Turns spans, logs and metrics captured past the invocation's flush point into\n * envelopes. Before the flush point the boundary `flush()` drains their buffers; after\n * it (or outside any instrumented invocation) nothing else would: the log/metric idle\n * timer is disabled for this runtime (`_flushInterval: 0`) and the span buffer's own 5s\n * timer fires outside any invocation, where the runtime suspends the send. Each capture\n * drains only its own bucket (the ended span's trace, the log buffer, the metric\n * buffer), so a fan-out of concurrent traces stays one envelope per trace. RPC method\n * spans never reach this path: `wrapMethodWithSentry` runs the boundary flush after the\n * method span has ended, so only work past that (e.g. detached continuations) lands here.\n */\n private _setupEagerBufferDelivery(): void {\n this.on('afterSpanEnd', span => {\n // The trace id must come from the span, not the current scope: `continueTrace`\n // writes the propagation context to the *current* scope, so the forked\n // isolation scope's propagation context carries a different trace id and\n // flushing by it silently no-ops.\n const traceId = span.spanContext().traceId;\n this._eagerDrain(() => this.emit('flushTraceSpans', traceId));\n });\n this.on('afterCaptureLog', () => this._eagerDrain(() => _INTERNAL_flushLogsBuffer(this)));\n this.on('afterCaptureMetric', () => this._eagerDrain(() => _INTERNAL_flushMetricsBuffer(this)));\n }\n\n /**\n * Runs `drain` unless the owning invocation has not reached its flush point yet\n * (before it the boundary `flush()` delivers the buffers).\n */\n private _eagerDrain(drain: () => void): void {\n const invocationState = getInvocationState();\n\n if (invocationState && !invocationState.flushPointReached) {\n return;\n }\n\n drain();\n }\n\n /**\n * Attaches a promise to the `waitUntil` of the invocation that owns the current\n * async context, so the runtime keeps the send alive after the response is returned.\n * Outside any instrumented invocation (or where the context has no `waitUntil`,\n * e.g. Astro prerendering) the send is fire-and-forget.\n */\n private _registerWithInvocationWaitUntil(promise: PromiseLike<unknown>): void {\n const invocationState = getInvocationState();\n const waitUntil = invocationState && getInvocationWaitUntil(invocationState);\n if (!waitUntil) {\n return;\n }\n\n try {\n waitUntil(\n Promise.resolve(promise).then(\n () => undefined,\n () => undefined,\n ),\n );\n } catch {\n // The owning invocation already ended; the send races isolate teardown either way.\n }\n }\n}\n\ninterface BaseCloudflareOptions {\n /**\n * @ignore Used internally to disable the deDupeIntegration for workflows.\n * @hidden Used internally to disable the deDupeIntegration for workflows.\n * @default true\n */\n enableDedupe?: boolean;\n\n /**\n * The Cloudflare SDK is not OpenTelemetry native. By default (`false`) it does not set up a tracer\n * provider; spans are emitted via the SDK's own instrumentation and scopes are isolated with\n * AsyncLocalStorage.\n *\n * Set this to `true` to opt into the OpenTelemetry compatibility tracer, which captures spans\n * emitted via `@opentelemetry/api`. Big caveat: it does not handle custom context, always working\n * off the current scope. This is good enough for many, but not all, integrations.\n *\n * @default false\n */\n enableOpenTelemetrySetup?: boolean;\n\n /**\n * The bindings on `env` that outgoing RPC calls propagate trace context to.\n *\n * Strings match a binding name exactly, regular expressions match by pattern. An empty array\n * (the default) propagates to nothing.\n *\n * RPC has no headers to carry trace context, so the SDK appends it as a trailing argument to\n * every RPC method call on a matching binding. Only a Sentry-instrumented receiver strips that\n * argument again. Anywhere else it arrives as a real argument and changes what the method was\n * called with, so list only the bindings whose receiver you know runs Sentry.\n *\n * Propagation over `stub.fetch()` and service binding `fetch()` uses HTTP headers and is not\n * affected by this option.\n *\n * Strings match a binding name exactly, regular expressions match by pattern. Both match\n * case-insensitively.\n *\n * When you build with the Sentry Cloudflare Vite plugin, bindings that resolve to *this* worker\n * (its own Durable Objects, its self service bindings) are added for you, because the plugin\n * instruments those receivers itself. Whatever you list here is added on top of them.\n *\n * @default []\n * @example\n * ```ts\n * // Propagate to `env.ORDERS` and every `env.SVC_*` binding\n * export default Sentry.withSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * rpcTracePropagationBindings: ['ORDERS', /^SVC_/],\n * }),\n * handler,\n * );\n * ```\n */\n rpcTracePropagationBindings?: TracePropagationTargets;\n\n /**\n * Table names that should stay instrumented even though they match the reserved `cf_` prefix used\n * by Durable Object frameworks (`agents`, `partyserver`, ...) for their internal SQLite tables.\n *\n * By default, `exec` queries against `cf_`-prefixed tables are treated as framework noise and no\n * `db.query` span is created for them. If one of your own tables happens to use this prefix, add it\n * here to opt it back into instrumentation. Entries are matched against each table name in the\n * query summary — strings must match exactly, while regular expressions give you prefix/pattern\n * matching.\n *\n * @default []\n * @example\n * ```ts\n * export default Sentry.withSentry(\n * (env) => ({\n * dsn: env.SENTRY_DSN,\n * durableObjectSqlSpanAllowlist: ['cf_my_table', /^cf_reports_/],\n * }),\n * handler,\n * );\n * ```\n */\n durableObjectSqlSpanAllowlist?: Array<string | RegExp>;\n\n /**\n * KV keys that should stay instrumented even though they match a reserved prefix used by Durable\n * Object frameworks (`agents`, `partyserver`, ...) for their internal storage entries.\n *\n * By default, KV reads/writes (`get`, `put`, `delete`, `list`) of `cf_`- or `__ps_`-prefixed keys\n * are treated as framework noise and no `durable_object_storage_*` span is created for them,\n * mirroring how `cf_`-prefixed SQL tables are handled (see {@link durableObjectSqlSpanAllowlist}).\n * If one of your own keys happens to use such a prefix, add it here to opt it back into\n * instrumentation. Strings must match exactly, while regular expressions give you prefix/pattern\n * matching.\n *\n * @default []\n * @example\n * ```ts\n * export default Sentry.withSentry(\n * (env) => ({\n * dsn: env.SENTRY_DSN,\n * durableObjectStorageSpanAllowlist: ['cf_my_key', /^cf_reports_/],\n * }),\n * handler,\n * );\n * ```\n */\n durableObjectStorageSpanAllowlist?: Array<string | RegExp>;\n\n /**\n * Sets an optional server name (device name).\n *\n * This is useful for identifying which server or instance is sending events.\n */\n serverName?: string;\n\n /**\n * If you use Spotlight by Sentry during development, use\n * this option to forward captured Sentry events to Spotlight.\n *\n * Either set it to true, or provide a specific Spotlight Sidecar URL.\n *\n * More details: https://spotlightjs.com/\n *\n * IMPORTANT: Only set this option to `true` while developing, not in production!\n */\n spotlight?: boolean | string;\n\n /**\n * Cache the client and reuse it across invocations within the same isolate.\n *\n * The SDK creates one client per isolate and reuses it for all requests/DO\n * handlers in that isolate. This avoids the per-invocation cost of\n * constructing a new client.\n *\n * Since a cached client outlives any single invocation, data captured after an\n * invocation's flush point (post-response `waitUntil` work, detached background\n * work) is delivered eagerly instead of waiting for a flush that never comes.\n *\n * The first `init()` in an isolate decides the cached client's options; later\n * `init()` calls with different options (e.g. another DSN) reuse the cached client\n * unchanged (a debug warning is logged for a DSN change). Use `cacheClient: false`\n * when options must differ per invocation.\n *\n * When disabled, a new client is created per invocation and disposed after the\n * handler completes.\n *\n * @default true\n */\n cacheClient?: boolean;\n}\n\n/**\n * Configuration options for the Sentry Cloudflare SDK\n *\n * @see @sentry/core Options for more information.\n */\nexport interface CloudflareOptions extends Options<CloudflareTransportOptions>, BaseCloudflareOptions {\n ctx?: ExecutionContextCompat;\n}\n\n/**\n * Configuration options for the Sentry Cloudflare SDK Client class\n *\n * @see CloudflareClient for more information.\n */\nexport interface CloudflareClientOptions extends ClientOptions<CloudflareTransportOptions>, BaseCloudflareOptions {\n flushLock?: ReturnType<typeof makeFlushLock>;\n}\n"],"names":["ServerRuntimeClient","applySdkMetadata","DEBUG_BUILD","debug","spanIsSampled","_INTERNAL_clearAiProviderSkips","getInvocationState","_INTERNAL_flushLogsBuffer","_INTERNAL_flushMetricsBuffer","getInvocationWaitUntil"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../../../src/client.ts"],"sourcesContent":["import type { ClientOptions, Options, TracePropagationTargets } from '@sentry/core';\nimport {\n _INTERNAL_clearAiProviderSkips,\n _INTERNAL_flushLogsBuffer,\n _INTERNAL_flushMetricsBuffer,\n applySdkMetadata,\n debug,\n spanIsSampled,\n} from '@sentry/core';\nimport type { ServerRuntimeClientOptions } from '@sentry/core/server';\nimport { ServerRuntimeClient } from '@sentry/core/server';\nimport { DEBUG_BUILD } from './debug-build';\nimport type { ExecutionContextCompat } from './executionContext';\nimport type { makeFlushLock } from './flush';\nimport type { CloudflareTransportOptions } from './transport';\nimport { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext';\n\n/**\n * The Sentry Cloudflare SDK Client.\n *\n * @see CloudflareClientOptions for documentation on configuration options.\n * @see ServerRuntimeClient for usage documentation.\n */\nexport class CloudflareClient extends ServerRuntimeClient {\n private readonly _flushLock: ReturnType<typeof makeFlushLock> | void;\n private _pendingSpans: Set<string> = new Set();\n private _spanCompletionPromise: Promise<void> | null = null;\n private _resolveSpanCompletion: (() => void) | null = null;\n\n private _unsubscribeSpanStart: (() => void) | null = null;\n private _unsubscribeSpanEnd: (() => void) | null = null;\n\n // True while a boundary `flush()` is draining; envelopes created by that drain ride it\n // and must not each start their own eager transport flush.\n private _inBoundaryFlush = false;\n\n /**\n * Whether this client is a cached, cross-invocation client (`cacheClient`).\n * Cached clients are never disposed at an invocation boundary, so their spans/events\n * are delivered eagerly instead of waiting for a per-invocation flush.\n */\n public readonly isCachedClient: boolean;\n\n /**\n * Creates a new Cloudflare SDK instance.\n * @param options Configuration options for this SDK.\n */\n public constructor(options: CloudflareClientOptions) {\n applySdkMetadata(options, 'cloudflare');\n options._metadata = options._metadata || {};\n const { flushLock, ...serverOptions } = options;\n\n const clientOptions: ServerRuntimeClientOptions = {\n ...serverOptions,\n platform: 'javascript',\n // TODO: Grab version information\n runtime: { name: 'cloudflare' },\n // TODO: Add server name\n _flushInterval: 0,\n };\n\n super(clientOptions);\n this._flushLock = flushLock;\n this.isCachedClient = options.cacheClient === true;\n\n // Track span lifecycle to know when to flush. Skipped for cached clients\n // (`cacheClient`): they are never disposed, so spans that end after\n // a flush are still delivered. Per-invocation clients are disposed right after\n // the boundary flush, so the flush must wait for open spans to end otherwise\n // their transaction never gets emitted.\n if (!this.isCachedClient) {\n this._unsubscribeSpanStart = this.on('spanStart', span => {\n const spanId = span.spanContext().spanId;\n DEBUG_BUILD && debug.log('[CloudflareClient] Span started:', spanId);\n\n // Negatively sampled spans never emit spanEnd,\n // so tracking them would cause _pendingSpans to grow unboundedly.\n // We should fix the inconsistent behavior for NonRecordingSpans in the future but\n // for now, we just ignore them.\n if (!spanIsSampled(span)) {\n return;\n }\n\n this._pendingSpans.add(spanId);\n\n if (!this._spanCompletionPromise) {\n this._spanCompletionPromise = new Promise(resolve => {\n this._resolveSpanCompletion = resolve;\n });\n }\n });\n\n this._unsubscribeSpanEnd = this.on('spanEnd', span => {\n const spanId = span.spanContext().spanId;\n DEBUG_BUILD && debug.log('[CloudflareClient] Span ended:', spanId);\n this._pendingSpans.delete(spanId);\n\n // If no more pending spans, resolve the completion promise\n if (this._pendingSpans.size === 0 && this._resolveSpanCompletion) {\n DEBUG_BUILD && debug.log('[CloudflareClient] All spans completed, preparing to flush');\n this._resolveSpanCompletion();\n this._resetSpanCompletionPromise();\n }\n });\n }\n }\n\n /**\n * Flushes pending operations and ensures all data is processed.\n * If a timeout is provided, the operation will be completed within the specified time limit.\n *\n * It will wait for all pending spans to complete before flushing.\n *\n * @param {number} [timeout] - Optional timeout in milliseconds to force the completion of the flush operation.\n * @return {Promise<boolean>} A promise that resolves to a boolean indicating whether the flush operation was successful.\n */\n public async flush(timeout?: number): Promise<boolean> {\n // Wait for user waitUntil-registered work to settle before draining, so events\n // captured in that work are still in the buffer. Without this the final flush\n // can drain (and the client be disposed) before background captures land.\n if (this._flushLock) {\n await this._flushLock.finalize();\n }\n\n if (this._pendingSpans.size > 0 && this._spanCompletionPromise) {\n DEBUG_BUILD &&\n debug.log('[CloudflareClient] Waiting for', this._pendingSpans.size, 'pending spans to complete...');\n\n const timeoutMs = timeout ?? 5000;\n const spanCompletionRace = Promise.race([\n this._spanCompletionPromise,\n new Promise(resolve =>\n setTimeout(() => {\n DEBUG_BUILD &&\n debug.log('[CloudflareClient] Span completion timeout after', timeoutMs, 'ms, flushing anyway');\n resolve(undefined);\n }, timeoutMs),\n ),\n ]);\n\n await spanCompletionRace;\n }\n\n // Envelopes created while this flush drains (log/metric/span buffers turning into\n // envelopes on the `flush` emit) ride its own transport drain; without the flag each\n // of them would also start an eager drain and a `waitUntil` registration.\n this._inBoundaryFlush = true;\n try {\n return await super.flush(timeout);\n } finally {\n this._inBoundaryFlush = false;\n }\n }\n\n /**\n * Disposes of the client and releases all resources.\n *\n * This method clears all Cloudflare-specific state in addition to the base client cleanup.\n * It unsubscribes from span lifecycle events and clears pending span tracking.\n *\n * Call this method after flushing to allow the client to be garbage collected.\n * After calling dispose(), the client should not be used anymore.\n */\n public override dispose(): void {\n DEBUG_BUILD && debug.log('[CloudflareClient] Disposing client...');\n\n super.dispose();\n\n if (this._unsubscribeSpanStart) {\n this._unsubscribeSpanStart();\n this._unsubscribeSpanStart = null;\n }\n if (this._unsubscribeSpanEnd) {\n this._unsubscribeSpanEnd();\n this._unsubscribeSpanEnd = null;\n }\n\n this._resetSpanCompletionPromise();\n (this as unknown as { _flushLock: ReturnType<typeof makeFlushLock> | void })._flushLock = undefined;\n }\n\n /** @inheritDoc */\n protected override _setupIntegrations(): void {\n // Clear AI provider skip registrations before setting up integrations.\n // The registry is module-global and Cloudflare calls `init()` per request, so without this a\n // single `ai` SDK call would suppress direct `env.AI.run` spans for the rest of the isolate's\n // life. Mirrors the same reset in the Node client.\n _INTERNAL_clearAiProviderSkips();\n super._setupIntegrations();\n\n // Registered after the integrations on purpose: the flush-point marker must run\n // after core and the span buffer have turned their buffers into envelopes on the\n // same `flush` emit (so those envelopes ride the boundary drain instead of starting\n // eager ones), and the eager span handler relies on `spanStreamingIntegration`\n // having already buffered the span that triggers it.\n if (this.isCachedClient) {\n // Marks the invocation's natural flush point: anything captured from now on\n // (post-response `waitUntil` work, detached continuations) has no later flush\n // to ride and is delivered eagerly by the hooks below.\n this.on('flush', () => {\n const invocationState = getInvocationState();\n if (invocationState) {\n invocationState.flushPointReached = true;\n }\n });\n this._setupEagerEnvelopeDelivery();\n this._setupEagerBufferDelivery();\n }\n }\n\n /**\n * Resets the span completion promise and resolve function.\n */\n private _resetSpanCompletionPromise(): void {\n this._pendingSpans.clear();\n this._spanCompletionPromise = null;\n this._resolveSpanCompletion = null;\n }\n\n /**\n * Drains the transport after an envelope has been accepted past the invocation's\n * flush point. The transport queues request producers until `flush()`; before the\n * flush point the boundary `flush()` drains everything, but envelopes created after\n * it (post-response `waitUntil` work, detached continuations) have no later flush to\n * ride. The drain is registered with the invocation's `waitUntil` to keep the fetch\n * alive; outside any instrumented invocation it always runs.\n */\n private _setupEagerEnvelopeDelivery(): void {\n this.on('afterEnvelope', () => {\n const transport = this.getTransport();\n const invocationState = getInvocationState();\n\n if (!transport || this._inBoundaryFlush || (invocationState && !invocationState.flushPointReached)) {\n return;\n }\n\n this._registerWithInvocationWaitUntil(transport.flush(2000));\n });\n }\n\n /**\n * Turns spans, logs and metrics captured past the invocation's flush point into\n * envelopes. Before the flush point the boundary `flush()` drains their buffers; after\n * it (or outside any instrumented invocation) nothing else would: the log/metric idle\n * timer is disabled for this runtime (`_flushInterval: 0`) and the span buffer's own 5s\n * timer fires outside any invocation, where the runtime suspends the send. Each capture\n * drains only its own bucket (the ended span's trace, the log buffer, the metric\n * buffer), so a fan-out of concurrent traces stays one envelope per trace. RPC method\n * spans never reach this path: `wrapMethodWithSentry` runs the boundary flush after the\n * method span has ended, so only work past that (e.g. detached continuations) lands here.\n */\n private _setupEagerBufferDelivery(): void {\n this.on('afterSpanEnd', span => {\n // The trace id must come from the span, not the current scope: `continueTrace`\n // writes the propagation context to the *current* scope, so the forked\n // isolation scope's propagation context carries a different trace id and\n // flushing by it silently no-ops.\n const traceId = span.spanContext().traceId;\n this._eagerDrain(() => this.emit('flushTraceSpans', traceId));\n });\n this.on('afterCaptureLog', () => this._eagerDrain(() => _INTERNAL_flushLogsBuffer(this)));\n this.on('afterCaptureMetric', () => this._eagerDrain(() => _INTERNAL_flushMetricsBuffer(this)));\n }\n\n /**\n * Runs `drain` unless the owning invocation has not reached its flush point yet\n * (before it the boundary `flush()` delivers the buffers).\n */\n private _eagerDrain(drain: () => void): void {\n const invocationState = getInvocationState();\n\n if (invocationState && !invocationState.flushPointReached) {\n return;\n }\n\n drain();\n }\n\n /**\n * Attaches a promise to the `waitUntil` of the invocation that owns the current\n * async context, so the runtime keeps the send alive after the response is returned.\n * Outside any instrumented invocation (or where the context has no `waitUntil`,\n * e.g. Astro prerendering) the send is fire-and-forget.\n */\n private _registerWithInvocationWaitUntil(promise: PromiseLike<unknown>): void {\n const invocationState = getInvocationState();\n const waitUntil = invocationState && getInvocationWaitUntil(invocationState);\n if (!waitUntil) {\n return;\n }\n\n try {\n waitUntil(\n Promise.resolve(promise).then(\n () => undefined,\n () => undefined,\n ),\n );\n } catch {\n // The owning invocation already ended; the send races isolate teardown either way.\n }\n }\n}\n\ninterface BaseCloudflareOptions {\n /**\n * @ignore Used internally to disable the deDupeIntegration for workflows.\n * @hidden Used internally to disable the deDupeIntegration for workflows.\n * @default true\n */\n enableDedupe?: boolean;\n\n /**\n * The Cloudflare SDK is not OpenTelemetry native. By default (`false`) it does not set up a tracer\n * provider; spans are emitted via the SDK's own instrumentation and scopes are isolated with\n * AsyncLocalStorage.\n *\n * Set this to `true` to opt into the OpenTelemetry compatibility tracer, which captures spans\n * emitted via `@opentelemetry/api`. Big caveat: it does not handle custom context, always working\n * off the current scope. This is good enough for many, but not all, integrations.\n *\n * @default false\n */\n enableOpenTelemetrySetup?: boolean;\n\n /**\n * The bindings on `env` that outgoing RPC calls propagate trace context to.\n *\n * Strings match a binding name exactly, regular expressions match by pattern. An empty array\n * (the default) propagates to nothing.\n *\n * RPC has no headers to carry trace context, so the SDK appends it as a trailing argument to\n * every RPC method call on a matching binding. Only a Sentry-instrumented receiver strips that\n * argument again. Anywhere else it arrives as a real argument and changes what the method was\n * called with, so list only the bindings whose receiver you know runs Sentry.\n *\n * Propagation over `stub.fetch()` and service binding `fetch()` uses HTTP headers and is not\n * affected by this option.\n *\n * Strings match a binding name exactly, regular expressions match by pattern. Both match\n * case-insensitively.\n *\n * When you build with the Sentry Cloudflare Vite plugin, bindings that resolve to *this* worker\n * (its own Durable Objects, its self service bindings) are added for you, because the plugin\n * instruments those receivers itself. Whatever you list here is added on top of them.\n *\n * @default []\n * @example\n * ```ts\n * // Propagate to `env.ORDERS` and every `env.SVC_*` binding\n * export default Sentry.withSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * rpcTracePropagationBindings: ['ORDERS', /^SVC_/],\n * }),\n * handler,\n * );\n * ```\n */\n rpcTracePropagationBindings?: TracePropagationTargets;\n\n /**\n * Table names that should stay instrumented even though they match the reserved `cf_` prefix used\n * by Durable Object frameworks (`agents`, `partyserver`, ...) for their internal SQLite tables.\n *\n * By default, `exec` queries against `cf_`-prefixed tables are treated as framework noise and no\n * `db.query` span is created for them. If one of your own tables happens to use this prefix, add it\n * here to opt it back into instrumentation. Entries are matched against each table name in the\n * query summary — strings must match exactly, while regular expressions give you prefix/pattern\n * matching.\n *\n * @default []\n * @example\n * ```ts\n * export default Sentry.withSentry(\n * (env) => ({\n * dsn: env.SENTRY_DSN,\n * durableObjectSqlSpanAllowlist: ['cf_my_table', /^cf_reports_/],\n * }),\n * handler,\n * );\n * ```\n */\n durableObjectSqlSpanAllowlist?: Array<string | RegExp>;\n\n /**\n * KV keys that should stay instrumented even though they match a reserved prefix used by Durable\n * Object frameworks (`agents`, `partyserver`, ...) for their internal storage entries.\n *\n * By default, KV reads/writes (`get`, `put`, `delete`, `list`) of `cf_`- or `__ps_`-prefixed keys\n * are treated as framework noise and no `durable_object_storage_*` span is created for them,\n * mirroring how `cf_`-prefixed SQL tables are handled (see {@link durableObjectSqlSpanAllowlist}).\n * If one of your own keys happens to use such a prefix, add it here to opt it back into\n * instrumentation. Strings must match exactly, while regular expressions give you prefix/pattern\n * matching.\n *\n * @default []\n * @example\n * ```ts\n * export default Sentry.withSentry(\n * (env) => ({\n * dsn: env.SENTRY_DSN,\n * durableObjectStorageSpanAllowlist: ['cf_my_key', /^cf_reports_/],\n * }),\n * handler,\n * );\n * ```\n */\n durableObjectStorageSpanAllowlist?: Array<string | RegExp>;\n\n /**\n * Sets an optional server name (device name).\n *\n * This is useful for identifying which server or instance is sending events.\n */\n serverName?: string;\n\n /**\n * If you use Spotlight by Sentry during development, use\n * this option to forward captured Sentry events to Spotlight.\n *\n * Either set it to true, or provide a specific Spotlight Sidecar URL.\n *\n * More details: https://spotlightjs.com/\n *\n * IMPORTANT: Only set this option to `true` while developing, not in production!\n */\n spotlight?: boolean | string;\n\n /**\n * Cache the client and reuse it across invocations within the same isolate.\n *\n * The SDK creates one client per isolate and reuses it for all requests/DO\n * handlers in that isolate. This avoids the per-invocation cost of\n * constructing a new client.\n *\n * Since a cached client outlives any single invocation, data captured after an\n * invocation's flush point (post-response `waitUntil` work, detached background\n * work) is delivered eagerly instead of waiting for a flush that never comes.\n *\n * The first `init()` in an isolate decides the cached client's options; later\n * `init()` calls with different options (e.g. another DSN) reuse the cached client\n * unchanged (a debug warning is logged for a DSN change). Use `cacheClient: false`\n * when options must differ per invocation.\n *\n * When disabled, a new client is created per invocation and disposed after the\n * handler completes.\n *\n * @default true\n */\n cacheClient?: boolean;\n}\n\n/**\n * Configuration options for the Sentry Cloudflare SDK\n *\n * @see @sentry/core Options for more information.\n */\nexport interface CloudflareOptions extends Options<CloudflareTransportOptions>, BaseCloudflareOptions {\n ctx?: ExecutionContextCompat;\n}\n\n/**\n * Configuration options for the Sentry Cloudflare SDK Client class\n *\n * @see CloudflareClient for more information.\n */\nexport interface CloudflareClientOptions extends ClientOptions<CloudflareTransportOptions>, BaseCloudflareOptions {\n flushLock?: ReturnType<typeof makeFlushLock>;\n}\n"],"names":["ServerRuntimeClient","applySdkMetadata","DEBUG_BUILD","debug","spanIsSampled","_INTERNAL_clearAiProviderSkips","getInvocationState","_INTERNAL_flushLogsBuffer","_INTERNAL_flushMetricsBuffer","getInvocationWaitUntil"],"mappings":"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"}
|
|
@@ -4,10 +4,9 @@ const op = require('@sentry/conventions/op');
|
|
|
4
4
|
const core = require('@sentry/core');
|
|
5
5
|
const noDiagnosticChannels = require('@sentry/server-utils/no-diagnostic-channels');
|
|
6
6
|
const instrument = require('./instrument.js');
|
|
7
|
+
const instrumentDurableObjectHandlers = require('./instrumentations/instrumentDurableObjectHandlers.js');
|
|
7
8
|
const instrumentEnv = require('./instrumentations/worker/instrumentEnv.js');
|
|
8
9
|
const options = require('./options.js');
|
|
9
|
-
const wrapRequestHandlerWithInit = require('./wrapRequestHandlerWithInit.js');
|
|
10
|
-
const sdk = require('./sdk.js');
|
|
11
10
|
const instrumentContext = require('./utils/instrumentContext.js');
|
|
12
11
|
const rpcMeta = require('./utils/rpcMeta.js');
|
|
13
12
|
const index = require('./instrumentations/agents/index.js');
|
|
@@ -28,7 +27,7 @@ function constructInstrumentedDurableObject(target, ctx, env, newTarget, options
|
|
|
28
27
|
methodsBeforeConstruction,
|
|
29
28
|
cachedFrameworkManagedMethods
|
|
30
29
|
);
|
|
31
|
-
instrumentDurableObjectHandlers(obj, options$1, context);
|
|
30
|
+
instrumentDurableObjectHandlers.instrumentDurableObjectHandlers(obj, options$1, context);
|
|
32
31
|
return { obj, options: options$1, context, frameworkManagedMethods };
|
|
33
32
|
}
|
|
34
33
|
const frameworkManagedMethodsCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -62,79 +61,6 @@ function resolveFrameworkManagedMethods(prototype, obj, methodsBeforeConstructio
|
|
|
62
61
|
frameworkManagedMethodsCache.set(prototype, managed);
|
|
63
62
|
return managed;
|
|
64
63
|
}
|
|
65
|
-
function instrumentDurableObjectHandlers(obj, options, context) {
|
|
66
|
-
if (obj.fetch && typeof obj.fetch === "function") {
|
|
67
|
-
obj.fetch = instrument.ensureInstrumented(
|
|
68
|
-
obj.fetch.bind(obj),
|
|
69
|
-
(original) => new Proxy(original, {
|
|
70
|
-
apply(target, thisArg, args) {
|
|
71
|
-
return wrapRequestHandlerWithInit.wrapRequestHandlerWithInit(
|
|
72
|
-
{ options, request: args[0], context },
|
|
73
|
-
() => {
|
|
74
|
-
return Reflect.apply(target, thisArg, args);
|
|
75
|
-
},
|
|
76
|
-
sdk.init
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
if (obj.alarm && typeof obj.alarm === "function") {
|
|
83
|
-
obj.alarm = wrapMethodWithSentry.wrapMethodWithSentry(
|
|
84
|
-
{
|
|
85
|
-
options,
|
|
86
|
-
context,
|
|
87
|
-
spanName: "alarm",
|
|
88
|
-
spanOp: "function",
|
|
89
|
-
startNewTrace: true,
|
|
90
|
-
origin: "auto.faas.cloudflare.durable_object"
|
|
91
|
-
},
|
|
92
|
-
obj.alarm.bind(obj)
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
if (obj.webSocketMessage && typeof obj.webSocketMessage === "function") {
|
|
96
|
-
obj.webSocketMessage = wrapMethodWithSentry.wrapMethodWithSentry(
|
|
97
|
-
{
|
|
98
|
-
options,
|
|
99
|
-
context,
|
|
100
|
-
spanName: "webSocketMessage",
|
|
101
|
-
spanOp: op.WEBSOCKET,
|
|
102
|
-
origin: "auto.faas.cloudflare.durable_object"
|
|
103
|
-
},
|
|
104
|
-
obj.webSocketMessage.bind(obj)
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
if (obj.webSocketClose && typeof obj.webSocketClose === "function") {
|
|
108
|
-
obj.webSocketClose = wrapMethodWithSentry.wrapMethodWithSentry(
|
|
109
|
-
{
|
|
110
|
-
options,
|
|
111
|
-
context,
|
|
112
|
-
spanName: "webSocketClose",
|
|
113
|
-
spanOp: op.WEBSOCKET,
|
|
114
|
-
origin: "auto.faas.cloudflare.durable_object"
|
|
115
|
-
},
|
|
116
|
-
obj.webSocketClose.bind(obj)
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
if (obj.webSocketError && typeof obj.webSocketError === "function") {
|
|
120
|
-
obj.webSocketError = wrapMethodWithSentry.wrapMethodWithSentry(
|
|
121
|
-
{
|
|
122
|
-
options,
|
|
123
|
-
context,
|
|
124
|
-
spanName: "webSocketError",
|
|
125
|
-
spanOp: op.WEBSOCKET,
|
|
126
|
-
origin: "auto.faas.cloudflare.durable_object"
|
|
127
|
-
},
|
|
128
|
-
obj.webSocketError.bind(obj),
|
|
129
|
-
(_, error) => core.captureException(error, {
|
|
130
|
-
mechanism: {
|
|
131
|
-
type: "auto.faas.cloudflare.durable_object_websocket",
|
|
132
|
-
handled: false
|
|
133
|
-
}
|
|
134
|
-
})
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
64
|
const RESERVED_RPC_METHOD_NAMES = /* @__PURE__ */ new Set([
|
|
139
65
|
"constructor",
|
|
140
66
|
"fetch",
|
|
@@ -196,7 +122,7 @@ function createRpcPrototypeWrapper(methodName, originalMethod) {
|
|
|
196
122
|
options: state.options,
|
|
197
123
|
context: state.context,
|
|
198
124
|
spanName: methodName,
|
|
199
|
-
spanOp:
|
|
125
|
+
spanOp: op.RPC,
|
|
200
126
|
origin: "auto.faas.cloudflare.durable_object"
|
|
201
127
|
},
|
|
202
128
|
originalMethod,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durableobject.js","sources":["../../../src/durableobject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { WEBSOCKET } from '@sentry/conventions/op';\nimport { captureException, isObjectLike } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '@sentry/server-utils/no-diagnostic-channels';\nimport type { CloudflareOptions } from './client';\nimport { ensureInstrumented, getInstrumented, markAsInstrumented } from './instrument';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { getFinalOptions } from './options';\nimport { wrapRequestHandlerWithInit } from './wrapRequestHandlerWithInit';\nimport { init } from './sdk';\nimport { instrumentContext } from './utils/instrumentContext';\nimport { hasRpcMeta } from './utils/rpcMeta';\nimport { instrumentCloudflareAgent } from './instrumentations/agents';\nimport type { DefaultEnv, ResolveEnv, StrictCloudflareOptions } from './types';\nimport { type UncheckedMethod, wrapMethodWithSentry } from './wrapMethodWithSentry';\n\n/**\n * The instrumented context passed between the shared construction helpers.\n *\n * This is intentionally `any` rather than `ReturnType<typeof instrumentContext<DurableObjectState>>`.\n * A concrete `DurableObjectState` here forces `tsc` to structurally relate its `storage: SqlStorage`\n * graph against the `ExecutionContext | InstrumentedDurableObjectState` parameter of\n * `wrapMethodWithSentry`, while the RPC-branded `DurableObject` from `cloudflare:workers` is also in\n * scope. That union comparison explodes (1296×1296) and hangs the type build. The original inline\n * implementation avoided this only incidentally, because `ctx` reached it as `any` through the Proxy\n * `construct` trap. Keeping the shared context `any` preserves that behavior.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InstrumentedDurableObjectContext = any;\n\n/**\n * Constructs a Durable Object instance and instruments its built-in handler methods\n * (`fetch`, `alarm`, `webSocketMessage`, `webSocketClose`, `webSocketError`).\n *\n * This is the shared construction path used by both {@link instrumentDurableObjectWithSentry}\n * and {@link instrumentAgentWithSentry}. It intentionally does NOT apply the RPC prototype-method\n * instrumentation — callers apply that last via {@link finalizeWithRpcInstrumentation}, after any\n * additional per-instance instrumentation has been layered onto the returned object.\n *\n * @internal\n */\nexport function constructInstrumentedDurableObject<E, T extends DurableObject<E>>(\n target: new (state: DurableObjectState, env: E) => T,\n ctx: DurableObjectState,\n env: E,\n newTarget: NewableFunction,\n optionsCallback: (env: E) => CloudflareOptions,\n): {\n obj: T;\n options: CloudflareOptions;\n context: InstrumentedDurableObjectContext;\n frameworkManagedMethods: ReadonlySet<string>;\n} {\n setAsyncLocalStorageAsyncContextStrategy();\n const options = getFinalOptions(optionsCallback(env), env);\n // See InstrumentedDurableObjectContext — `ctx` is widened to `any` so the concrete\n // `DurableObjectState` type never enters the checker's relation graph in this module.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const context = instrumentContext(ctx as any);\n const instrumentedEnv = instrumentEnv(env as Record<string, unknown>, options);\n\n const prototype = (newTarget as unknown as { prototype?: object }).prototype ?? target.prototype;\n const cachedFrameworkManagedMethods = frameworkManagedMethodsCache.get(prototype);\n const methodsBeforeConstruction = cachedFrameworkManagedMethods ? undefined : resolvePrototypeMethods(prototype);\n\n // Pass `newTarget` so that subclasses of the instrumented class (e.g. the wrapper classes\n // created by wrangler's local dev tooling or `@cloudflare/vitest-pool-workers`) keep their\n // own prototype — otherwise subclass methods disappear and `instanceof` checks break.\n const obj = Reflect.construct(target, [context, instrumentedEnv], newTarget) as T;\n\n const frameworkManagedMethods = resolveFrameworkManagedMethods(\n prototype,\n obj,\n methodsBeforeConstruction,\n cachedFrameworkManagedMethods,\n );\n\n instrumentDurableObjectHandlers(obj, options, context);\n\n return { obj, options, context, frameworkManagedMethods };\n}\n\nconst frameworkManagedMethodsCache = new WeakMap<object, ReadonlySet<string>>();\n\n/**\n * Collects the methods visible from a prototype, using normal property lookup precedence.\n * Methods inherited from `Object.prototype` are excluded because they cannot be Durable Object RPC methods.\n */\nfunction resolvePrototypeMethods(prototype: object | null): Map<string, unknown> {\n const methods = new Map<string, unknown>();\n\n for (let current = prototype; current && current !== Object.prototype; current = Object.getPrototypeOf(current)) {\n for (const name of Object.getOwnPropertyNames(current)) {\n // The first occurrence wins, mirroring what a property lookup on the instance would find\n if (name === 'constructor' || methods.has(name)) {\n continue;\n }\n\n const descriptor = Object.getOwnPropertyDescriptor(current, name);\n\n if (descriptor && typeof descriptor.value === 'function') {\n methods.set(name, descriptor.value);\n }\n }\n }\n\n return methods;\n}\n\n/**\n * Finds methods that a framework replaced while constructing the first instance.\n *\n * Some frameworks register methods by function identity, so replacing one of their wrappers would\n * break dispatch. The result is cached because frameworks commonly install their wrappers only\n * once; later constructions would no longer reveal which methods they manage.\n */\nfunction resolveFrameworkManagedMethods(\n prototype: object,\n obj: object,\n methodsBeforeConstruction: Map<string, unknown> | undefined,\n cached: ReadonlySet<string> | undefined,\n): ReadonlySet<string> {\n if (cached) {\n return cached;\n }\n\n const methodsAfterConstruction = resolvePrototypeMethods(Object.getPrototypeOf(obj) as object);\n const managed = new Set<string>();\n\n for (const [name, method] of methodsAfterConstruction) {\n const before = methodsBeforeConstruction?.get(name);\n\n if (before && before !== method) {\n managed.add(name);\n }\n }\n\n frameworkManagedMethodsCache.set(prototype, managed);\n\n return managed;\n}\n\n/**\n * Instruments the built-in Durable Object handler methods on a constructed instance.\n *\n * These are the methods that are available on a Durable Object\n * ref: https://developers.cloudflare.com/durable-objects/api/base/\n * - obj.alarm\n * - obj.fetch\n * - obj.webSocketError\n * - obj.webSocketClose\n * - obj.webSocketMessage\n *\n * Any other public methods on the Durable Object instance are RPC calls.\n */\nfunction instrumentDurableObjectHandlers<E, T extends DurableObject<E>>(\n obj: T,\n options: CloudflareOptions,\n context: InstrumentedDurableObjectContext,\n): void {\n // Bind each built-in handler to this instance before wrapping.\n // See https://github.com/getsentry/sentry-javascript/issues/22328\n if (obj.fetch && typeof obj.fetch === 'function') {\n obj.fetch = ensureInstrumented(\n obj.fetch.bind(obj),\n original =>\n new Proxy(original, {\n apply(target, thisArg, args) {\n return wrapRequestHandlerWithInit(\n { options, request: args[0], context },\n () => {\n return Reflect.apply(target, thisArg, args);\n },\n init,\n );\n },\n }),\n );\n }\n\n if (obj.alarm && typeof obj.alarm === 'function') {\n // Alarms are independent invocations, so we start a new trace and link to the previous alarm\n obj.alarm = wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'alarm',\n spanOp: 'function',\n startNewTrace: true,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.alarm.bind(obj),\n );\n }\n\n if (obj.webSocketMessage && typeof obj.webSocketMessage === 'function') {\n obj.webSocketMessage = wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'webSocketMessage',\n spanOp: WEBSOCKET,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.webSocketMessage.bind(obj),\n );\n }\n\n if (obj.webSocketClose && typeof obj.webSocketClose === 'function') {\n obj.webSocketClose = wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'webSocketClose',\n spanOp: WEBSOCKET,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.webSocketClose.bind(obj),\n );\n }\n\n if (obj.webSocketError && typeof obj.webSocketError === 'function') {\n obj.webSocketError = wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'webSocketError',\n spanOp: WEBSOCKET,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.webSocketError.bind(obj),\n (_, error) =>\n captureException(error, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object_websocket',\n handled: false,\n },\n }),\n );\n }\n}\n\ntype RpcInstanceState = {\n options: CloudflareOptions;\n context: InstrumentedDurableObjectContext;\n /** Per-instance cache of the traced method wrappers, keyed by method name. Created on first use. */\n tracedMethods?: Map<string, UncheckedMethod>;\n};\n\n/**\n * Method names the runtime never dispatches over RPC, so wrapping them buys no tracing.\n *\n * Mirrors `isReservedName` in workerd (`src/workerd/api/worker-rpc.c++`): the runtime rejects these\n * before any property lookup happens. `fetch`, `alarm` and the `webSocket*` handlers are also\n * instrumented per-instance as own properties, and `constructor` is on every prototype.\n */\nconst RESERVED_RPC_METHOD_NAMES: ReadonlySet<string> = new Set([\n 'constructor',\n 'fetch',\n 'connect',\n 'alarm',\n 'webSocketMessage',\n 'webSocketClose',\n 'webSocketError',\n 'dup',\n]);\n\n// Prototype wrappers are shared by all instances, while SDK options and traced method caches are not.\nconst rpcInstanceStates = new WeakMap<object, RpcInstanceState>();\n\n/**\n * Adds trace propagation to a constructed Durable Object's RPC methods.\n *\n * RPC methods are wrapped on the prototype because Cloudflare dispatches them with the Durable\n * Object instance as the receiver. This preserves native private-field access and keeps the methods\n * visible to Cloudflare's RPC dispatcher. Built-in handlers, Agent handlers, and methods managed by\n * another framework are left untouched.\n *\n * Call this after all per-instance instrumentation has been applied.\n *\n * @param obj The constructed Durable Object instance.\n * @param options The resolved SDK options for this instance.\n * @param context The instrumented execution context for this instance.\n * @param excludedMethods Method names owned by another framework and therefore not safe to wrap.\n * @returns The same Durable Object instance, with eligible prototype methods instrumented.\n * @internal\n */\nexport function finalizeWithRpcInstrumentation<T extends object>(\n obj: T,\n options: CloudflareOptions,\n context: InstrumentedDurableObjectContext,\n excludedMethods?: ReadonlySet<string>,\n): T {\n rpcInstanceStates.set(obj, { options, context });\n\n instrumentPrototypeRpcMethods(obj, excludedMethods);\n\n return obj;\n}\n\n/**\n * Returns a prototype method when it is eligible for RPC instrumentation.\n */\nfunction getRpcMethodDescriptor(\n obj: object,\n prototype: object,\n methodName: string,\n excludedMethods?: ReadonlySet<string>,\n): PropertyDescriptor | undefined {\n if (\n RESERVED_RPC_METHOD_NAMES.has(methodName) ||\n Object.prototype.hasOwnProperty.call(obj, methodName) ||\n excludedMethods?.has(methodName)\n ) {\n return undefined;\n }\n\n const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);\n\n if (!descriptor || typeof descriptor.value !== 'function' || getInstrumented(descriptor.value)) {\n return undefined;\n }\n\n return descriptor;\n}\n\n/**\n * Wraps eligible methods on the instance's prototype chain once per class.\n */\nfunction instrumentPrototypeRpcMethods(obj: object, excludedMethods?: ReadonlySet<string>): void {\n let prototype: object | null = Object.getPrototypeOf(obj);\n\n while (prototype && prototype !== Object.prototype) {\n for (const methodName of Object.getOwnPropertyNames(prototype)) {\n const descriptor = getRpcMethodDescriptor(obj, prototype, methodName, excludedMethods);\n\n if (!descriptor) {\n continue;\n }\n\n const wrapped = createRpcPrototypeWrapper(methodName, descriptor.value as UncheckedMethod);\n\n try {\n Object.defineProperty(prototype, methodName, { ...descriptor, value: wrapped });\n } catch {}\n\n // Only the wrapper is marked, not the original method: `wrapMethodWithSentry` resolves\n // through the same global map and must not resolve the original to this wrapper,\n // which would recurse.\n markAsInstrumented(wrapped);\n }\n\n prototype = Object.getPrototypeOf(prototype);\n }\n}\n\n/**\n * Creates a prototype wrapper that traces RPC calls carrying Sentry metadata.\n *\n * The wrapper looks up SDK state from its receiver, allowing one prototype function to serve every\n * instance. Calls without RPC metadata or instance state use the original method directly. The\n * original function name and arity are preserved because frameworks may inspect them for dispatch.\n */\nfunction createRpcPrototypeWrapper(methodName: string, originalMethod: UncheckedMethod): UncheckedMethod {\n const wrapper = function (this: unknown, ...args: unknown[]): unknown {\n // Untraced calls are the common case — every internal call the instance makes to one of its\n // own methods lands here too — so check the arguments before touching per-instance state.\n if (!hasRpcMeta(args)) {\n return Reflect.apply(originalMethod, this, args);\n }\n\n const state = isObjectLike(this) ? rpcInstanceStates.get(this) : undefined;\n\n if (!state) {\n return Reflect.apply(originalMethod, this, args);\n }\n\n const tracedMethods = (state.tracedMethods ??= new Map());\n let traced = tracedMethods.get(methodName);\n\n if (!traced) {\n traced = wrapMethodWithSentry(\n {\n options: state.options,\n context: state.context,\n spanName: methodName,\n spanOp: 'rpc',\n origin: 'auto.faas.cloudflare.durable_object',\n },\n originalMethod,\n undefined,\n true,\n );\n tracedMethods.set(methodName, traced);\n }\n\n return Reflect.apply(traced, this, args);\n };\n\n Object.defineProperties(wrapper, {\n name: { value: originalMethod.name, configurable: true },\n length: { value: originalMethod.length, configurable: true },\n });\n\n return wrapper as UncheckedMethod;\n}\n\n/**\n * Instruments a Durable Object class to capture errors and performance data.\n *\n * Instruments the following methods by default:\n * - fetch\n * - alarm\n * - webSocketMessage\n * - webSocketClose\n * - webSocketError\n *\n * RPC methods (prototype methods) are instrumented too, so an incoming trace continues into them.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param DurableObjectClass The Durable Object class to instrument.\n * @returns The instrumented Durable Object class.\n *\n * @example\n * ```ts\n * class MyDurableObjectBase extends DurableObject {\n * constructor(ctx: DurableObjectState, env: Env) {\n * super(ctx, env);\n * }\n * }\n *\n * export const MyDurableObject = instrumentDurableObjectWithSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyDurableObjectBase,\n * );\n * ```\n */\nexport function instrumentDurableObjectWithSentry<\n Env = DefaultEnv,\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends DurableObject<any> = DurableObject<Env>,\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (state: DurableObjectState, env: any) => T = new (state: DurableObjectState, env: any) => T,\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, Env>) => StrictCloudflareOptions<O>, DurableObjectClass: C): C {\n return new Proxy(DurableObjectClass, {\n construct(target, [ctx, env], newTarget) {\n const { obj, options, context, frameworkManagedMethods } = constructInstrumentedDurableObject(\n target,\n ctx,\n env,\n newTarget,\n optionsCallback,\n );\n\n return finalizeWithRpcInstrumentation(obj, options, context, frameworkManagedMethods);\n },\n });\n}\n\n/**\n * Instruments a Cloudflare [`agents`](https://www.npmjs.com/package/agents) Agent class with Sentry.\n *\n * An `Agent` is a Durable Object under the hood, so this applies the same instrumentation as\n * {@link instrumentDurableObjectWithSentry} (request transactions, `alarm`, WebSocket handlers, RPC\n * trace propagation, SQL spans) and additionally captures Agent-specific telemetry via\n * `instrumentCloudflareAgent`:\n *\n * - **Callable RPC spans** — a span (op `rpc`) for each `@callable()` method invoked over WebSocket.\n * - **Breadcrumbs** — for every Agent observability event (`rpc`, `state:update`, `connect`,\n * `disconnect`, `schedule:*`, `queue:*`, `workflow:*`, `email:*`, `mcp:*`, ...).\n *\n * Cloudflare Workers cannot auto-instrument, so the Agent class must be wrapped manually.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param AgentClass The Agent class to instrument.\n * @returns The instrumented Agent class.\n *\n * @example\n * ```ts\n * import { Agent, callable, routeAgentRequest } from 'agents';\n * import * as Sentry from '@sentry/cloudflare';\n *\n * class MyAgentBase extends Agent<Env> {\n * @callable()\n * async greet(name: string): Promise<string> {\n * return `Hello, ${name}!`;\n * }\n * }\n *\n * export const MyAgent = Sentry.instrumentAgentWithSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyAgentBase,\n * );\n * ```\n */\nexport function instrumentAgentWithSentry<\n Env = DefaultEnv,\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends DurableObject<any> = DurableObject<Env>,\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (state: DurableObjectState, env: any) => T = new (state: DurableObjectState, env: any) => T,\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, Env>) => StrictCloudflareOptions<O>, AgentClass: C): C {\n return new Proxy(AgentClass, {\n construct(target, [ctx, env], newTarget) {\n const { obj, options, context, frameworkManagedMethods } = constructInstrumentedDurableObject(\n target,\n ctx,\n env,\n newTarget,\n optionsCallback,\n );\n\n instrumentCloudflareAgent(obj);\n\n // Apply RPC prototype-method instrumentation last, so the Agent-specific own-property\n // handlers we just installed are excluded from RPC method tracing. Methods the Agent\n // framework installed itself are excluded too — `instrumentCloudflareAgent` traces those by\n // wrapping the dispatch instead of the method.\n return finalizeWithRpcInstrumentation(obj, options, context, frameworkManagedMethods);\n },\n });\n}\n"],"names":["setAsyncLocalStorageAsyncContextStrategy","options","getFinalOptions","instrumentContext","instrumentEnv","ensureInstrumented","wrapRequestHandlerWithInit","init","wrapMethodWithSentry","WEBSOCKET","captureException","getInstrumented","markAsInstrumented","hasRpcMeta","isObjectLike","instrumentCloudflareAgent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"durableobject.js","sources":["../../../src/durableobject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { RPC } from '@sentry/conventions/op';\nimport { isObjectLike } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport { setAsyncLocalStorageAsyncContextStrategy } from '@sentry/server-utils/no-diagnostic-channels';\nimport type { CloudflareOptions } from './client';\nimport { getInstrumented, markAsInstrumented } from './instrument';\nimport { instrumentDurableObjectHandlers } from './instrumentations/instrumentDurableObjectHandlers';\nimport { instrumentEnv } from './instrumentations/worker/instrumentEnv';\nimport { getFinalOptions } from './options';\nimport { instrumentContext } from './utils/instrumentContext';\nimport { hasRpcMeta } from './utils/rpcMeta';\nimport { instrumentCloudflareAgent } from './instrumentations/agents';\nimport type { DefaultEnv, ResolveEnv, StrictCloudflareOptions } from './types';\nimport { type UncheckedMethod, wrapMethodWithSentry } from './wrapMethodWithSentry';\n\n/**\n * The instrumented context passed between the shared construction helpers.\n *\n * This is intentionally `any` rather than `ReturnType<typeof instrumentContext<DurableObjectState>>`.\n * A concrete `DurableObjectState` here forces `tsc` to structurally relate its `storage: SqlStorage`\n * graph against the `ExecutionContext | InstrumentedDurableObjectState` parameter of\n * `wrapMethodWithSentry`, while the RPC-branded `DurableObject` from `cloudflare:workers` is also in\n * scope. That union comparison explodes (1296×1296) and hangs the type build. The original inline\n * implementation avoided this only incidentally, because `ctx` reached it as `any` through the Proxy\n * `construct` trap. Keeping the shared context `any` preserves that behavior.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InstrumentedDurableObjectContext = any;\n\n/**\n * Constructs a Durable Object instance and instruments its built-in handler methods\n * (`fetch`, `alarm`, `webSocketMessage`, `webSocketClose`, `webSocketError`).\n *\n * This is the shared construction path used by both {@link instrumentDurableObjectWithSentry}\n * and {@link instrumentAgentWithSentry}. It intentionally does NOT apply the RPC prototype-method\n * instrumentation — callers apply that last via {@link finalizeWithRpcInstrumentation}, after any\n * additional per-instance instrumentation has been layered onto the returned object.\n *\n * @internal\n */\nexport function constructInstrumentedDurableObject<E, T extends DurableObject<E>>(\n target: new (state: DurableObjectState, env: E) => T,\n ctx: DurableObjectState,\n env: E,\n newTarget: NewableFunction,\n optionsCallback: (env: E) => CloudflareOptions,\n): {\n obj: T;\n options: CloudflareOptions;\n context: InstrumentedDurableObjectContext;\n frameworkManagedMethods: ReadonlySet<string>;\n} {\n setAsyncLocalStorageAsyncContextStrategy();\n const options = getFinalOptions(optionsCallback(env), env);\n // See InstrumentedDurableObjectContext — `ctx` is widened to `any` so the concrete\n // `DurableObjectState` type never enters the checker's relation graph in this module.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const context = instrumentContext(ctx as any);\n const instrumentedEnv = instrumentEnv(env as Record<string, unknown>, options);\n\n const prototype = (newTarget as unknown as { prototype?: object }).prototype ?? target.prototype;\n const cachedFrameworkManagedMethods = frameworkManagedMethodsCache.get(prototype);\n const methodsBeforeConstruction = cachedFrameworkManagedMethods ? undefined : resolvePrototypeMethods(prototype);\n\n // Pass `newTarget` so that subclasses of the instrumented class (e.g. the wrapper classes\n // created by wrangler's local dev tooling or `@cloudflare/vitest-pool-workers`) keep their\n // own prototype — otherwise subclass methods disappear and `instanceof` checks break.\n const obj = Reflect.construct(target, [context, instrumentedEnv], newTarget) as T;\n\n const frameworkManagedMethods = resolveFrameworkManagedMethods(\n prototype,\n obj,\n methodsBeforeConstruction,\n cachedFrameworkManagedMethods,\n );\n\n instrumentDurableObjectHandlers(obj, options, context);\n\n return { obj, options, context, frameworkManagedMethods };\n}\n\nconst frameworkManagedMethodsCache = new WeakMap<object, ReadonlySet<string>>();\n\n/**\n * Collects the methods visible from a prototype, using normal property lookup precedence.\n * Methods inherited from `Object.prototype` are excluded because they cannot be Durable Object RPC methods.\n */\nfunction resolvePrototypeMethods(prototype: object | null): Map<string, unknown> {\n const methods = new Map<string, unknown>();\n\n for (let current = prototype; current && current !== Object.prototype; current = Object.getPrototypeOf(current)) {\n for (const name of Object.getOwnPropertyNames(current)) {\n // The first occurrence wins, mirroring what a property lookup on the instance would find\n if (name === 'constructor' || methods.has(name)) {\n continue;\n }\n\n const descriptor = Object.getOwnPropertyDescriptor(current, name);\n\n if (descriptor && typeof descriptor.value === 'function') {\n methods.set(name, descriptor.value);\n }\n }\n }\n\n return methods;\n}\n\n/**\n * Finds methods that a framework replaced while constructing the first instance.\n *\n * Some frameworks register methods by function identity, so replacing one of their wrappers would\n * break dispatch. The result is cached because frameworks commonly install their wrappers only\n * once; later constructions would no longer reveal which methods they manage.\n */\nfunction resolveFrameworkManagedMethods(\n prototype: object,\n obj: object,\n methodsBeforeConstruction: Map<string, unknown> | undefined,\n cached: ReadonlySet<string> | undefined,\n): ReadonlySet<string> {\n if (cached) {\n return cached;\n }\n\n const methodsAfterConstruction = resolvePrototypeMethods(Object.getPrototypeOf(obj) as object);\n const managed = new Set<string>();\n\n for (const [name, method] of methodsAfterConstruction) {\n const before = methodsBeforeConstruction?.get(name);\n\n if (before && before !== method) {\n managed.add(name);\n }\n }\n\n frameworkManagedMethodsCache.set(prototype, managed);\n\n return managed;\n}\n\ntype RpcInstanceState = {\n options: CloudflareOptions;\n context: InstrumentedDurableObjectContext;\n /** Per-instance cache of the traced method wrappers, keyed by method name. Created on first use. */\n tracedMethods?: Map<string, UncheckedMethod>;\n};\n\n/**\n * Method names the runtime never dispatches over RPC, so wrapping them buys no tracing.\n *\n * Mirrors `isReservedName` in workerd (`src/workerd/api/worker-rpc.c++`): the runtime rejects these\n * before any property lookup happens. `fetch`, `alarm` and the `webSocket*` handlers are also\n * instrumented per-instance as own properties, and `constructor` is on every prototype.\n */\nconst RESERVED_RPC_METHOD_NAMES: ReadonlySet<string> = new Set([\n 'constructor',\n 'fetch',\n 'connect',\n 'alarm',\n 'webSocketMessage',\n 'webSocketClose',\n 'webSocketError',\n 'dup',\n]);\n\n// Prototype wrappers are shared by all instances, while SDK options and traced method caches are not.\nconst rpcInstanceStates = new WeakMap<object, RpcInstanceState>();\n\n/**\n * Adds trace propagation to a constructed Durable Object's RPC methods.\n *\n * RPC methods are wrapped on the prototype because Cloudflare dispatches them with the Durable\n * Object instance as the receiver. This preserves native private-field access and keeps the methods\n * visible to Cloudflare's RPC dispatcher. Built-in handlers, Agent handlers, and methods managed by\n * another framework are left untouched.\n *\n * Call this after all per-instance instrumentation has been applied.\n *\n * @param obj The constructed Durable Object instance.\n * @param options The resolved SDK options for this instance.\n * @param context The instrumented execution context for this instance.\n * @param excludedMethods Method names owned by another framework and therefore not safe to wrap.\n * @returns The same Durable Object instance, with eligible prototype methods instrumented.\n * @internal\n */\nexport function finalizeWithRpcInstrumentation<T extends object>(\n obj: T,\n options: CloudflareOptions,\n context: InstrumentedDurableObjectContext,\n excludedMethods?: ReadonlySet<string>,\n): T {\n rpcInstanceStates.set(obj, { options, context });\n\n instrumentPrototypeRpcMethods(obj, excludedMethods);\n\n return obj;\n}\n\n/**\n * Returns a prototype method when it is eligible for RPC instrumentation.\n */\nfunction getRpcMethodDescriptor(\n obj: object,\n prototype: object,\n methodName: string,\n excludedMethods?: ReadonlySet<string>,\n): PropertyDescriptor | undefined {\n if (\n RESERVED_RPC_METHOD_NAMES.has(methodName) ||\n Object.prototype.hasOwnProperty.call(obj, methodName) ||\n excludedMethods?.has(methodName)\n ) {\n return undefined;\n }\n\n const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);\n\n if (!descriptor || typeof descriptor.value !== 'function' || getInstrumented(descriptor.value)) {\n return undefined;\n }\n\n return descriptor;\n}\n\n/**\n * Wraps eligible methods on the instance's prototype chain once per class.\n */\nfunction instrumentPrototypeRpcMethods(obj: object, excludedMethods?: ReadonlySet<string>): void {\n let prototype: object | null = Object.getPrototypeOf(obj);\n\n while (prototype && prototype !== Object.prototype) {\n for (const methodName of Object.getOwnPropertyNames(prototype)) {\n const descriptor = getRpcMethodDescriptor(obj, prototype, methodName, excludedMethods);\n\n if (!descriptor) {\n continue;\n }\n\n const wrapped = createRpcPrototypeWrapper(methodName, descriptor.value as UncheckedMethod);\n\n try {\n Object.defineProperty(prototype, methodName, { ...descriptor, value: wrapped });\n } catch {}\n\n // Only the wrapper is marked, not the original method: `wrapMethodWithSentry` resolves\n // through the same global map and must not resolve the original to this wrapper,\n // which would recurse.\n markAsInstrumented(wrapped);\n }\n\n prototype = Object.getPrototypeOf(prototype);\n }\n}\n\n/**\n * Creates a prototype wrapper that traces RPC calls carrying Sentry metadata.\n *\n * The wrapper looks up SDK state from its receiver, allowing one prototype function to serve every\n * instance. Calls without RPC metadata or instance state use the original method directly. The\n * original function name and arity are preserved because frameworks may inspect them for dispatch.\n */\nfunction createRpcPrototypeWrapper(methodName: string, originalMethod: UncheckedMethod): UncheckedMethod {\n const wrapper = function (this: unknown, ...args: unknown[]): unknown {\n // Untraced calls are the common case — every internal call the instance makes to one of its\n // own methods lands here too — so check the arguments before touching per-instance state.\n if (!hasRpcMeta(args)) {\n return Reflect.apply(originalMethod, this, args);\n }\n\n const state = isObjectLike(this) ? rpcInstanceStates.get(this) : undefined;\n\n if (!state) {\n return Reflect.apply(originalMethod, this, args);\n }\n\n const tracedMethods = (state.tracedMethods ??= new Map());\n let traced = tracedMethods.get(methodName);\n\n if (!traced) {\n traced = wrapMethodWithSentry(\n {\n options: state.options,\n context: state.context,\n spanName: methodName,\n spanOp: RPC,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n originalMethod,\n undefined,\n true,\n );\n tracedMethods.set(methodName, traced);\n }\n\n return Reflect.apply(traced, this, args);\n };\n\n Object.defineProperties(wrapper, {\n name: { value: originalMethod.name, configurable: true },\n length: { value: originalMethod.length, configurable: true },\n });\n\n return wrapper as UncheckedMethod;\n}\n\n/**\n * Instruments a Durable Object class to capture errors and performance data.\n *\n * Instruments the following methods by default:\n * - fetch\n * - alarm\n * - webSocketMessage\n * - webSocketClose\n * - webSocketError\n *\n * RPC methods (prototype methods) are instrumented too, so an incoming trace continues into them.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param DurableObjectClass The Durable Object class to instrument.\n * @returns The instrumented Durable Object class.\n *\n * @example\n * ```ts\n * class MyDurableObjectBase extends DurableObject {\n * constructor(ctx: DurableObjectState, env: Env) {\n * super(ctx, env);\n * }\n * }\n *\n * export const MyDurableObject = instrumentDurableObjectWithSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyDurableObjectBase,\n * );\n * ```\n */\nexport function instrumentDurableObjectWithSentry<\n Env = DefaultEnv,\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends DurableObject<any> = DurableObject<Env>,\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (state: DurableObjectState, env: any) => T = new (state: DurableObjectState, env: any) => T,\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, Env>) => StrictCloudflareOptions<O>, DurableObjectClass: C): C {\n return new Proxy(DurableObjectClass, {\n construct(target, [ctx, env], newTarget) {\n const { obj, options, context, frameworkManagedMethods } = constructInstrumentedDurableObject(\n target,\n ctx,\n env,\n newTarget,\n optionsCallback,\n );\n\n return finalizeWithRpcInstrumentation(obj, options, context, frameworkManagedMethods);\n },\n });\n}\n\n/**\n * Instruments a Cloudflare [`agents`](https://www.npmjs.com/package/agents) Agent class with Sentry.\n *\n * An `Agent` is a Durable Object under the hood, so this applies the same instrumentation as\n * {@link instrumentDurableObjectWithSentry} (request transactions, `alarm`, WebSocket handlers, RPC\n * trace propagation, SQL spans) and additionally captures Agent-specific telemetry via\n * `instrumentCloudflareAgent`:\n *\n * - **Callable RPC spans** — a span (op `rpc`) for each `@callable()` method invoked over WebSocket.\n * - **Breadcrumbs** — for every Agent observability event (`rpc`, `state:update`, `connect`,\n * `disconnect`, `schedule:*`, `queue:*`, `workflow:*`, `email:*`, `mcp:*`, ...).\n *\n * Cloudflare Workers cannot auto-instrument, so the Agent class must be wrapped manually.\n *\n * @param optionsCallback Function that returns the options for the SDK initialization.\n * @param AgentClass The Agent class to instrument.\n * @returns The instrumented Agent class.\n *\n * @example\n * ```ts\n * import { Agent, callable, routeAgentRequest } from 'agents';\n * import * as Sentry from '@sentry/cloudflare';\n *\n * class MyAgentBase extends Agent<Env> {\n * @callable()\n * async greet(name: string): Promise<string> {\n * return `Hello, ${name}!`;\n * }\n * }\n *\n * export const MyAgent = Sentry.instrumentAgentWithSentry(\n * env => ({\n * dsn: env.SENTRY_DSN,\n * tracesSampleRate: 1.0,\n * }),\n * MyAgentBase,\n * );\n * ```\n */\nexport function instrumentAgentWithSentry<\n Env = DefaultEnv,\n // oxlint-disable-next-line typescript/no-explicit-any\n T extends DurableObject<any> = DurableObject<Env>,\n // oxlint-disable-next-line typescript/no-explicit-any\n C extends new (state: DurableObjectState, env: any) => T = new (state: DurableObjectState, env: any) => T,\n O = unknown,\n>(optionsCallback: (env: ResolveEnv<C, Env>) => StrictCloudflareOptions<O>, AgentClass: C): C {\n return new Proxy(AgentClass, {\n construct(target, [ctx, env], newTarget) {\n const { obj, options, context, frameworkManagedMethods } = constructInstrumentedDurableObject(\n target,\n ctx,\n env,\n newTarget,\n optionsCallback,\n );\n\n instrumentCloudflareAgent(obj);\n\n // Apply RPC prototype-method instrumentation last, so the Agent-specific own-property\n // handlers we just installed are excluded from RPC method tracing. Methods the Agent\n // framework installed itself are excluded too — `instrumentCloudflareAgent` traces those by\n // wrapping the dispatch instead of the method.\n return finalizeWithRpcInstrumentation(obj, options, context, frameworkManagedMethods);\n },\n });\n}\n"],"names":["setAsyncLocalStorageAsyncContextStrategy","options","getFinalOptions","instrumentContext","instrumentEnv","instrumentDurableObjectHandlers","getInstrumented","markAsInstrumented","hasRpcMeta","isObjectLike","wrapMethodWithSentry","RPC","instrumentCloudflareAgent"],"mappings":"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"}
|
package/build/cjs/dev/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
|
+
const server = require('@sentry/core/server');
|
|
4
5
|
const withSentry = require('./withSentry.js');
|
|
5
6
|
const defineCloudflareOptions = require('./defineCloudflareOptions.js');
|
|
6
7
|
const durableobject = require('./durableobject.js');
|
|
@@ -55,7 +56,6 @@ exports.getSpanStatusFromHttpCode = core.getSpanStatusFromHttpCode;
|
|
|
55
56
|
exports.getTraceData = core.getTraceData;
|
|
56
57
|
exports.getTraceMetaTags = core.getTraceMetaTags;
|
|
57
58
|
exports.growthbookIntegration = core.growthbookIntegration;
|
|
58
|
-
exports.instrumentPostgresJsSql = core.instrumentPostgresJsSql;
|
|
59
59
|
exports.instrumentSupabaseClient = core.instrumentSupabaseClient;
|
|
60
60
|
exports.isEnabled = core.isEnabled;
|
|
61
61
|
exports.isInitialized = core.isInitialized;
|
|
@@ -89,7 +89,6 @@ exports.startSpan = core.startSpan;
|
|
|
89
89
|
exports.startSpanManual = core.startSpanManual;
|
|
90
90
|
exports.supabaseIntegration = core.supabaseIntegration;
|
|
91
91
|
exports.suppressTracing = core.suppressTracing;
|
|
92
|
-
exports.trpcMiddleware = core.trpcMiddleware;
|
|
93
92
|
exports.updateSpanName = core.updateSpanName;
|
|
94
93
|
exports.withActiveSpan = core.withActiveSpan;
|
|
95
94
|
exports.withIsolationScope = core.withIsolationScope;
|
|
@@ -97,8 +96,10 @@ exports.withMonitor = core.withMonitor;
|
|
|
97
96
|
exports.withScope = core.withScope;
|
|
98
97
|
exports.withStaticSpan = core.withStaticSpan;
|
|
99
98
|
exports.withStreamedSpan = core.withStreamedSpan;
|
|
100
|
-
exports.wrapMcpServerWithSentry = core.wrapMcpServerWithSentry;
|
|
101
99
|
exports.zodErrorsIntegration = core.zodErrorsIntegration;
|
|
100
|
+
exports.instrumentPostgresJsSql = server.instrumentPostgresJsSql;
|
|
101
|
+
exports.trpcMiddleware = server.trpcMiddleware;
|
|
102
|
+
exports.wrapMcpServerWithSentry = server.wrapMcpServerWithSentry;
|
|
102
103
|
exports.withSentry = withSentry.withSentry;
|
|
103
104
|
exports.defineCloudflareOptions = defineCloudflareOptions.defineCloudflareOptions;
|
|
104
105
|
exports.instrumentAgentWithSentry = durableobject.instrumentAgentWithSentry;
|
|
@@ -119,7 +120,7 @@ exports.instrumentLangChainEmbeddings = serverUtils.instrumentLangChainEmbedding
|
|
|
119
120
|
exports.instrumentOpenAiClient = serverUtils.instrumentOpenAiClient;
|
|
120
121
|
exports.instrumentStateGraph = serverUtils.instrumentStateGraph;
|
|
121
122
|
exports.instrumentWorkersAiClient = serverUtils.instrumentWorkersAiClient;
|
|
122
|
-
exports.
|
|
123
|
+
exports.openTelemetryIntegration = serverUtils.openTelemetryIntegration;
|
|
123
124
|
exports.prismaIntegration = serverUtils.prismaIntegration;
|
|
124
125
|
exports.vercelAIIntegration = serverUtils.vercelAIIntegration;
|
|
125
126
|
exports.instrumentWorkflowWithSentry = workflows.instrumentWorkflowWithSentry;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
+
const attributes = require('@sentry/conventions/attributes');
|
|
4
|
+
const op = require('@sentry/conventions/op');
|
|
3
5
|
const core = require('@sentry/core');
|
|
4
6
|
const debugBuild = require('../../debug-build.js');
|
|
5
7
|
const types = require('./types.js');
|
|
@@ -20,7 +22,7 @@ function instrumentAgentCallableRpc(obj) {
|
|
|
20
22
|
{
|
|
21
23
|
name: method,
|
|
22
24
|
attributes: {
|
|
23
|
-
[
|
|
25
|
+
[attributes.SENTRY_OP]: op.RPC,
|
|
24
26
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: types.AGENT_SPAN_ORIGIN,
|
|
25
27
|
...types.getAgentAttributes(thisArg)
|
|
26
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentAgentCallableRpc.js","sources":["../../../../../src/instrumentations/agents/instrumentAgentCallableRpc.ts"],"sourcesContent":["import { debug,
|
|
1
|
+
{"version":3,"file":"instrumentAgentCallableRpc.js","sources":["../../../../../src/instrumentations/agents/instrumentAgentCallableRpc.ts"],"sourcesContent":["import { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { RPC } from '@sentry/conventions/op';\nimport { debug, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/core';\nimport { DEBUG_BUILD } from '../../debug-build';\nimport { AGENT_SPAN_ORIGIN, type AgentInternals, getAgentAttributes, setAgentConversationId } from './types';\n\n/**\n * Wraps the Agent's `onMessage` handler to create a span for each `@callable()` RPC invocation.\n * RPC requests arrive as WebSocket messages, so this span nests under the active transaction for\n * the WebSocket message (on Cloudflare, the instrumented Durable Object `webSocketMessage` hook).\n *\n * Also sets the conversation id on the scope for the duration of the call: callable methods are the\n * unit of work for plain (non-chat) agents, which run LLM calls just like chat turns do. It is\n * awaited so the id is on the scope before the method body creates any span; the `agents`\n * `onMessage` own property this wraps is already `async`, so the promise return is nothing new to\n * the WebSocket dispatch upstream.\n */\nexport function instrumentAgentCallableRpc(obj: AgentInternals): void {\n const original = obj.onMessage;\n if (typeof original !== 'function') {\n DEBUG_BUILD && debug.log('[Sentry] Agent `onMessage` not found — callable RPC span instrumentation skipped.');\n return;\n }\n\n obj.onMessage = new Proxy(original, {\n apply(target, thisArg: AgentInternals, args: unknown[]): unknown {\n const method = extractCallableMethod(args[1]);\n\n if (!method) {\n return Reflect.apply(target, thisArg, args);\n }\n\n return startSpan(\n {\n name: method,\n attributes: {\n [SENTRY_OP]: RPC,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: AGENT_SPAN_ORIGIN,\n ...getAgentAttributes(thisArg),\n },\n },\n async () => {\n await setAgentConversationId(thisArg);\n return Reflect.apply(target, thisArg, args);\n },\n );\n },\n });\n}\n\n/** Extracts the RPC method name from a WebSocket message, mirroring the SDK's `isRPCRequest`. */\nfunction extractCallableMethod(message: unknown): string | undefined {\n const text =\n typeof message === 'string'\n ? message\n : message instanceof ArrayBuffer\n ? new TextDecoder().decode(message)\n : undefined;\n\n if (!text) {\n return undefined;\n }\n\n try {\n const parsed = JSON.parse(text) as { type?: unknown; method?: unknown; args?: unknown };\n if (parsed.type === 'rpc' && typeof parsed.method === 'string' && Array.isArray(parsed.args)) {\n return parsed.method;\n }\n } catch {\n // Not JSON, or not an RPC request — no span.\n }\n\n return undefined;\n}\n"],"names":["DEBUG_BUILD","debug","startSpan","SENTRY_OP","RPC","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","AGENT_SPAN_ORIGIN","getAgentAttributes","setAgentConversationId"],"mappings":";;;;;;;;AAiBO,SAAS,2BAA2B,GAAA,EAA2B;AACpE,EAAA,MAAM,WAAW,GAAA,CAAI,SAAA;AACrB,EAAA,IAAI,OAAO,aAAa,UAAA,EAAY;AAClC,IAAAA,sBAAA,IAAeC,UAAA,CAAM,IAAI,wFAAmF,CAAA;AAC5G,IAAA;AAAA,EACF;AAEA,EAAA,GAAA,CAAI,SAAA,GAAY,IAAI,KAAA,CAAM,QAAA,EAAU;AAAA,IAClC,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAyB,IAAA,EAA0B;AAC/D,MAAA,MAAM,MAAA,GAAS,qBAAA,CAAsB,IAAA,CAAK,CAAC,CAAC,CAAA;AAE5C,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,MAC5C;AAEA,MAAA,OAAOC,cAAA;AAAA,QACL;AAAA,UACE,IAAA,EAAM,MAAA;AAAA,UACN,UAAA,EAAY;AAAA,YACV,CAACC,oBAAS,GAAGC,MAAA;AAAA,YACb,CAACC,qCAAgC,GAAGC,uBAAA;AAAA,YACpC,GAAGC,yBAAmB,OAAO;AAAA;AAC/B,SACF;AAAA,QACA,YAAY;AACV,UAAA,MAAMC,6BAAuB,OAAO,CAAA;AACpC,UAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,QAC5C;AAAA,OACF;AAAA,IACF;AAAA,GACD,CAAA;AACH;AAGA,SAAS,sBAAsB,OAAA,EAAsC;AACnE,EAAA,MAAM,IAAA,GACJ,OAAO,OAAA,KAAY,QAAA,GACf,OAAA,GACA,OAAA,YAAmB,WAAA,GACjB,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,OAAO,CAAA,GAChC,MAAA;AAER,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC9B,IAAA,IAAI,MAAA,CAAO,IAAA,KAAS,KAAA,IAAS,OAAO,MAAA,CAAO,MAAA,KAAW,QAAA,IAAY,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,EAAG;AAC5F,MAAA,OAAO,MAAA,CAAO,MAAA;AAAA,IAChB;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,OAAO,MAAA;AACT;;;;"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const op = require('@sentry/conventions/op');
|
|
4
|
+
const core = require('@sentry/core');
|
|
5
|
+
const debugBuild = require('../debug-build.js');
|
|
6
|
+
const instrument = require('../instrument.js');
|
|
7
|
+
const sdk = require('../sdk.js');
|
|
8
|
+
const wrapMethodWithSentry = require('../wrapMethodWithSentry.js');
|
|
9
|
+
const wrapRequestHandlerWithInit = require('../wrapRequestHandlerWithInit.js');
|
|
10
|
+
|
|
11
|
+
function instrumentDurableObjectHandlers(obj, options, context) {
|
|
12
|
+
if (obj.fetch && typeof obj.fetch === "function") {
|
|
13
|
+
setInstanceHandler(
|
|
14
|
+
obj,
|
|
15
|
+
"fetch",
|
|
16
|
+
instrument.ensureInstrumented(
|
|
17
|
+
obj.fetch.bind(obj),
|
|
18
|
+
(original) => new Proxy(original, {
|
|
19
|
+
apply(target, thisArg, args) {
|
|
20
|
+
return wrapRequestHandlerWithInit.wrapRequestHandlerWithInit(
|
|
21
|
+
{ options, request: args[0], context },
|
|
22
|
+
() => {
|
|
23
|
+
return Reflect.apply(target, thisArg, args);
|
|
24
|
+
},
|
|
25
|
+
sdk.init
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
if (obj.alarm && typeof obj.alarm === "function") {
|
|
33
|
+
setInstanceHandler(
|
|
34
|
+
obj,
|
|
35
|
+
"alarm",
|
|
36
|
+
wrapMethodWithSentry.wrapMethodWithSentry(
|
|
37
|
+
{
|
|
38
|
+
options,
|
|
39
|
+
context,
|
|
40
|
+
spanName: "alarm",
|
|
41
|
+
spanOp: op.FUNCTION,
|
|
42
|
+
startNewTrace: true,
|
|
43
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
44
|
+
},
|
|
45
|
+
obj.alarm.bind(obj)
|
|
46
|
+
)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
if (obj.webSocketMessage && typeof obj.webSocketMessage === "function") {
|
|
50
|
+
setInstanceHandler(
|
|
51
|
+
obj,
|
|
52
|
+
"webSocketMessage",
|
|
53
|
+
wrapMethodWithSentry.wrapMethodWithSentry(
|
|
54
|
+
{
|
|
55
|
+
options,
|
|
56
|
+
context,
|
|
57
|
+
spanName: "webSocketMessage",
|
|
58
|
+
spanOp: op.WEBSOCKET,
|
|
59
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
60
|
+
},
|
|
61
|
+
obj.webSocketMessage.bind(obj)
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (obj.webSocketClose && typeof obj.webSocketClose === "function") {
|
|
66
|
+
setInstanceHandler(
|
|
67
|
+
obj,
|
|
68
|
+
"webSocketClose",
|
|
69
|
+
wrapMethodWithSentry.wrapMethodWithSentry(
|
|
70
|
+
{
|
|
71
|
+
options,
|
|
72
|
+
context,
|
|
73
|
+
spanName: "webSocketClose",
|
|
74
|
+
spanOp: op.WEBSOCKET,
|
|
75
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
76
|
+
},
|
|
77
|
+
obj.webSocketClose.bind(obj)
|
|
78
|
+
)
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (obj.webSocketError && typeof obj.webSocketError === "function") {
|
|
82
|
+
setInstanceHandler(
|
|
83
|
+
obj,
|
|
84
|
+
"webSocketError",
|
|
85
|
+
wrapMethodWithSentry.wrapMethodWithSentry(
|
|
86
|
+
{
|
|
87
|
+
options,
|
|
88
|
+
context,
|
|
89
|
+
spanName: "webSocketError",
|
|
90
|
+
spanOp: op.WEBSOCKET,
|
|
91
|
+
origin: "auto.faas.cloudflare.durable_object"
|
|
92
|
+
},
|
|
93
|
+
obj.webSocketError.bind(obj),
|
|
94
|
+
(_, error) => core.captureException(error, {
|
|
95
|
+
mechanism: {
|
|
96
|
+
type: "auto.faas.cloudflare.durable_object_websocket",
|
|
97
|
+
handled: false
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
)
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function setInstanceHandler(obj, name, handler) {
|
|
105
|
+
const descriptor = Object.getOwnPropertyDescriptor(obj, name);
|
|
106
|
+
try {
|
|
107
|
+
if (descriptor?.writable === false) {
|
|
108
|
+
Object.defineProperty(obj, name, {
|
|
109
|
+
value: handler,
|
|
110
|
+
writable: true,
|
|
111
|
+
enumerable: descriptor.enumerable,
|
|
112
|
+
configurable: descriptor.configurable
|
|
113
|
+
});
|
|
114
|
+
} else {
|
|
115
|
+
obj[name] = handler;
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
debugBuild.DEBUG_BUILD && core.debug.warn(`Failed to instrument Durable Object handler "${name}"`, error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
exports.instrumentDurableObjectHandlers = instrumentDurableObjectHandlers;
|
|
123
|
+
//# sourceMappingURL=instrumentDurableObjectHandlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentDurableObjectHandlers.js","sources":["../../../../src/instrumentations/instrumentDurableObjectHandlers.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { FUNCTION, WEBSOCKET } from '@sentry/conventions/op';\nimport { captureException, debug } from '@sentry/core';\nimport type { DurableObject } from 'cloudflare:workers';\nimport type { CloudflareOptions } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { ensureInstrumented } from '../instrument';\nimport { init } from '../sdk';\nimport { wrapMethodWithSentry } from '../wrapMethodWithSentry';\nimport { wrapRequestHandlerWithInit } from '../wrapRequestHandlerWithInit';\n\n/**\n * The instrumented context of the Durable Object being wrapped.\n *\n * Kept as `any` for the same reason as in `durableobject.ts`: a concrete `DurableObjectState` here\n * makes `tsc` relate its `SqlStorage` graph against the parameter union of `wrapMethodWithSentry`,\n * which hangs the type build.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InstrumentedDurableObjectContext = any;\n\n/**\n * Instruments the built-in Durable Object handler methods on a constructed instance.\n *\n * These are the methods that are available on a Durable Object\n * ref: https://developers.cloudflare.com/durable-objects/api/base/\n * - obj.alarm\n * - obj.fetch\n * - obj.webSocketError\n * - obj.webSocketClose\n * - obj.webSocketMessage\n *\n * Any other public methods on the Durable Object instance are RPC calls.\n *\n * @internal\n */\nexport function instrumentDurableObjectHandlers<E, T extends DurableObject<E>>(\n obj: T,\n options: CloudflareOptions,\n context: InstrumentedDurableObjectContext,\n): void {\n // Bind each built-in handler to this instance before wrapping.\n // See https://github.com/getsentry/sentry-javascript/issues/22328\n if (obj.fetch && typeof obj.fetch === 'function') {\n setInstanceHandler(\n obj,\n 'fetch',\n ensureInstrumented(\n obj.fetch.bind(obj),\n original =>\n new Proxy(original, {\n apply(target, thisArg, args) {\n return wrapRequestHandlerWithInit(\n { options, request: args[0], context },\n () => {\n return Reflect.apply(target, thisArg, args);\n },\n init,\n );\n },\n }),\n ),\n );\n }\n\n if (obj.alarm && typeof obj.alarm === 'function') {\n // Alarms are independent invocations, so we start a new trace and link to the previous alarm\n setInstanceHandler(\n obj,\n 'alarm',\n wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'alarm',\n spanOp: FUNCTION,\n startNewTrace: true,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.alarm.bind(obj),\n ),\n );\n }\n\n if (obj.webSocketMessage && typeof obj.webSocketMessage === 'function') {\n setInstanceHandler(\n obj,\n 'webSocketMessage',\n wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'webSocketMessage',\n spanOp: WEBSOCKET,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.webSocketMessage.bind(obj),\n ),\n );\n }\n\n if (obj.webSocketClose && typeof obj.webSocketClose === 'function') {\n setInstanceHandler(\n obj,\n 'webSocketClose',\n wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'webSocketClose',\n spanOp: WEBSOCKET,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.webSocketClose.bind(obj),\n ),\n );\n }\n\n if (obj.webSocketError && typeof obj.webSocketError === 'function') {\n setInstanceHandler(\n obj,\n 'webSocketError',\n wrapMethodWithSentry(\n {\n options,\n context,\n spanName: 'webSocketError',\n spanOp: WEBSOCKET,\n origin: 'auto.faas.cloudflare.durable_object',\n },\n obj.webSocketError.bind(obj),\n (_, error) =>\n captureException(error, {\n mechanism: {\n type: 'auto.faas.cloudflare.durable_object_websocket',\n handled: false,\n },\n }),\n ),\n );\n }\n}\n\n/**\n * Installs an instrumented handler as an own property of the Durable Object instance.\n *\n * A plain assignment is not always possible. The `agents` package installs its handlers with\n * `Object.defineProperty(instance, name, { value, configurable: true })`, and `defineProperty`\n * leaves `writable` at `false`. Assigning to such a property throws a `TypeError` in strict mode,\n * so a read-only property is redefined instead. When the property can be neither assigned nor\n * redefined, the handler stays uninstrumented rather than breaking the object.\n */\nfunction setInstanceHandler(obj: object, name: string, handler: unknown): void {\n const descriptor = Object.getOwnPropertyDescriptor(obj, name);\n\n try {\n if (descriptor?.writable === false) {\n Object.defineProperty(obj, name, {\n value: handler,\n writable: true,\n enumerable: descriptor.enumerable,\n configurable: descriptor.configurable,\n });\n } else {\n (obj as Record<string, unknown>)[name] = handler;\n }\n } catch (error) {\n DEBUG_BUILD && debug.warn(`Failed to instrument Durable Object handler \"${name}\"`, error);\n }\n}\n"],"names":["ensureInstrumented","wrapRequestHandlerWithInit","init","wrapMethodWithSentry","FUNCTION","WEBSOCKET","captureException","DEBUG_BUILD","debug"],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
+
const attributes = require('@sentry/conventions/attributes');
|
|
4
|
+
const op = require('@sentry/conventions/op');
|
|
3
5
|
const core = require('@sentry/core');
|
|
4
6
|
const internalStorageKey = require('../utils/internalStorageKey.js');
|
|
5
7
|
const traceLinks = require('../utils/traceLinks.js');
|
|
@@ -34,8 +36,8 @@ function instrumentDurableObjectStorage(storage, waitUntil) {
|
|
|
34
36
|
{
|
|
35
37
|
// Use underscore naming to match Cloudflare's native instrumentation (e.g., "durable_object_storage_get")
|
|
36
38
|
name: `durable_object_storage_${methodName}`,
|
|
37
|
-
op: "db",
|
|
38
39
|
attributes: {
|
|
40
|
+
[attributes.SENTRY_OP]: op.DB,
|
|
39
41
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.db.cloudflare.durable_object",
|
|
40
42
|
"db.system.name": "cloudflare.durable_object.storage",
|
|
41
43
|
"db.operation.name": methodName
|