@sentry/cloudflare 11.0.0-beta.2 → 11.0.0-rc.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.
Files changed (95) hide show
  1. package/build/cjs/dev/index.js +4 -0
  2. package/build/cjs/dev/index.js.map +1 -1
  3. package/build/cjs/dev/instrumentations/worker/instrumentD1.js +19 -17
  4. package/build/cjs/dev/instrumentations/worker/instrumentD1.js.map +1 -1
  5. package/build/cjs/dev/instrumentations/worker/instrumentEmail.js +4 -3
  6. package/build/cjs/dev/instrumentations/worker/instrumentEmail.js.map +1 -1
  7. package/build/cjs/dev/instrumentations/worker/instrumentScheduled.js +10 -5
  8. package/build/cjs/dev/instrumentations/worker/instrumentScheduled.js.map +1 -1
  9. package/build/cjs/dev/orchestrion-deferred-channels.js +39 -0
  10. package/build/cjs/dev/orchestrion-deferred-channels.js.map +1 -0
  11. package/build/cjs/dev/orchestrion-diagnostics-channel.js +83 -0
  12. package/build/cjs/dev/orchestrion-diagnostics-channel.js.map +1 -0
  13. package/build/cjs/dev/vite/index.js +6 -1
  14. package/build/cjs/dev/vite/index.js.map +1 -1
  15. package/build/cjs/dev/vite/mastraObservability.js +39 -0
  16. package/build/cjs/dev/vite/mastraObservability.js.map +1 -0
  17. package/build/cjs/dev/wrapMethodWithSentry.js +8 -4
  18. package/build/cjs/dev/wrapMethodWithSentry.js.map +1 -1
  19. package/build/cjs/dev/wrapRequestHandlerWithInit.js +2 -0
  20. package/build/cjs/dev/wrapRequestHandlerWithInit.js.map +1 -1
  21. package/build/cjs/prod/index.js +4 -0
  22. package/build/cjs/prod/index.js.map +1 -1
  23. package/build/cjs/prod/instrumentations/worker/instrumentD1.js +19 -17
  24. package/build/cjs/prod/instrumentations/worker/instrumentD1.js.map +1 -1
  25. package/build/cjs/prod/instrumentations/worker/instrumentEmail.js +4 -3
  26. package/build/cjs/prod/instrumentations/worker/instrumentEmail.js.map +1 -1
  27. package/build/cjs/prod/instrumentations/worker/instrumentScheduled.js +10 -5
  28. package/build/cjs/prod/instrumentations/worker/instrumentScheduled.js.map +1 -1
  29. package/build/cjs/prod/orchestrion-deferred-channels.js +39 -0
  30. package/build/cjs/prod/orchestrion-deferred-channels.js.map +1 -0
  31. package/build/cjs/prod/orchestrion-diagnostics-channel.js +83 -0
  32. package/build/cjs/prod/orchestrion-diagnostics-channel.js.map +1 -0
  33. package/build/cjs/prod/vite/index.js +6 -1
  34. package/build/cjs/prod/vite/index.js.map +1 -1
  35. package/build/cjs/prod/vite/mastraObservability.js +39 -0
  36. package/build/cjs/prod/vite/mastraObservability.js.map +1 -0
  37. package/build/cjs/prod/wrapMethodWithSentry.js +8 -4
  38. package/build/cjs/prod/wrapMethodWithSentry.js.map +1 -1
  39. package/build/cjs/prod/wrapRequestHandlerWithInit.js +2 -0
  40. package/build/cjs/prod/wrapRequestHandlerWithInit.js.map +1 -1
  41. package/build/esm/dev/index.js +1 -1
  42. package/build/esm/dev/instrumentations/worker/instrumentD1.js +20 -18
  43. package/build/esm/dev/instrumentations/worker/instrumentD1.js.map +1 -1
  44. package/build/esm/dev/instrumentations/worker/instrumentEmail.js +6 -5
  45. package/build/esm/dev/instrumentations/worker/instrumentEmail.js.map +1 -1
  46. package/build/esm/dev/instrumentations/worker/instrumentScheduled.js +12 -7
  47. package/build/esm/dev/instrumentations/worker/instrumentScheduled.js.map +1 -1
  48. package/build/esm/dev/orchestrion-deferred-channels.js +35 -0
  49. package/build/esm/dev/orchestrion-deferred-channels.js.map +1 -0
  50. package/build/esm/dev/orchestrion-diagnostics-channel.js +77 -0
  51. package/build/esm/dev/orchestrion-diagnostics-channel.js.map +1 -0
  52. package/build/esm/dev/package.json +1 -1
  53. package/build/esm/dev/vite/index.js +6 -1
  54. package/build/esm/dev/vite/index.js.map +1 -1
  55. package/build/esm/dev/vite/mastraObservability.js +36 -0
  56. package/build/esm/dev/vite/mastraObservability.js.map +1 -0
  57. package/build/esm/dev/wrapMethodWithSentry.js +7 -3
  58. package/build/esm/dev/wrapMethodWithSentry.js.map +1 -1
  59. package/build/esm/dev/wrapRequestHandlerWithInit.js +2 -0
  60. package/build/esm/dev/wrapRequestHandlerWithInit.js.map +1 -1
  61. package/build/esm/prod/index.js +1 -1
  62. package/build/esm/prod/instrumentations/worker/instrumentD1.js +20 -18
  63. package/build/esm/prod/instrumentations/worker/instrumentD1.js.map +1 -1
  64. package/build/esm/prod/instrumentations/worker/instrumentEmail.js +6 -5
  65. package/build/esm/prod/instrumentations/worker/instrumentEmail.js.map +1 -1
  66. package/build/esm/prod/instrumentations/worker/instrumentScheduled.js +12 -7
  67. package/build/esm/prod/instrumentations/worker/instrumentScheduled.js.map +1 -1
  68. package/build/esm/prod/orchestrion-deferred-channels.js +35 -0
  69. package/build/esm/prod/orchestrion-deferred-channels.js.map +1 -0
  70. package/build/esm/prod/orchestrion-diagnostics-channel.js +77 -0
  71. package/build/esm/prod/orchestrion-diagnostics-channel.js.map +1 -0
  72. package/build/esm/prod/package.json +1 -1
  73. package/build/esm/prod/vite/index.js +6 -1
  74. package/build/esm/prod/vite/index.js.map +1 -1
  75. package/build/esm/prod/vite/mastraObservability.js +36 -0
  76. package/build/esm/prod/vite/mastraObservability.js.map +1 -0
  77. package/build/esm/prod/wrapMethodWithSentry.js +7 -3
  78. package/build/esm/prod/wrapMethodWithSentry.js.map +1 -1
  79. package/build/esm/prod/wrapRequestHandlerWithInit.js +2 -0
  80. package/build/esm/prod/wrapRequestHandlerWithInit.js.map +1 -1
  81. package/build/types/index.d.ts +2 -2
  82. package/build/types/index.d.ts.map +1 -1
  83. package/build/types/instrumentations/worker/instrumentD1.d.ts.map +1 -1
  84. package/build/types/instrumentations/worker/instrumentEmail.d.ts.map +1 -1
  85. package/build/types/instrumentations/worker/instrumentScheduled.d.ts.map +1 -1
  86. package/build/types/orchestrion-deferred-channels.d.ts +26 -0
  87. package/build/types/orchestrion-deferred-channels.d.ts.map +1 -0
  88. package/build/types/orchestrion-diagnostics-channel.d.ts +44 -0
  89. package/build/types/orchestrion-diagnostics-channel.d.ts.map +1 -0
  90. package/build/types/vite/index.d.ts.map +1 -1
  91. package/build/types/vite/mastraObservability.d.ts +27 -0
  92. package/build/types/vite/mastraObservability.d.ts.map +1 -0
  93. package/build/types/wrapMethodWithSentry.d.ts.map +1 -1
  94. package/build/types/wrapRequestHandlerWithInit.d.ts.map +1 -1
  95. package/package.json +10 -5
@@ -1 +1 @@
1
- {"version":3,"file":"wrapMethodWithSentry.js","sources":["../../../src/wrapMethodWithSentry.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport type { SerializedTraceData } from '@sentry/core';\nimport {\n isObjectLike,\n captureException,\n continueTrace,\n isThenable,\n type Scope,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startNewTrace as startNewTraceCore,\n startSpan,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport type { ExecutionContextCompat } from './executionContext';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { ensureInstrumented } from './instrument';\nimport { init } from './sdk';\nimport { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\nimport { extractRpcMeta } from './utils/rpcMeta';\nimport { buildSpanLinks, getStoredSpanContext, storeSpanContext } from './utils/traceLinks';\n\n/** Extended DurableObjectState with originalStorage exposed by instrumentContext */\nexport interface InstrumentedDurableObjectState extends DurableObjectState {\n originalStorage?: DurableObjectStorage;\n}\n\n/**\n * Resolves uninstrumented DO storage for the current invocation.\n * Prefer `thisArg.ctx` (the live Durable Object instance) over the context captured at\n * construction time to avoid cross-DO I/O errors in the same isolate.\n */\nfunction resolveOriginalStorage(\n context: ExecutionContext | InstrumentedDurableObjectState | undefined,\n thisArg: unknown,\n): DurableObjectStorage | undefined {\n if (isObjectLike(thisArg) && 'ctx' in thisArg) {\n const doCtx = (thisArg as { ctx: InstrumentedDurableObjectState }).ctx;\n if (doCtx?.originalStorage) {\n return doCtx.originalStorage;\n }\n }\n\n if (context && 'originalStorage' in context && context.originalStorage) {\n return context.originalStorage;\n }\n\n return undefined;\n}\n\ntype MethodWrapperOptions = {\n /**\n * The span name, or a resolver called with the RPC metadata of the current call.\n * Returning `undefined` skips the span and only captures errors.\n */\n spanName?: string | ((rpcMeta: SerializedTraceData | undefined) => string | undefined);\n spanOp?: string;\n options: CloudflareOptions;\n context: ExecutionContext | InstrumentedDurableObjectState;\n /**\n * If true, starts a fresh trace instead of inheriting from a parent trace.\n * Useful for scheduled/independent invocations like alarms.\n *\n * If true, it also stores the current span context and links to the previous invocation's span.\n * Uses Durable Object storage to persist the link. The link is set asynchronously via `span.addLinks()`\n * in a `waitUntil` to avoid blocking.\n *\n * @default false\n */\n startNewTrace?: boolean;\n /**\n * The trace origin identifying which instrumentation created the span, e.g. `auto.faas.cloudflare.durable_object`.\n * Used both as the span's `sentry.origin` attribute and as the `mechanism.type` for captured exceptions.\n */\n origin: string;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type UncheckedMethod = (...args: any[]) => any;\ntype OriginalMethod = UncheckedMethod;\n\n/**\n * Wraps a method with Sentry error tracking and optional tracing.\n * Supports starting new traces and linking to previous invocations via Durable Object storage.\n *\n * @param wrapperOptions - The options for the wrapper.\n * @param handler - The method to wrap.\n * @param callback - The callback to call.\n * @param noMark - Whether to mark the method as instrumented.\n * @returns The wrapped method.\n */\nexport function wrapMethodWithSentry<T extends OriginalMethod>(\n wrapperOptions: MethodWrapperOptions,\n handler: T,\n callback?: (...args: Parameters<T>) => void,\n noMark?: true,\n): T {\n return ensureInstrumented(\n handler,\n original =>\n new Proxy(original, {\n apply(target, thisArg, rawArgs: Parameters<T>) {\n const { startNewTrace, origin } = wrapperOptions;\n\n // For RPC methods, extract Sentry trace context from the trailing argument.\n // The caller side (instrumentDurableObjectStub / JSRPC proxy) appends it;\n // we strip it here so the user's method never sees it.\n let args = rawArgs;\n let rpcMeta: SerializedTraceData | undefined;\n\n if (wrapperOptions.spanOp === 'rpc') {\n const extracted = extractRpcMeta(rawArgs);\n args = extracted.args;\n rpcMeta = extracted.rpcMeta;\n }\n\n const spanName =\n typeof wrapperOptions.spanName === 'function' ? wrapperOptions.spanName(rpcMeta) : wrapperOptions.spanName;\n\n const wrappedFunction = (scope: Scope): unknown | Promise<unknown> => {\n // In certain situations, the passed context can become undefined.\n // For example, for Astro while prerendering pages at build time.\n // see: https://github.com/getsentry/sentry-javascript/issues/13217\n const context: typeof wrapperOptions.context | undefined = wrapperOptions.context;\n\n // see: https://github.com/getsentry/sentry-javascript/issues/22328\n // Resolved once per invocation and cached on its state: reading `ctx.waitUntil`\n // on a native context is a runtime getter call.\n const invocationState = getInvocationState();\n const waitUntil = invocationState\n ? getInvocationWaitUntil(invocationState)\n : context\n ? getOriginalWaitUntil(context as ExecutionContextCompat)?.bind(context)\n : undefined;\n const storage = resolveOriginalStorage(context, thisArg);\n\n let scopeClient = scope.getClient();\n // Re-init when the scope has no usable client (a previous handler disposed it, e.g.\n // DO alarm handlers) or for `startNewTrace`, so the client points at this\n // invocation's context. With `cacheClient: true` `init()` returns the isolate's\n // cached client and only creates (and caches) a fresh one when nothing is cached yet;\n // `cacheClient: false` creates one per invocation.\n if (startNewTrace || !scopeClient?.getTransport()) {\n const client = init({\n ...wrapperOptions.options,\n ctx: context as unknown as ExecutionContext | undefined,\n });\n scope.setClient(client);\n scopeClient = client;\n }\n\n const clientToDispose = scopeClient;\n const methodName = spanName || 'unknown';\n\n const teardown = async (): Promise<void> => {\n if (startNewTrace && storage) {\n storeSpanContext(storage, methodName);\n }\n await flushAndDispose(clientToDispose);\n };\n\n const onFulfilled = (res: unknown) => {\n waitUntil?.(teardown());\n return res;\n };\n\n const captureAndRethrow = (e: unknown): never => {\n captureException(e, {\n mechanism: {\n type: origin,\n handled: false,\n },\n });\n throw e;\n };\n\n const onRejected = (e: unknown) => {\n try {\n return captureAndRethrow(e);\n } finally {\n waitUntil?.(teardown());\n }\n };\n\n if (!spanName) {\n try {\n if (callback) {\n callback(...args);\n }\n\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(onFulfilled, onRejected);\n } else {\n return onFulfilled(result);\n }\n } catch (e) {\n return onRejected(e);\n }\n }\n\n const attributes = wrapperOptions.spanOp\n ? {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: wrapperOptions.spanOp,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin,\n }\n : {};\n\n const executeSpan = (): unknown => {\n return startSpan({ name: methodName, attributes }, span => {\n if (startNewTrace && storage) {\n const storedContext = getStoredSpanContext(storage, methodName);\n\n if (storedContext) {\n span.addLinks(buildSpanLinks(storedContext));\n // TODO: Remove this once EAP can store span links. We currently only set this attribute so that we\n // can obtain the previous trace information from the EAP store. Long-term, EAP will handle\n // span links and then we should remove this again. Also throwing in a TODO(v11), to remind us\n // to check this at v11 time :)\n const sampledFlag = storedContext.sampled ? '1' : '0';\n span.setAttribute(\n 'sentry.previous_trace',\n `${storedContext.traceId}-${storedContext.spanId}-${sampledFlag}`,\n );\n }\n }\n\n try {\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(undefined, captureAndRethrow);\n }\n return result;\n } catch (e) {\n return captureAndRethrow(e);\n }\n });\n };\n\n // The boundary flush (teardown) must run after the method span has ended, so the\n // span is in the buffer when that flush drains it. Running it inside the span\n // callback (before `startSpan` ends the span) would leave the span for the eager\n // path and cost a second flush per invocation.\n const runWithTeardown = (run: () => unknown): unknown => {\n let out: unknown;\n try {\n out = run();\n } catch (e) {\n // Synchronous throw: `startSpan` already ended the span and rethrew.\n waitUntil?.(teardown());\n throw e;\n }\n if (isThenable(out)) {\n return out.then(\n res => {\n waitUntil?.(teardown());\n return res;\n },\n e => {\n waitUntil?.(teardown());\n throw e;\n },\n );\n }\n waitUntil?.(teardown());\n return out;\n };\n\n if (rpcMeta) {\n return runWithTeardown(() =>\n continueTrace(\n { sentryTrace: rpcMeta['sentry-trace'] || '', baggage: rpcMeta.baggage || '' },\n executeSpan,\n ),\n );\n }\n\n if (startNewTrace) {\n return runWithTeardown(() => startNewTraceCore(() => executeSpan()));\n }\n\n return runWithTeardown(executeSpan);\n };\n\n return withInvocationIsolationScope(\n wrappedFunction,\n wrapperOptions.context as ExecutionContextCompat | undefined,\n );\n },\n }),\n noMark,\n );\n}\n"],"names":["isObjectLike","ensureInstrumented","rpcMeta","extractRpcMeta","getInvocationState","getInvocationWaitUntil","getOriginalWaitUntil","init","storeSpanContext","flushAndDispose","captureException","isThenable","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","startSpan","getStoredSpanContext","buildSpanLinks","continueTrace","startNewTraceCore","withInvocationIsolationScope"],"mappings":"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"}
1
+ {"version":3,"file":"wrapMethodWithSentry.js","sources":["../../../src/wrapMethodWithSentry.ts"],"sourcesContent":["import type { DurableObjectStorage } from '@cloudflare/workers-types';\nimport type { SerializedTraceData } from '@sentry/core';\nimport { CODE_FUNCTION_NAME, SENTRY_OP, SENTRY_ORIGIN } from '@sentry/conventions/attributes';\nimport { FUNCTION } from '@sentry/conventions/op';\nimport {\n isObjectLike,\n captureException,\n continueTrace,\n isThenable,\n type Scope,\n startNewTrace as startNewTraceCore,\n startSpan,\n} from '@sentry/core';\nimport type { CloudflareOptions } from './client';\nimport type { ExecutionContextCompat } from './executionContext';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { ensureInstrumented } from './instrument';\nimport { init } from './sdk';\nimport { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\nimport { extractRpcMeta } from './utils/rpcMeta';\nimport { buildSpanLinks, getStoredSpanContext, storeSpanContext } from './utils/traceLinks';\n\n/** Extended DurableObjectState with originalStorage exposed by instrumentContext */\nexport interface InstrumentedDurableObjectState extends DurableObjectState {\n originalStorage?: DurableObjectStorage;\n}\n\n/**\n * Resolves uninstrumented DO storage for the current invocation.\n * Prefer `thisArg.ctx` (the live Durable Object instance) over the context captured at\n * construction time to avoid cross-DO I/O errors in the same isolate.\n */\nfunction resolveOriginalStorage(\n context: ExecutionContext | InstrumentedDurableObjectState | undefined,\n thisArg: unknown,\n): DurableObjectStorage | undefined {\n if (isObjectLike(thisArg) && 'ctx' in thisArg) {\n const doCtx = (thisArg as { ctx: InstrumentedDurableObjectState }).ctx;\n if (doCtx?.originalStorage) {\n return doCtx.originalStorage;\n }\n }\n\n if (context && 'originalStorage' in context && context.originalStorage) {\n return context.originalStorage;\n }\n\n return undefined;\n}\n\ntype MethodWrapperOptions = {\n /**\n * The span name, or a resolver called with the RPC metadata of the current call.\n * Returning `undefined` skips the span and only captures errors.\n */\n spanName?: string | ((rpcMeta: SerializedTraceData | undefined) => string | undefined);\n spanOp?: string;\n options: CloudflareOptions;\n context: ExecutionContext | InstrumentedDurableObjectState;\n /**\n * If true, starts a fresh trace instead of inheriting from a parent trace.\n * Useful for scheduled/independent invocations like alarms.\n *\n * If true, it also stores the current span context and links to the previous invocation's span.\n * Uses Durable Object storage to persist the link. The link is set asynchronously via `span.addLinks()`\n * in a `waitUntil` to avoid blocking.\n *\n * @default false\n */\n startNewTrace?: boolean;\n /**\n * The trace origin identifying which instrumentation created the span, e.g. `auto.faas.cloudflare.durable_object`.\n * Used both as the span's `sentry.origin` attribute and as the `mechanism.type` for captured exceptions.\n */\n origin: string;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type UncheckedMethod = (...args: any[]) => any;\ntype OriginalMethod = UncheckedMethod;\n\n/**\n * Wraps a method with Sentry error tracking and optional tracing.\n * Supports starting new traces and linking to previous invocations via Durable Object storage.\n *\n * @param wrapperOptions - The options for the wrapper.\n * @param handler - The method to wrap.\n * @param callback - The callback to call.\n * @param noMark - Whether to mark the method as instrumented.\n * @returns The wrapped method.\n */\nexport function wrapMethodWithSentry<T extends OriginalMethod>(\n wrapperOptions: MethodWrapperOptions,\n handler: T,\n callback?: (...args: Parameters<T>) => void,\n noMark?: true,\n): T {\n return ensureInstrumented(\n handler,\n original =>\n new Proxy(original, {\n apply(target, thisArg, rawArgs: Parameters<T>) {\n const { startNewTrace, origin } = wrapperOptions;\n\n // For RPC methods, extract Sentry trace context from the trailing argument.\n // The caller side (instrumentDurableObjectStub / JSRPC proxy) appends it;\n // we strip it here so the user's method never sees it.\n let args = rawArgs;\n let rpcMeta: SerializedTraceData | undefined;\n\n if (wrapperOptions.spanOp === 'rpc') {\n const extracted = extractRpcMeta(rawArgs);\n args = extracted.args;\n rpcMeta = extracted.rpcMeta;\n }\n\n const spanName =\n typeof wrapperOptions.spanName === 'function' ? wrapperOptions.spanName(rpcMeta) : wrapperOptions.spanName;\n\n const wrappedFunction = (scope: Scope): unknown | Promise<unknown> => {\n // In certain situations, the passed context can become undefined.\n // For example, for Astro while prerendering pages at build time.\n // see: https://github.com/getsentry/sentry-javascript/issues/13217\n const context: typeof wrapperOptions.context | undefined = wrapperOptions.context;\n\n // see: https://github.com/getsentry/sentry-javascript/issues/22328\n // Resolved once per invocation and cached on its state: reading `ctx.waitUntil`\n // on a native context is a runtime getter call.\n const invocationState = getInvocationState();\n const waitUntil = invocationState\n ? getInvocationWaitUntil(invocationState)\n : context\n ? getOriginalWaitUntil(context as ExecutionContextCompat)?.bind(context)\n : undefined;\n const storage = resolveOriginalStorage(context, thisArg);\n\n let scopeClient = scope.getClient();\n // Re-init when the scope has no usable client (a previous handler disposed it, e.g.\n // DO alarm handlers) or for `startNewTrace`, so the client points at this\n // invocation's context. With `cacheClient: true` `init()` returns the isolate's\n // cached client and only creates (and caches) a fresh one when nothing is cached yet;\n // `cacheClient: false` creates one per invocation.\n if (startNewTrace || !scopeClient?.getTransport()) {\n const client = init({\n ...wrapperOptions.options,\n ctx: context as unknown as ExecutionContext | undefined,\n });\n scope.setClient(client);\n scopeClient = client;\n }\n\n const clientToDispose = scopeClient;\n const methodName = spanName || 'unknown';\n\n const teardown = async (): Promise<void> => {\n if (startNewTrace && storage) {\n storeSpanContext(storage, methodName);\n }\n await flushAndDispose(clientToDispose);\n };\n\n const onFulfilled = (res: unknown) => {\n waitUntil?.(teardown());\n return res;\n };\n\n const captureAndRethrow = (e: unknown): never => {\n captureException(e, {\n mechanism: {\n type: origin,\n handled: false,\n },\n });\n throw e;\n };\n\n const onRejected = (e: unknown) => {\n try {\n return captureAndRethrow(e);\n } finally {\n waitUntil?.(teardown());\n }\n };\n\n if (!spanName) {\n try {\n if (callback) {\n callback(...args);\n }\n\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(onFulfilled, onRejected);\n } else {\n return onFulfilled(result);\n }\n } catch (e) {\n return onRejected(e);\n }\n }\n\n const attributes = wrapperOptions.spanOp\n ? {\n [SENTRY_OP]: wrapperOptions.spanOp,\n [SENTRY_ORIGIN]: origin,\n // `function` spans are already named like their function name, so we just set `code.function.name` here.\n ...(wrapperOptions.spanOp === FUNCTION && { [CODE_FUNCTION_NAME]: methodName }),\n }\n : {};\n\n const executeSpan = (): unknown => {\n return startSpan({ name: methodName, attributes }, span => {\n if (startNewTrace && storage) {\n const storedContext = getStoredSpanContext(storage, methodName);\n\n if (storedContext) {\n span.addLinks(buildSpanLinks(storedContext));\n // TODO(v12): Remove this once the Sentry trace view finds linked traces via span links.\n // EAP stores span links, but the trace view still reads this attribute to navigate to the\n // previous/next trace.\n const sampledFlag = storedContext.sampled ? '1' : '0';\n span.setAttribute(\n 'sentry.previous_trace',\n `${storedContext.traceId}-${storedContext.spanId}-${sampledFlag}`,\n );\n }\n }\n\n try {\n const result = Reflect.apply(target, thisArg, args);\n\n if (isThenable(result)) {\n return result.then(undefined, captureAndRethrow);\n }\n return result;\n } catch (e) {\n return captureAndRethrow(e);\n }\n });\n };\n\n // The boundary flush (teardown) must run after the method span has ended, so the\n // span is in the buffer when that flush drains it. Running it inside the span\n // callback (before `startSpan` ends the span) would leave the span for the eager\n // path and cost a second flush per invocation.\n const runWithTeardown = (run: () => unknown): unknown => {\n let out: unknown;\n try {\n out = run();\n } catch (e) {\n // Synchronous throw: `startSpan` already ended the span and rethrew.\n waitUntil?.(teardown());\n throw e;\n }\n if (isThenable(out)) {\n return out.then(\n res => {\n waitUntil?.(teardown());\n return res;\n },\n e => {\n waitUntil?.(teardown());\n throw e;\n },\n );\n }\n waitUntil?.(teardown());\n return out;\n };\n\n if (rpcMeta) {\n return runWithTeardown(() =>\n continueTrace(\n { sentryTrace: rpcMeta['sentry-trace'] || '', baggage: rpcMeta.baggage || '' },\n executeSpan,\n ),\n );\n }\n\n if (startNewTrace) {\n return runWithTeardown(() => startNewTraceCore(() => executeSpan()));\n }\n\n return runWithTeardown(executeSpan);\n };\n\n return withInvocationIsolationScope(\n wrappedFunction,\n wrapperOptions.context as ExecutionContextCompat | undefined,\n );\n },\n }),\n noMark,\n );\n}\n"],"names":["isObjectLike","ensureInstrumented","rpcMeta","extractRpcMeta","getInvocationState","getInvocationWaitUntil","getOriginalWaitUntil","init","storeSpanContext","flushAndDispose","captureException","isThenable","attributes","SENTRY_OP","SENTRY_ORIGIN","FUNCTION","CODE_FUNCTION_NAME","startSpan","getStoredSpanContext","buildSpanLinks","continueTrace","startNewTraceCore","withInvocationIsolationScope"],"mappings":"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"}
@@ -4,6 +4,7 @@ const attributes = require('@sentry/conventions/attributes');
4
4
  const op = require('@sentry/conventions/op');
5
5
  const core = require('@sentry/core');
6
6
  const httpServer = require('./integrations/httpServer.js');
7
+ const orchestrionDeferredChannels = require('./orchestrion-deferred-channels.js');
7
8
  const flush = require('./flush.js');
8
9
  const scopeUtils = require('./scope-utils.js');
9
10
  const invocationContext = require('./utils/invocationContext.js');
@@ -22,6 +23,7 @@ function wrapRequestHandlerWithInit(wrapperOptions, handler, initSdk) {
22
23
  const errorMechanismType = getRequestErrorMechanismType(context);
23
24
  const client = initSdk({ ...options, ctx: context });
24
25
  isolationScope.setClient(client);
26
+ orchestrionDeferredChannels.flushDeferredChannelEvents();
25
27
  const urlObject = core.parseStringToURLObject(request.url);
26
28
  const [rawName, attributes$1] = core.getHttpSpanDetailsFromUrlObject(
27
29
  urlObject,
@@ -1 +1 @@
1
- {"version":3,"file":"wrapRequestHandlerWithInit.js","sources":["../../../src/wrapRequestHandlerWithInit.ts"],"sourcesContent":["import type { CfProperties, IncomingRequestCfProperties } from '@cloudflare/workers-types';\nimport {\n NETWORK_PROTOCOL_NAME,\n NETWORK_PROTOCOL_VERSION,\n SENTRY_OP,\n SENTRY_SEGMENT_NAME_SOURCE,\n} from '@sentry/conventions/attributes';\nimport { HTTP_SERVER } from '@sentry/conventions/op';\nimport {\n captureException,\n continueTrace,\n getHttpSpanDetailsFromUrlObject,\n hasSpanStreamingEnabled,\n httpHeadersToSpanAttributes,\n HTTP_SPAN_NAME_FALLBACK,\n parseStringToURLObject,\n setHttpStatus,\n startSpanManual,\n winterCGHeadersToDict,\n} from '@sentry/core';\nimport { captureIncomingRequestBody } from './integrations/httpServer';\nimport type { CloudflareClient, CloudflareOptions } from './client';\nimport type { ExecutionContextCompat } from './executionContext';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { addCloudResourceContext, addCultureContext, addRequest } from './scope-utils';\nimport { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\nimport { classifyResponseStreaming } from './utils/streaming';\n\nfunction getRequestErrorMechanismType(context: ExecutionContextCompat | undefined): string {\n // Durable Object fetch handlers use DO state as context (see instrumentDurableObjectWithSentry)\n return context && 'storage' in context ? 'auto.faas.cloudflare.durable_object' : 'auto.http.cloudflare';\n}\n\nexport interface RequestHandlerWrapperOptions {\n options: CloudflareOptions;\n request: Request<unknown, IncomingRequestCfProperties<unknown> | CfProperties<unknown>>;\n context: ExecutionContextCompat | undefined;\n /**\n * If true, errors will be captured, rethrown and sent to Sentry.\n * Otherwise, errors are rethrown but not captured.\n *\n * You most likely don't want to set this to `false`, if you use `wrapRequestHandler` directly.\n * This is primarily meant as an escape hatch for higher-level SDKs relying on additional error\n * capturing mechanisms where this wrapper captures errors too early or too generally.\n *\n * @default true\n */\n captureErrors?: boolean;\n}\n\ntype InitSdk = (options: CloudflareOptions) => CloudflareClient | undefined;\n\n/**\n * Same as {@link wrapRequestHandler}, but with the SDK initialization injected.\n *\n * Wrappers that are only reachable from the main entry point — where `nodejs_compat` is a\n * requirement anyway — pass `init` from `sdk.ts` to get the full default integrations.\n *\n * @internal\n */\nexport function wrapRequestHandlerWithInit(\n wrapperOptions: RequestHandlerWrapperOptions,\n handler: (...args: unknown[]) => Response | Promise<Response>,\n initSdk: InitSdk,\n): Promise<Response> {\n return withInvocationIsolationScope(async isolationScope => {\n const { options, request, captureErrors = true } = wrapperOptions;\n const context = wrapperOptions.context;\n\n // The un-instrumented waitUntil, so flushAndDispose cannot deadlock on the flush\n // lock's own wrapper. Resolved once per invocation and cached on its state; reading\n // `ctx.waitUntil` on a native context is a runtime getter call.\n const invocationState = getInvocationState();\n const waitUntil = invocationState\n ? getInvocationWaitUntil(invocationState)\n : context\n ? getOriginalWaitUntil(context).bind(context)\n : undefined;\n const errorMechanismType = getRequestErrorMechanismType(context);\n\n const client = initSdk({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n const urlObject = parseStringToURLObject(request.url);\n const [rawName, attributes] = getHttpSpanDetailsFromUrlObject(\n urlObject,\n 'server',\n 'auto.http.cloudflare',\n request,\n undefined,\n client,\n );\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL.\n // A `route` source means the name already is (e.g. the `/` path), so it is kept as-is.\n const name =\n attributes[SENTRY_SEGMENT_NAME_SOURCE] === 'route' || !client || !hasSpanStreamingEnabled(client)\n ? rawName\n : request.method?.toUpperCase() || HTTP_SPAN_NAME_FALLBACK;\n\n const contentLength = request.headers.get('content-length');\n if (contentLength) {\n attributes['http.request.body.size'] = parseInt(contentLength, 10);\n }\n\n const userAgentHeader = request.headers.get('user-agent');\n if (userAgentHeader) {\n attributes['user_agent.original'] = userAgentHeader;\n }\n\n if (client) {\n Object.assign(\n attributes,\n httpHeadersToSpanAttributes(winterCGHeadersToDict(request.headers), client.getDataCollectionOptions()),\n );\n }\n\n attributes[SENTRY_OP] = HTTP_SERVER;\n\n addCloudResourceContext(isolationScope);\n addRequest(isolationScope, request);\n if (request.cf) {\n addCultureContext(isolationScope, request.cf);\n\n if (typeof request.cf.httpProtocol === 'string') {\n const [protocolName, protocolVersion] = request.cf.httpProtocol.toLowerCase().split('/');\n attributes[NETWORK_PROTOCOL_NAME] = protocolName;\n attributes[NETWORK_PROTOCOL_VERSION] = protocolVersion;\n }\n }\n\n // Do not capture spans for OPTIONS and HEAD requests\n if (request.method === 'OPTIONS' || request.method === 'HEAD') {\n try {\n return await handler();\n } catch (e) {\n if (captureErrors) {\n captureException(e, { mechanism: { handled: false, type: errorMechanismType } });\n }\n throw e;\n } finally {\n waitUntil?.(flushAndDispose(client));\n }\n }\n\n if (client) {\n await captureIncomingRequestBody(client, request);\n }\n\n return continueTrace(\n { sentryTrace: request.headers.get('sentry-trace') || '', baggage: request.headers.get('baggage') },\n () => {\n // Note: This span will not have a duration unless I/O happens in the handler. This is\n // because of how the cloudflare workers runtime works.\n // See: https://developers.cloudflare.com/workers/runtime-apis/performance/\n\n // Use startSpanManual to control when span ends (needed for streaming responses)\n return startSpanManual({ name, attributes }, async span => {\n let res: Response;\n\n try {\n res = await handler();\n setHttpStatus(span, res.status);\n\n // After the handler runs, the span name might have been updated by nested instrumentation\n // (e.g., Remix parameterizing routes). The span should already have the correct name\n // from that instrumentation, so we don't need to do anything here.\n } catch (e) {\n span.end();\n if (captureErrors) {\n captureException(e, { mechanism: { handled: false, type: errorMechanismType } });\n }\n waitUntil?.(flushAndDispose(client));\n throw e;\n }\n\n // Classify response to detect actual streaming\n const classification = classifyResponseStreaming(res);\n\n if (classification.isStreaming && res.body) {\n try {\n let ended = false;\n\n const endSpanOnce = (): void => {\n if (ended) return;\n\n ended = true;\n span.end();\n waitUntil?.(flushAndDispose(client));\n };\n\n const transform = new TransformStream({\n flush() {\n // Source stream completed normally.\n endSpanOnce();\n },\n cancel() {\n // Client disconnected (or downstream cancelled). The `cancel`\n // is being called while the response is still considered\n // active, so this is a safe place to end the span.\n endSpanOnce();\n },\n });\n\n return new Response(res.body.pipeThrough(transform), {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n });\n } catch {\n span.end();\n waitUntil?.(flushAndDispose(client));\n return res;\n }\n }\n\n // Non-streaming response - end span immediately and return original\n span.end();\n\n // Don't dispose for protocol upgrades (101 Switching Protocols) - the connection stays alive.\n // This includes WebSocket upgrades where webSocketMessage/webSocketClose handlers\n // will still be called and may need the client to capture errors.\n if (res.status === 101) {\n waitUntil?.(client?.flush(2000));\n } else {\n waitUntil?.(flushAndDispose(client));\n }\n return res;\n });\n },\n );\n }, wrapperOptions.context);\n}\n"],"names":["withInvocationIsolationScope","getInvocationState","getInvocationWaitUntil","getOriginalWaitUntil","parseStringToURLObject","attributes","getHttpSpanDetailsFromUrlObject","SENTRY_SEGMENT_NAME_SOURCE","hasSpanStreamingEnabled","HTTP_SPAN_NAME_FALLBACK","httpHeadersToSpanAttributes","winterCGHeadersToDict","SENTRY_OP","HTTP_SERVER","addCloudResourceContext","addRequest","addCultureContext","NETWORK_PROTOCOL_NAME","NETWORK_PROTOCOL_VERSION","captureException","flushAndDispose","captureIncomingRequestBody","continueTrace","startSpanManual","setHttpStatus","classifyResponseStreaming"],"mappings":"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"}
1
+ {"version":3,"file":"wrapRequestHandlerWithInit.js","sources":["../../../src/wrapRequestHandlerWithInit.ts"],"sourcesContent":["import type { CfProperties, IncomingRequestCfProperties } from '@cloudflare/workers-types';\nimport {\n NETWORK_PROTOCOL_NAME,\n NETWORK_PROTOCOL_VERSION,\n SENTRY_OP,\n SENTRY_SEGMENT_NAME_SOURCE,\n} from '@sentry/conventions/attributes';\nimport { HTTP_SERVER } from '@sentry/conventions/op';\nimport {\n captureException,\n continueTrace,\n getHttpSpanDetailsFromUrlObject,\n hasSpanStreamingEnabled,\n httpHeadersToSpanAttributes,\n HTTP_SPAN_NAME_FALLBACK,\n parseStringToURLObject,\n setHttpStatus,\n startSpanManual,\n winterCGHeadersToDict,\n} from '@sentry/core';\nimport { captureIncomingRequestBody } from './integrations/httpServer';\nimport { flushDeferredChannelEvents } from './orchestrion-deferred-channels';\nimport type { CloudflareClient, CloudflareOptions } from './client';\nimport type { ExecutionContextCompat } from './executionContext';\nimport { flushAndDispose, getOriginalWaitUntil } from './flush';\nimport { addCloudResourceContext, addCultureContext, addRequest } from './scope-utils';\nimport { getInvocationState, getInvocationWaitUntil } from './utils/invocationContext';\nimport { withInvocationIsolationScope } from './utils/invocationScope';\nimport { classifyResponseStreaming } from './utils/streaming';\n\nfunction getRequestErrorMechanismType(context: ExecutionContextCompat | undefined): string {\n // Durable Object fetch handlers use DO state as context (see instrumentDurableObjectWithSentry)\n return context && 'storage' in context ? 'auto.faas.cloudflare.durable_object' : 'auto.http.cloudflare';\n}\n\nexport interface RequestHandlerWrapperOptions {\n options: CloudflareOptions;\n request: Request<unknown, IncomingRequestCfProperties<unknown> | CfProperties<unknown>>;\n context: ExecutionContextCompat | undefined;\n /**\n * If true, errors will be captured, rethrown and sent to Sentry.\n * Otherwise, errors are rethrown but not captured.\n *\n * You most likely don't want to set this to `false`, if you use `wrapRequestHandler` directly.\n * This is primarily meant as an escape hatch for higher-level SDKs relying on additional error\n * capturing mechanisms where this wrapper captures errors too early or too generally.\n *\n * @default true\n */\n captureErrors?: boolean;\n}\n\ntype InitSdk = (options: CloudflareOptions) => CloudflareClient | undefined;\n\n/**\n * Same as {@link wrapRequestHandler}, but with the SDK initialization injected.\n *\n * Wrappers that are only reachable from the main entry point — where `nodejs_compat` is a\n * requirement anyway — pass `init` from `sdk.ts` to get the full default integrations.\n *\n * @internal\n */\nexport function wrapRequestHandlerWithInit(\n wrapperOptions: RequestHandlerWrapperOptions,\n handler: (...args: unknown[]) => Response | Promise<Response>,\n initSdk: InitSdk,\n): Promise<Response> {\n return withInvocationIsolationScope(async isolationScope => {\n const { options, request, captureErrors = true } = wrapperOptions;\n const context = wrapperOptions.context;\n\n // The un-instrumented waitUntil, so flushAndDispose cannot deadlock on the flush\n // lock's own wrapper. Resolved once per invocation and cached on its state; reading\n // `ctx.waitUntil` on a native context is a runtime getter call.\n const invocationState = getInvocationState();\n const waitUntil = invocationState\n ? getInvocationWaitUntil(invocationState)\n : context\n ? getOriginalWaitUntil(context).bind(context)\n : undefined;\n const errorMechanismType = getRequestErrorMechanismType(context);\n\n const client = initSdk({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n // Emit any orchestrion channel events deferred at module scope (e.g. a top-level\n // `const app = new Hono()` wrapped by build-time instrumentation): we're now in a\n // request, where workerd allows publish, and init() above has registered subscribers.\n flushDeferredChannelEvents();\n\n const urlObject = parseStringToURLObject(request.url);\n const [rawName, attributes] = getHttpSpanDetailsFromUrlObject(\n urlObject,\n 'server',\n 'auto.http.cloudflare',\n request,\n undefined,\n client,\n );\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL.\n // A `route` source means the name already is (e.g. the `/` path), so it is kept as-is.\n const name =\n attributes[SENTRY_SEGMENT_NAME_SOURCE] === 'route' || !client || !hasSpanStreamingEnabled(client)\n ? rawName\n : request.method?.toUpperCase() || HTTP_SPAN_NAME_FALLBACK;\n\n const contentLength = request.headers.get('content-length');\n if (contentLength) {\n attributes['http.request.body.size'] = parseInt(contentLength, 10);\n }\n\n const userAgentHeader = request.headers.get('user-agent');\n if (userAgentHeader) {\n attributes['user_agent.original'] = userAgentHeader;\n }\n\n if (client) {\n Object.assign(\n attributes,\n httpHeadersToSpanAttributes(winterCGHeadersToDict(request.headers), client.getDataCollectionOptions()),\n );\n }\n\n attributes[SENTRY_OP] = HTTP_SERVER;\n\n addCloudResourceContext(isolationScope);\n addRequest(isolationScope, request);\n if (request.cf) {\n addCultureContext(isolationScope, request.cf);\n\n if (typeof request.cf.httpProtocol === 'string') {\n const [protocolName, protocolVersion] = request.cf.httpProtocol.toLowerCase().split('/');\n attributes[NETWORK_PROTOCOL_NAME] = protocolName;\n attributes[NETWORK_PROTOCOL_VERSION] = protocolVersion;\n }\n }\n\n // Do not capture spans for OPTIONS and HEAD requests\n if (request.method === 'OPTIONS' || request.method === 'HEAD') {\n try {\n return await handler();\n } catch (e) {\n if (captureErrors) {\n captureException(e, { mechanism: { handled: false, type: errorMechanismType } });\n }\n throw e;\n } finally {\n waitUntil?.(flushAndDispose(client));\n }\n }\n\n if (client) {\n await captureIncomingRequestBody(client, request);\n }\n\n return continueTrace(\n { sentryTrace: request.headers.get('sentry-trace') || '', baggage: request.headers.get('baggage') },\n () => {\n // Note: This span will not have a duration unless I/O happens in the handler. This is\n // because of how the cloudflare workers runtime works.\n // See: https://developers.cloudflare.com/workers/runtime-apis/performance/\n\n // Use startSpanManual to control when span ends (needed for streaming responses)\n return startSpanManual({ name, attributes }, async span => {\n let res: Response;\n\n try {\n res = await handler();\n setHttpStatus(span, res.status);\n\n // After the handler runs, the span name might have been updated by nested instrumentation\n // (e.g., Remix parameterizing routes). The span should already have the correct name\n // from that instrumentation, so we don't need to do anything here.\n } catch (e) {\n span.end();\n if (captureErrors) {\n captureException(e, { mechanism: { handled: false, type: errorMechanismType } });\n }\n waitUntil?.(flushAndDispose(client));\n throw e;\n }\n\n // Classify response to detect actual streaming\n const classification = classifyResponseStreaming(res);\n\n if (classification.isStreaming && res.body) {\n try {\n let ended = false;\n\n const endSpanOnce = (): void => {\n if (ended) return;\n\n ended = true;\n span.end();\n waitUntil?.(flushAndDispose(client));\n };\n\n const transform = new TransformStream({\n flush() {\n // Source stream completed normally.\n endSpanOnce();\n },\n cancel() {\n // Client disconnected (or downstream cancelled). The `cancel`\n // is being called while the response is still considered\n // active, so this is a safe place to end the span.\n endSpanOnce();\n },\n });\n\n return new Response(res.body.pipeThrough(transform), {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n });\n } catch {\n span.end();\n waitUntil?.(flushAndDispose(client));\n return res;\n }\n }\n\n // Non-streaming response - end span immediately and return original\n span.end();\n\n // Don't dispose for protocol upgrades (101 Switching Protocols) - the connection stays alive.\n // This includes WebSocket upgrades where webSocketMessage/webSocketClose handlers\n // will still be called and may need the client to capture errors.\n if (res.status === 101) {\n waitUntil?.(client?.flush(2000));\n } else {\n waitUntil?.(flushAndDispose(client));\n }\n return res;\n });\n },\n );\n }, wrapperOptions.context);\n}\n"],"names":["withInvocationIsolationScope","getInvocationState","getInvocationWaitUntil","getOriginalWaitUntil","flushDeferredChannelEvents","parseStringToURLObject","attributes","getHttpSpanDetailsFromUrlObject","SENTRY_SEGMENT_NAME_SOURCE","hasSpanStreamingEnabled","HTTP_SPAN_NAME_FALLBACK","httpHeadersToSpanAttributes","winterCGHeadersToDict","SENTRY_OP","HTTP_SERVER","addCloudResourceContext","addRequest","addCultureContext","NETWORK_PROTOCOL_NAME","NETWORK_PROTOCOL_VERSION","captureException","flushAndDispose","captureIncomingRequestBody","continueTrace","startSpanManual","setHttpStatus","classifyResponseStreaming"],"mappings":"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"}
@@ -100,12 +100,16 @@ exports.withStreamedSpan = core.withStreamedSpan;
100
100
  exports.zodErrorsIntegration = core.zodErrorsIntegration;
101
101
  exports.trpcMiddleware = server.trpcMiddleware;
102
102
  exports.wrapMcpServerWithSentry = server.wrapMcpServerWithSentry;
103
+ exports.createFlueInstrumentation = serverUtils.createFlueInstrumentation;
103
104
  exports.createLangChainCallbackHandler = serverUtils.createLangChainCallbackHandler;
105
+ exports.eveConversationHook = serverUtils.eveConversationHook;
106
+ exports.getInstrumentedModuleNames = serverUtils.getInstrumentedModuleNames;
104
107
  exports.getOtlpTracesEndpoint = serverUtils.getOtlpTracesEndpoint;
105
108
  exports.instrumentAnthropicAiClient = serverUtils.instrumentAnthropicAiClient;
106
109
  exports.instrumentCreateReactAgent = serverUtils.instrumentCreateReactAgent;
107
110
  exports.instrumentGoogleGenAIClient = serverUtils.instrumentGoogleGenAIClient;
108
111
  exports.instrumentLangChainEmbeddings = serverUtils.instrumentLangChainEmbeddings;
112
+ exports.instrumentMistralAiClient = serverUtils.instrumentMistralAiClient;
109
113
  exports.instrumentOpenAiClient = serverUtils.instrumentOpenAiClient;
110
114
  exports.instrumentPostgresJsSql = serverUtils.instrumentPostgresJsSql;
111
115
  exports.instrumentStateGraph = serverUtils.instrumentStateGraph;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -11,40 +11,41 @@ function instrumentD1PreparedStatementQueries(statement, query) {
11
11
  if (patchedStatement.has(statement)) {
12
12
  return statement;
13
13
  }
14
+ const queryText = query ? serverUtils.sanitizeSqlQuery(query) : void 0;
14
15
  statement.first = new Proxy(statement.first, {
15
16
  apply(target, thisArg, args) {
16
- return core.startSpan(createStartSpanOptions(query, "first"), async () => {
17
+ return core.startSpan(createStartSpanOptions(queryText, "first"), async () => {
17
18
  const res = await Reflect.apply(target, thisArg, args);
18
- createD1Breadcrumb(query, "first");
19
+ createD1Breadcrumb(queryText, "first");
19
20
  return res;
20
21
  });
21
22
  }
22
23
  });
23
24
  statement.run = new Proxy(statement.run, {
24
25
  apply(target, thisArg, args) {
25
- return core.startSpan(createStartSpanOptions(query, "run"), async (span) => {
26
+ return core.startSpan(createStartSpanOptions(queryText, "run"), async (span) => {
26
27
  const d1Response = await Reflect.apply(target, thisArg, args);
27
28
  applyD1ReturnObjectToSpan(span, d1Response);
28
- createD1Breadcrumb(query, "run", d1Response);
29
+ createD1Breadcrumb(queryText, "run", d1Response);
29
30
  return d1Response;
30
31
  });
31
32
  }
32
33
  });
33
34
  statement.all = new Proxy(statement.all, {
34
35
  apply(target, thisArg, args) {
35
- return core.startSpan(createStartSpanOptions(query, "all"), async (span) => {
36
+ return core.startSpan(createStartSpanOptions(queryText, "all"), async (span) => {
36
37
  const d1Result = await Reflect.apply(target, thisArg, args);
37
38
  applyD1ReturnObjectToSpan(span, d1Result);
38
- createD1Breadcrumb(query, "all", d1Result);
39
+ createD1Breadcrumb(queryText, "all", d1Result);
39
40
  return d1Result;
40
41
  });
41
42
  }
42
43
  });
43
44
  statement.raw = new Proxy(statement.raw, {
44
45
  apply(target, thisArg, args) {
45
- return core.startSpan(createStartSpanOptions(query, "raw"), async () => {
46
+ return core.startSpan(createStartSpanOptions(queryText, "raw"), async () => {
46
47
  const res = await Reflect.apply(target, thisArg, args);
47
- createD1Breadcrumb(query, "raw");
48
+ createD1Breadcrumb(queryText, "raw");
48
49
  return res;
49
50
  });
50
51
  }
@@ -73,27 +74,27 @@ function getAttributesFromD1Response(d1Result) {
73
74
  "cloudflare.d1.rows_written": d1Result.meta.rows_written
74
75
  };
75
76
  }
76
- function createD1Breadcrumb(query, type, d1Result) {
77
+ function createD1Breadcrumb(message, type, d1Result) {
77
78
  core.addBreadcrumb({
78
79
  category: "query",
79
- message: query,
80
+ message,
80
81
  data: {
81
82
  ...d1Result ? getAttributesFromD1Response(d1Result) : {},
82
83
  "db.operation.name": type
83
84
  }
84
85
  });
85
86
  }
86
- function createStartSpanOptions(query, type) {
87
- const querySummary = query ? serverUtils.getSqlQuerySummary(serverUtils.sanitizeSqlQuery(query)) : void 0;
87
+ function createStartSpanOptions(queryText, type) {
88
+ const querySummary = queryText ? serverUtils.getSqlQuerySummary(queryText) : void 0;
88
89
  const client = core.getClient();
89
- const name = client && core.hasSpanStreamingEnabled(client) ? querySummary || "cloudflare-d1" : query;
90
+ const name = client && core.hasSpanStreamingEnabled(client) ? querySummary || "cloudflare-d1" : queryText ?? "cloudflare-d1";
90
91
  return {
91
92
  name,
92
93
  attributes: {
93
94
  [attributes.SENTRY_OP]: op.DB_QUERY,
94
95
  "db.system.name": "cloudflare-d1",
95
96
  "db.operation.name": type,
96
- "db.query.text": query,
97
+ "db.query.text": queryText,
97
98
  "db.query.summary": querySummary,
98
99
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.db.cloudflare.d1"
99
100
  }
@@ -111,7 +112,7 @@ function instrumentBatch(batch) {
111
112
  return new Proxy(batch, {
112
113
  apply(target, thisArg, args) {
113
114
  const statements = args[0];
114
- const queryText = statements.map((statement) => statement.statement ?? "").filter(Boolean).join("\n");
115
+ const queryText = statements.map((statement) => statement.statement ?? "").filter(Boolean).map((statement) => serverUtils.sanitizeSqlQuery(statement)).join("\n");
115
116
  return core.startSpan(
116
117
  {
117
118
  name: "D1 batch",
@@ -144,9 +145,10 @@ function _instrumentD1(db) {
144
145
  db.exec = new Proxy(db.exec, {
145
146
  apply(target, thisArg, args) {
146
147
  const [query] = args;
147
- return core.startSpan(createStartSpanOptions(query, "exec"), async () => {
148
+ const queryText = query ? serverUtils.sanitizeSqlQuery(query) : void 0;
149
+ return core.startSpan(createStartSpanOptions(queryText, "exec"), async () => {
148
150
  const res = await Reflect.apply(target, thisArg, args);
149
- createD1Breadcrumb(query, "exec");
151
+ createD1Breadcrumb(queryText, "exec");
150
152
  return res;
151
153
  });
152
154
  }
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentD1.js","sources":["../../../../../src/instrumentations/worker/instrumentD1.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport type { D1Database, D1DatabaseSession, D1PreparedStatement, D1Response } from '@cloudflare/workers-types';\nimport { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { DB_QUERY } from '@sentry/conventions/op';\nimport type { Span, SpanAttributes, StartSpanOptions } from '@sentry/core';\nimport {\n addBreadcrumb,\n getClient,\n hasSpanStreamingEnabled,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n startSpan,\n} from '@sentry/core';\nimport { getSqlQuerySummary, sanitizeSqlQuery } from '@sentry/server-utils';\nimport { ensureInstrumented } from '../../instrument';\n\n// Patching is based on internal Cloudflare D1 API\n// https://github.com/cloudflare/workerd/blob/cd5279e7b305003f1d9c851e73efa9d67e4b68b2/src/cloudflare/internal/d1-api.ts\n\nconst patchedStatement = new WeakSet<D1PreparedStatement>();\n\n/**\n * Patches the query methods of a Cloudflare D1 prepared statement with Sentry.\n */\nfunction instrumentD1PreparedStatementQueries(statement: D1PreparedStatement, query: string): D1PreparedStatement {\n if (patchedStatement.has(statement)) {\n return statement;\n }\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n statement.first = new Proxy(statement.first, {\n apply(target, thisArg, args: Parameters<typeof statement.first>) {\n return startSpan(createStartSpanOptions(query, 'first'), async () => {\n const res = await Reflect.apply(target, thisArg, args);\n createD1Breadcrumb(query, 'first');\n return res;\n });\n },\n });\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n statement.run = new Proxy(statement.run, {\n apply(target, thisArg, args: Parameters<typeof statement.run>) {\n return startSpan(createStartSpanOptions(query, 'run'), async span => {\n const d1Response = await Reflect.apply(target, thisArg, args);\n applyD1ReturnObjectToSpan(span, d1Response);\n createD1Breadcrumb(query, 'run', d1Response);\n return d1Response;\n });\n },\n });\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n statement.all = new Proxy(statement.all, {\n apply(target, thisArg, args: Parameters<typeof statement.all>) {\n return startSpan(createStartSpanOptions(query, 'all'), async span => {\n const d1Result = await Reflect.apply(target, thisArg, args);\n applyD1ReturnObjectToSpan(span, d1Result);\n createD1Breadcrumb(query, 'all', d1Result);\n return d1Result;\n });\n },\n });\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n statement.raw = new Proxy(statement.raw, {\n apply(target, thisArg, args: Parameters<typeof statement.raw>) {\n return startSpan(createStartSpanOptions(query, 'raw'), async () => {\n const res = await Reflect.apply(target, thisArg, args);\n createD1Breadcrumb(query, 'raw');\n return res;\n });\n },\n });\n\n patchedStatement.add(statement);\n\n return statement;\n}\n\n/**\n * Instruments a Cloudflare D1 prepared statement with Sentry.\n *\n * This is meant to be used as a top-level call, under the hood it calls `instrumentD1PreparedStatementQueries`\n * to patch the query methods. The reason for this abstraction is to ensure that the `bind` method is also patched.\n */\nfunction instrumentD1PreparedStatement(statement: D1PreparedStatement, query: string): D1PreparedStatement {\n // statement.bind() returns a new instance of D1PreparedStatement, so we have to patch it as well.\n // eslint-disable-next-line @typescript-eslint/unbound-method\n statement.bind = new Proxy(statement.bind, {\n apply(target, thisArg, args: Parameters<typeof statement.bind>) {\n return instrumentD1PreparedStatementQueries(Reflect.apply(target, thisArg, args), query);\n },\n });\n\n return instrumentD1PreparedStatementQueries(statement, query);\n}\n\n/**\n * Add D1Response meta information to a span.\n *\n * See: https://developers.cloudflare.com/d1/build-with-d1/d1-client-api/#return-object\n */\nfunction applyD1ReturnObjectToSpan(span: Span, d1Result: D1Response): void {\n if (!d1Result.success) {\n span.setStatus({ code: SPAN_STATUS_ERROR });\n }\n\n span.setAttributes(getAttributesFromD1Response(d1Result));\n}\n\nfunction getAttributesFromD1Response(d1Result: D1Response): SpanAttributes {\n return {\n 'cloudflare.d1.duration': d1Result.meta.duration,\n 'cloudflare.d1.rows_read': d1Result.meta.rows_read,\n 'cloudflare.d1.rows_written': d1Result.meta.rows_written,\n };\n}\n\ntype D1QueryType = 'first' | 'run' | 'all' | 'raw' | 'batch' | 'exec';\n\nfunction createD1Breadcrumb(query: string, type: D1QueryType, d1Result?: D1Response): void {\n addBreadcrumb({\n category: 'query',\n message: query,\n data: {\n ...(d1Result ? getAttributesFromD1Response(d1Result) : {}),\n 'db.operation.name': type,\n },\n });\n}\n\nfunction createStartSpanOptions(query: string, type: D1QueryType): StartSpanOptions {\n const querySummary = query ? getSqlQuerySummary(sanitizeSqlQuery(query)) : undefined;\n\n const client = getClient();\n const name = client && hasSpanStreamingEnabled(client) ? querySummary || 'cloudflare-d1' : query;\n\n return {\n name,\n attributes: {\n [SENTRY_OP]: DB_QUERY,\n 'db.system.name': 'cloudflare-d1',\n 'db.operation.name': type,\n 'db.query.text': query,\n 'db.query.summary': querySummary,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.cloudflare.d1',\n },\n };\n}\n\nfunction instrumentPrepare(\n prepare: D1Database['prepare'] | D1DatabaseSession['prepare'],\n): D1Database['prepare'] | D1DatabaseSession['prepare'] {\n return new Proxy(prepare, {\n apply(target, thisArg, args: Parameters<typeof prepare>) {\n const [query] = args;\n return instrumentD1PreparedStatement(Reflect.apply(target, thisArg, args), query);\n },\n });\n}\n\nfunction instrumentBatch(\n batch: D1Database['batch'] | D1DatabaseSession['batch'],\n): D1Database['batch'] | D1DatabaseSession['batch'] {\n return new Proxy(batch, {\n apply(target, thisArg, args: Parameters<typeof batch>) {\n const statements = args[0];\n // D1PreparedStatement exposes a `statement` property at runtime, but it's not in @cloudflare/workers-types.\n // https://github.com/cloudflare/workerd/blob/dc12d7650b4f5d4f9ba6a47aa45fad769cdf8db4/src/cloudflare/internal/d1-api.ts#L210\n const queryText = statements\n .map(statement => (statement as unknown as { statement?: string }).statement ?? '')\n .filter(Boolean)\n .join('\\n');\n\n return startSpan(\n {\n name: 'D1 batch',\n attributes: {\n [SENTRY_OP]: DB_QUERY,\n 'db.system.name': 'cloudflare-d1',\n 'db.operation.name': 'batch',\n 'db.query.text': queryText || undefined,\n 'db.operation.batch.size': statements.length,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.cloudflare.d1',\n },\n },\n async () => {\n const res = await Reflect.apply(target, thisArg, args);\n createD1Breadcrumb('D1 batch', 'batch');\n return res;\n },\n );\n },\n });\n}\n\nfunction instrumentD1Session(session: D1DatabaseSession): D1DatabaseSession {\n session.prepare = instrumentPrepare(session.prepare);\n session.batch = instrumentBatch(session.batch);\n return session;\n}\n\nfunction _instrumentD1(db: D1Database): D1Database {\n db.prepare = instrumentPrepare(db.prepare);\n db.batch = instrumentBatch(db.batch);\n\n db.exec = new Proxy(db.exec, {\n apply(target, thisArg, args: Parameters<typeof db.exec>) {\n const [query] = args;\n return startSpan(createStartSpanOptions(query, 'exec'), async () => {\n const res = await Reflect.apply(target, thisArg, args);\n createD1Breadcrumb(query, 'exec');\n return res;\n });\n },\n });\n\n if ('withSession' in db && typeof db.withSession === 'function') {\n db.withSession = new Proxy(db.withSession, {\n apply(target, thisArg, args: [unknown]) {\n return instrumentD1Session(Reflect.apply(target, thisArg, args) as D1DatabaseSession);\n },\n });\n }\n\n return db;\n}\n\nexport function instrumentD1(db: D1Database): D1Database {\n return ensureInstrumented(db, _instrumentD1);\n}\n"],"names":["startSpan","SPAN_STATUS_ERROR","addBreadcrumb","getSqlQuerySummary","sanitizeSqlQuery","getClient","hasSpanStreamingEnabled","SENTRY_OP","DB_QUERY","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","ensureInstrumented"],"mappings":"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"}
1
+ {"version":3,"file":"instrumentD1.js","sources":["../../../../../src/instrumentations/worker/instrumentD1.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport type { D1Database, D1DatabaseSession, D1PreparedStatement, D1Response } from '@cloudflare/workers-types';\nimport { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { DB_QUERY } from '@sentry/conventions/op';\nimport type { Span, SpanAttributes, StartSpanOptions } from '@sentry/core';\nimport {\n addBreadcrumb,\n getClient,\n hasSpanStreamingEnabled,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n startSpan,\n} from '@sentry/core';\nimport { getSqlQuerySummary, sanitizeSqlQuery } from '@sentry/server-utils';\nimport { ensureInstrumented } from '../../instrument';\n\n// Patching is based on internal Cloudflare D1 API\n// https://github.com/cloudflare/workerd/blob/cd5279e7b305003f1d9c851e73efa9d67e4b68b2/src/cloudflare/internal/d1-api.ts\n\nconst patchedStatement = new WeakSet<D1PreparedStatement>();\n\n/**\n * Patches the query methods of a Cloudflare D1 prepared statement with Sentry.\n */\nfunction instrumentD1PreparedStatementQueries(statement: D1PreparedStatement, query: string): D1PreparedStatement {\n if (patchedStatement.has(statement)) {\n return statement;\n }\n\n const queryText = query ? sanitizeSqlQuery(query) : undefined;\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n statement.first = new Proxy(statement.first, {\n apply(target, thisArg, args: Parameters<typeof statement.first>) {\n return startSpan(createStartSpanOptions(queryText, 'first'), async () => {\n const res = await Reflect.apply(target, thisArg, args);\n createD1Breadcrumb(queryText, 'first');\n return res;\n });\n },\n });\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n statement.run = new Proxy(statement.run, {\n apply(target, thisArg, args: Parameters<typeof statement.run>) {\n return startSpan(createStartSpanOptions(queryText, 'run'), async span => {\n const d1Response = await Reflect.apply(target, thisArg, args);\n applyD1ReturnObjectToSpan(span, d1Response);\n createD1Breadcrumb(queryText, 'run', d1Response);\n return d1Response;\n });\n },\n });\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n statement.all = new Proxy(statement.all, {\n apply(target, thisArg, args: Parameters<typeof statement.all>) {\n return startSpan(createStartSpanOptions(queryText, 'all'), async span => {\n const d1Result = await Reflect.apply(target, thisArg, args);\n applyD1ReturnObjectToSpan(span, d1Result);\n createD1Breadcrumb(queryText, 'all', d1Result);\n return d1Result;\n });\n },\n });\n\n // eslint-disable-next-line @typescript-eslint/unbound-method\n statement.raw = new Proxy(statement.raw, {\n apply(target, thisArg, args: Parameters<typeof statement.raw>) {\n return startSpan(createStartSpanOptions(queryText, 'raw'), async () => {\n const res = await Reflect.apply(target, thisArg, args);\n createD1Breadcrumb(queryText, 'raw');\n return res;\n });\n },\n });\n\n patchedStatement.add(statement);\n\n return statement;\n}\n\n/**\n * Instruments a Cloudflare D1 prepared statement with Sentry.\n *\n * This is meant to be used as a top-level call, under the hood it calls `instrumentD1PreparedStatementQueries`\n * to patch the query methods. The reason for this abstraction is to ensure that the `bind` method is also patched.\n */\nfunction instrumentD1PreparedStatement(statement: D1PreparedStatement, query: string): D1PreparedStatement {\n // statement.bind() returns a new instance of D1PreparedStatement, so we have to patch it as well.\n // eslint-disable-next-line @typescript-eslint/unbound-method\n statement.bind = new Proxy(statement.bind, {\n apply(target, thisArg, args: Parameters<typeof statement.bind>) {\n return instrumentD1PreparedStatementQueries(Reflect.apply(target, thisArg, args), query);\n },\n });\n\n return instrumentD1PreparedStatementQueries(statement, query);\n}\n\n/**\n * Add D1Response meta information to a span.\n *\n * See: https://developers.cloudflare.com/d1/build-with-d1/d1-client-api/#return-object\n */\nfunction applyD1ReturnObjectToSpan(span: Span, d1Result: D1Response): void {\n if (!d1Result.success) {\n span.setStatus({ code: SPAN_STATUS_ERROR });\n }\n\n span.setAttributes(getAttributesFromD1Response(d1Result));\n}\n\nfunction getAttributesFromD1Response(d1Result: D1Response): SpanAttributes {\n return {\n 'cloudflare.d1.duration': d1Result.meta.duration,\n 'cloudflare.d1.rows_read': d1Result.meta.rows_read,\n 'cloudflare.d1.rows_written': d1Result.meta.rows_written,\n };\n}\n\ntype D1QueryType = 'first' | 'run' | 'all' | 'raw' | 'batch' | 'exec';\n\n/** The message is the span's query text (already sanitized) or a static label such as `D1 batch`. */\nfunction createD1Breadcrumb(message: string | undefined, type: D1QueryType, d1Result?: D1Response): void {\n addBreadcrumb({\n category: 'query',\n message,\n data: {\n ...(d1Result ? getAttributesFromD1Response(d1Result) : {}),\n 'db.operation.name': type,\n },\n });\n}\n\nfunction createStartSpanOptions(queryText: string | undefined, type: D1QueryType): StartSpanOptions {\n const querySummary = queryText ? getSqlQuerySummary(queryText) : undefined;\n\n const client = getClient();\n const name =\n client && hasSpanStreamingEnabled(client) ? querySummary || 'cloudflare-d1' : (queryText ?? 'cloudflare-d1');\n\n return {\n name,\n attributes: {\n [SENTRY_OP]: DB_QUERY,\n 'db.system.name': 'cloudflare-d1',\n 'db.operation.name': type,\n 'db.query.text': queryText,\n 'db.query.summary': querySummary,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.cloudflare.d1',\n },\n };\n}\n\nfunction instrumentPrepare(\n prepare: D1Database['prepare'] | D1DatabaseSession['prepare'],\n): D1Database['prepare'] | D1DatabaseSession['prepare'] {\n return new Proxy(prepare, {\n apply(target, thisArg, args: Parameters<typeof prepare>) {\n const [query] = args;\n return instrumentD1PreparedStatement(Reflect.apply(target, thisArg, args), query);\n },\n });\n}\n\nfunction instrumentBatch(\n batch: D1Database['batch'] | D1DatabaseSession['batch'],\n): D1Database['batch'] | D1DatabaseSession['batch'] {\n return new Proxy(batch, {\n apply(target, thisArg, args: Parameters<typeof batch>) {\n const statements = args[0];\n // D1PreparedStatement exposes a `statement` property at runtime, but it's not in @cloudflare/workers-types.\n // https://github.com/cloudflare/workerd/blob/dc12d7650b4f5d4f9ba6a47aa45fad769cdf8db4/src/cloudflare/internal/d1-api.ts#L210\n const queryText = statements\n .map(statement => (statement as unknown as { statement?: string }).statement ?? '')\n .filter(Boolean)\n .map(statement => sanitizeSqlQuery(statement))\n .join('\\n');\n\n return startSpan(\n {\n name: 'D1 batch',\n attributes: {\n [SENTRY_OP]: DB_QUERY,\n 'db.system.name': 'cloudflare-d1',\n 'db.operation.name': 'batch',\n 'db.query.text': queryText || undefined,\n 'db.operation.batch.size': statements.length,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.cloudflare.d1',\n },\n },\n async () => {\n const res = await Reflect.apply(target, thisArg, args);\n createD1Breadcrumb('D1 batch', 'batch');\n return res;\n },\n );\n },\n });\n}\n\nfunction instrumentD1Session(session: D1DatabaseSession): D1DatabaseSession {\n session.prepare = instrumentPrepare(session.prepare);\n session.batch = instrumentBatch(session.batch);\n return session;\n}\n\nfunction _instrumentD1(db: D1Database): D1Database {\n db.prepare = instrumentPrepare(db.prepare);\n db.batch = instrumentBatch(db.batch);\n\n db.exec = new Proxy(db.exec, {\n apply(target, thisArg, args: Parameters<typeof db.exec>) {\n const [query] = args;\n const queryText = query ? sanitizeSqlQuery(query) : undefined;\n return startSpan(createStartSpanOptions(queryText, 'exec'), async () => {\n const res = await Reflect.apply(target, thisArg, args);\n createD1Breadcrumb(queryText, 'exec');\n return res;\n });\n },\n });\n\n if ('withSession' in db && typeof db.withSession === 'function') {\n db.withSession = new Proxy(db.withSession, {\n apply(target, thisArg, args: [unknown]) {\n return instrumentD1Session(Reflect.apply(target, thisArg, args) as D1DatabaseSession);\n },\n });\n }\n\n return db;\n}\n\nexport function instrumentD1(db: D1Database): D1Database {\n return ensureInstrumented(db, _instrumentD1);\n}\n"],"names":["sanitizeSqlQuery","startSpan","SPAN_STATUS_ERROR","addBreadcrumb","getSqlQuerySummary","getClient","hasSpanStreamingEnabled","SENTRY_OP","DB_QUERY","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","ensureInstrumented"],"mappings":"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"}
@@ -21,11 +21,12 @@ function wrapEmailHandler(emailMessage, options, context, fn) {
21
21
  scopeUtils.addCloudResourceContext(isolationScope);
22
22
  return core.startSpan(
23
23
  {
24
- name: `Handle Email ${emailMessage.to}`,
24
+ name: "email",
25
25
  attributes: {
26
26
  [attributes.SENTRY_OP]: op.FUNCTION,
27
- "faas.trigger": "email",
28
- [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.faas.cloudflare.email",
27
+ [attributes.CODE_FUNCTION_NAME]: "email",
28
+ [attributes.FAAS_TRIGGER]: "email",
29
+ [attributes.SENTRY_ORIGIN]: "auto.faas.cloudflare.email",
29
30
  [attributes.SENTRY_SEGMENT_NAME_SOURCE]: "task"
30
31
  }
31
32
  },
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentEmail.js","sources":["../../../../../src/instrumentations/worker/instrumentEmail.ts"],"sourcesContent":["import type { EmailMessage } from '@cloudflare/workers-types';\nimport type { AnyExportedHandler } from '../../types';\nimport type { env as cloudflareEnv } from 'cloudflare:workers';\nimport { SENTRY_SEGMENT_NAME_SOURCE, SENTRY_OP } from '@sentry/conventions/attributes';\nimport { FUNCTION } from '@sentry/conventions/op';\nimport { captureException, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan, withIsolationScope } from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { ensureInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\nimport { setInvocationState } from '../../utils/invocationContext';\nimport { instrumentEnv } from './instrumentEnv';\n\n/**\n * Core email handler logic - wraps execution with Sentry instrumentation.\n */\nfunction wrapEmailHandler(\n emailMessage: EmailMessage,\n options: CloudflareOptions,\n context: ExecutionContext,\n fn: () => unknown,\n): unknown {\n return withIsolationScope(isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n setInvocationState(isolationScope, { ctx: context });\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return startSpan(\n {\n name: `Handle Email ${emailMessage.to}`,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n 'faas.trigger': 'email',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.email',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'task',\n },\n },\n async () => {\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.email' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n },\n );\n });\n}\n\n/**\n * Instruments an email handler for ExportedHandler (env/ctx come from args).\n */\nexport function instrumentExportedHandlerEmail<T extends AnyExportedHandler>(\n handler: T,\n optionsCallback: (env: typeof cloudflareEnv) => CloudflareOptions | undefined,\n): void {\n if (!('email' in handler) || typeof handler.email !== 'function') {\n return;\n }\n\n handler.email = ensureInstrumented(\n handler.email,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<NonNullable<T['email']>>) {\n const [emailMessage, env, ctx] = args;\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n args[1] = instrumentEnv(env, options);\n args[2] = context;\n\n return wrapEmailHandler(emailMessage, options, context, () => target.apply(thisArg, args));\n },\n }),\n );\n}\n"],"names":["withIsolationScope","setInvocationState","init","addCloudResourceContext","startSpan","SENTRY_OP","FUNCTION","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SENTRY_SEGMENT_NAME_SOURCE","captureException","flushAndDispose","ensureInstrumented","instrumentContext","options","getFinalOptions","instrumentEnv"],"mappings":";;;;;;;;;;;;;;AAmBA,SAAS,gBAAA,CACP,YAAA,EACA,OAAA,EACA,OAAA,EACA,EAAA,EACS;AACT,EAAA,OAAOA,wBAAmB,CAAA,cAAA,KAAkB;AAC1C,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA;AAEhD,IAAAC,oCAAA,CAAmB,cAAA,EAAgB,EAAE,GAAA,EAAK,OAAA,EAAS,CAAA;AAEnD,IAAA,MAAM,SAASC,QAAA,CAAK,EAAE,GAAG,OAAA,EAAS,GAAA,EAAK,SAAS,CAAA;AAChD,IAAA,cAAA,CAAe,UAAU,MAAM,CAAA;AAE/B,IAAAC,kCAAA,CAAwB,cAAc,CAAA;AAEtC,IAAA,OAAOC,cAAA;AAAA,MACL;AAAA,QACE,IAAA,EAAM,CAAA,aAAA,EAAgB,YAAA,CAAa,EAAE,CAAA,CAAA;AAAA,QACrC,UAAA,EAAY;AAAA,UACV,CAACC,oBAAS,GAAGC,WAAA;AAAA,UACb,cAAA,EAAgB,OAAA;AAAA,UAChB,CAACC,qCAAgC,GAAG,4BAAA;AAAA,UACpC,CAACC,qCAA0B,GAAG;AAAA;AAChC,OACF;AAAA,MACA,YAAY;AACV,QAAA,IAAI;AACF,UAAA,OAAO,MAAM,EAAA,EAAG;AAAA,QAClB,SAAS,CAAA,EAAG;AACV,UAAAC,qBAAA,CAAiB,CAAA,EAAG,EAAE,SAAA,EAAW,EAAE,SAAS,KAAA,EAAO,IAAA,EAAM,4BAAA,EAA6B,EAAG,CAAA;AACzF,UAAA,MAAM,CAAA;AAAA,QACR,CAAA,SAAE;AACA,UAAA,SAAA,CAAUC,qBAAA,CAAgB,MAAM,CAAC,CAAA;AAAA,QACnC;AAAA,MACF;AAAA,KACF;AAAA,EACF,CAAC,CAAA;AACH;AAKO,SAAS,8BAAA,CACd,SACA,eAAA,EACM;AACN,EAAA,IAAI,EAAE,OAAA,IAAW,OAAA,CAAA,IAAY,OAAO,OAAA,CAAQ,UAAU,UAAA,EAAY;AAChE,IAAA;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,KAAA,GAAQC,6BAAA;AAAA,IACd,OAAA,CAAQ,KAAA;AAAA,IACR,CAAA,QAAA,KACE,IAAI,KAAA,CAAM,QAAA,EAAU;AAAA,MAClB,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,IAAA,EAA2C;AAChE,QAAA,MAAM,CAAC,YAAA,EAAc,GAAA,EAAK,GAAG,CAAA,GAAI,IAAA;AACjC,QAAA,MAAM,OAAA,GAAUC,oCAAkB,GAAG,CAAA;AACrC,QAAA,MAAMC,SAAA,GAAUC,uBAAA,CAAgB,eAAA,CAAgB,GAAG,GAAG,GAAG,CAAA;AACzD,QAAA,IAAA,CAAK,CAAC,CAAA,GAAIC,2BAAA,CAAc,GAAA,EAAKF,SAAO,CAAA;AACpC,QAAA,IAAA,CAAK,CAAC,CAAA,GAAI,OAAA;AAEV,QAAA,OAAO,gBAAA,CAAiB,cAAcA,SAAA,EAAS,OAAA,EAAS,MAAM,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,IAAI,CAAC,CAAA;AAAA,MAC3F;AAAA,KACD;AAAA,GACL;AACF;;;;"}
1
+ {"version":3,"file":"instrumentEmail.js","sources":["../../../../../src/instrumentations/worker/instrumentEmail.ts"],"sourcesContent":["import type { EmailMessage } from '@cloudflare/workers-types';\nimport type { AnyExportedHandler } from '../../types';\nimport type { env as cloudflareEnv } from 'cloudflare:workers';\nimport {\n SENTRY_SEGMENT_NAME_SOURCE,\n CODE_FUNCTION_NAME,\n SENTRY_OP,\n FAAS_TRIGGER,\n SENTRY_ORIGIN,\n} from '@sentry/conventions/attributes';\nimport { FUNCTION } from '@sentry/conventions/op';\nimport { captureException, startSpan, withIsolationScope } from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { ensureInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\nimport { setInvocationState } from '../../utils/invocationContext';\nimport { instrumentEnv } from './instrumentEnv';\n\n/**\n * Core email handler logic - wraps execution with Sentry instrumentation.\n */\nfunction wrapEmailHandler(\n emailMessage: EmailMessage,\n options: CloudflareOptions,\n context: ExecutionContext,\n fn: () => unknown,\n): unknown {\n return withIsolationScope(isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n setInvocationState(isolationScope, { ctx: context });\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return startSpan(\n {\n name: 'email',\n attributes: {\n [SENTRY_OP]: FUNCTION,\n [CODE_FUNCTION_NAME]: 'email',\n [FAAS_TRIGGER]: 'email',\n [SENTRY_ORIGIN]: 'auto.faas.cloudflare.email',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'task',\n },\n },\n async () => {\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.email' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n },\n );\n });\n}\n\n/**\n * Instruments an email handler for ExportedHandler (env/ctx come from args).\n */\nexport function instrumentExportedHandlerEmail<T extends AnyExportedHandler>(\n handler: T,\n optionsCallback: (env: typeof cloudflareEnv) => CloudflareOptions | undefined,\n): void {\n if (!('email' in handler) || typeof handler.email !== 'function') {\n return;\n }\n\n handler.email = ensureInstrumented(\n handler.email,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<NonNullable<T['email']>>) {\n const [emailMessage, env, ctx] = args;\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n args[1] = instrumentEnv(env, options);\n args[2] = context;\n\n return wrapEmailHandler(emailMessage, options, context, () => target.apply(thisArg, args));\n },\n }),\n );\n}\n"],"names":["withIsolationScope","setInvocationState","init","addCloudResourceContext","startSpan","SENTRY_OP","FUNCTION","CODE_FUNCTION_NAME","FAAS_TRIGGER","SENTRY_ORIGIN","SENTRY_SEGMENT_NAME_SOURCE","captureException","flushAndDispose","ensureInstrumented","instrumentContext","options","getFinalOptions","instrumentEnv"],"mappings":";;;;;;;;;;;;;;AAyBA,SAAS,gBAAA,CACP,YAAA,EACA,OAAA,EACA,OAAA,EACA,EAAA,EACS;AACT,EAAA,OAAOA,wBAAmB,CAAA,cAAA,KAAkB;AAC1C,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA;AAEhD,IAAAC,oCAAA,CAAmB,cAAA,EAAgB,EAAE,GAAA,EAAK,OAAA,EAAS,CAAA;AAEnD,IAAA,MAAM,SAASC,QAAA,CAAK,EAAE,GAAG,OAAA,EAAS,GAAA,EAAK,SAAS,CAAA;AAChD,IAAA,cAAA,CAAe,UAAU,MAAM,CAAA;AAE/B,IAAAC,kCAAA,CAAwB,cAAc,CAAA;AAEtC,IAAA,OAAOC,cAAA;AAAA,MACL;AAAA,QACE,IAAA,EAAM,OAAA;AAAA,QACN,UAAA,EAAY;AAAA,UACV,CAACC,oBAAS,GAAGC,WAAA;AAAA,UACb,CAACC,6BAAkB,GAAG,OAAA;AAAA,UACtB,CAACC,uBAAY,GAAG,OAAA;AAAA,UAChB,CAACC,wBAAa,GAAG,4BAAA;AAAA,UACjB,CAACC,qCAA0B,GAAG;AAAA;AAChC,OACF;AAAA,MACA,YAAY;AACV,QAAA,IAAI;AACF,UAAA,OAAO,MAAM,EAAA,EAAG;AAAA,QAClB,SAAS,CAAA,EAAG;AACV,UAAAC,qBAAA,CAAiB,CAAA,EAAG,EAAE,SAAA,EAAW,EAAE,SAAS,KAAA,EAAO,IAAA,EAAM,4BAAA,EAA6B,EAAG,CAAA;AACzF,UAAA,MAAM,CAAA;AAAA,QACR,CAAA,SAAE;AACA,UAAA,SAAA,CAAUC,qBAAA,CAAgB,MAAM,CAAC,CAAA;AAAA,QACnC;AAAA,MACF;AAAA,KACF;AAAA,EACF,CAAC,CAAA;AACH;AAKO,SAAS,8BAAA,CACd,SACA,eAAA,EACM;AACN,EAAA,IAAI,EAAE,OAAA,IAAW,OAAA,CAAA,IAAY,OAAO,OAAA,CAAQ,UAAU,UAAA,EAAY;AAChE,IAAA;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,KAAA,GAAQC,6BAAA;AAAA,IACd,OAAA,CAAQ,KAAA;AAAA,IACR,CAAA,QAAA,KACE,IAAI,KAAA,CAAM,QAAA,EAAU;AAAA,MAClB,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,IAAA,EAA2C;AAChE,QAAA,MAAM,CAAC,YAAA,EAAc,GAAA,EAAK,GAAG,CAAA,GAAI,IAAA;AACjC,QAAA,MAAM,OAAA,GAAUC,oCAAkB,GAAG,CAAA;AACrC,QAAA,MAAMC,SAAA,GAAUC,uBAAA,CAAgB,eAAA,CAAgB,GAAG,GAAG,GAAG,CAAA;AACzD,QAAA,IAAA,CAAK,CAAC,CAAA,GAAIC,2BAAA,CAAc,GAAA,EAAKF,SAAO,CAAA;AACpC,QAAA,IAAA,CAAK,CAAC,CAAA,GAAI,OAAA;AAEV,QAAA,OAAO,gBAAA,CAAiB,cAAcA,SAAA,EAAS,OAAA,EAAS,MAAM,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,IAAI,CAAC,CAAA;AAAA,MAC3F;AAAA,KACD;AAAA,GACL;AACF;;;;"}
@@ -19,15 +19,20 @@ function wrapScheduledHandler(controller, options, context, fn) {
19
19
  const client = sdk.init({ ...options, ctx: context });
20
20
  isolationScope.setClient(client);
21
21
  scopeUtils.addCloudResourceContext(isolationScope);
22
+ const description = `Scheduled Cron ${controller.cron}`;
22
23
  return core.startSpan(
23
24
  {
24
- name: `Scheduled Cron ${controller.cron}`,
25
+ name: client && core.hasSpanStreamingEnabled(client) ? "scheduled" : description,
25
26
  attributes: {
26
27
  [attributes.SENTRY_OP]: op.FUNCTION,
27
- "faas.cron": controller.cron,
28
- "faas.time": new Date(controller.scheduledTime).toISOString(),
29
- "faas.trigger": "timer",
30
- [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.faas.cloudflare.scheduled",
28
+ // override description inference by Relay to preserve the original (transaction-based) description.
29
+ // sentry-conventions can't map the special case for the "Scheduled Cron" prefix and the chron string.
30
+ [attributes.SENTRY_DESCRIPTION]: description,
31
+ [attributes.CODE_FUNCTION_NAME]: "scheduled",
32
+ [attributes.FAAS_CRON]: controller.cron,
33
+ [attributes.FAAS_TIME]: new Date(controller.scheduledTime).toISOString(),
34
+ [attributes.FAAS_TRIGGER]: "timer",
35
+ [attributes.SENTRY_ORIGIN]: "auto.faas.cloudflare.scheduled",
31
36
  [attributes.SENTRY_SEGMENT_NAME_SOURCE]: "task"
32
37
  }
33
38
  },
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentScheduled.js","sources":["../../../../../src/instrumentations/worker/instrumentScheduled.ts"],"sourcesContent":["import type { ScheduledController } from '@cloudflare/workers-types';\nimport type { AnyExportedHandler } from '../../types';\nimport type { env as cloudflareEnv, WorkerEntrypoint } from 'cloudflare:workers';\nimport { SENTRY_SEGMENT_NAME_SOURCE, SENTRY_OP } from '@sentry/conventions/attributes';\nimport { FUNCTION } from '@sentry/conventions/op';\nimport { captureException, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan, withIsolationScope } from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { ensureInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\nimport { setInvocationState } from '../../utils/invocationContext';\nimport { instrumentEnv } from './instrumentEnv';\n\nfunction wrapScheduledHandler(\n controller: ScheduledController,\n options: CloudflareOptions,\n context: ExecutionContext,\n fn: () => unknown,\n): unknown {\n return withIsolationScope(isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n setInvocationState(isolationScope, { ctx: context });\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n return startSpan(\n {\n name: `Scheduled Cron ${controller.cron}`,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n 'faas.cron': controller.cron,\n 'faas.time': new Date(controller.scheduledTime).toISOString(),\n 'faas.trigger': 'timer',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.faas.cloudflare.scheduled',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'task',\n },\n },\n async () => {\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.scheduled' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n },\n );\n });\n}\n\n/**\n * Instruments a scheduled handler for ExportedHandler (env/ctx come from args).\n */\nexport function instrumentExportedHandlerScheduled<T extends AnyExportedHandler>(\n handler: T,\n optionsCallback: (env: typeof cloudflareEnv) => CloudflareOptions | undefined,\n): void {\n if (!('scheduled' in handler) || typeof handler.scheduled !== 'function') {\n return;\n }\n\n handler.scheduled = ensureInstrumented(\n handler.scheduled,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<NonNullable<T['scheduled']>>) {\n const [controller, env, ctx] = args;\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n args[1] = instrumentEnv(env, options);\n args[2] = context;\n\n return wrapScheduledHandler(controller, options, context, () => target.apply(thisArg, args));\n },\n }),\n );\n}\n\n/**\n * Instruments a scheduled method for WorkerEntrypoint (options/context already available).\n */\nexport function instrumentWorkerEntrypointScheduled<T extends WorkerEntrypoint>(\n instance: T,\n options: CloudflareOptions,\n context: ExecutionContext,\n): void {\n if (!instance.scheduled) {\n return;\n }\n\n const original = instance.scheduled.bind(instance);\n instance.scheduled = new Proxy(original, {\n apply(target, thisArg, args: [ScheduledController]) {\n const [controller] = args;\n\n return wrapScheduledHandler(controller, options, context, () => Reflect.apply(target, thisArg, args));\n },\n });\n}\n"],"names":["withIsolationScope","setInvocationState","init","addCloudResourceContext","startSpan","SENTRY_OP","FUNCTION","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SENTRY_SEGMENT_NAME_SOURCE","captureException","flushAndDispose","ensureInstrumented","instrumentContext","options","getFinalOptions","instrumentEnv"],"mappings":"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"}
1
+ {"version":3,"file":"instrumentScheduled.js","sources":["../../../../../src/instrumentations/worker/instrumentScheduled.ts"],"sourcesContent":["import type { ScheduledController } from '@cloudflare/workers-types';\nimport type { AnyExportedHandler } from '../../types';\nimport type { env as cloudflareEnv, WorkerEntrypoint } from 'cloudflare:workers';\nimport {\n SENTRY_SEGMENT_NAME_SOURCE,\n CODE_FUNCTION_NAME,\n SENTRY_OP,\n FAAS_CRON,\n FAAS_TIME,\n FAAS_TRIGGER,\n SENTRY_DESCRIPTION,\n SENTRY_ORIGIN,\n} from '@sentry/conventions/attributes';\nimport { FUNCTION } from '@sentry/conventions/op';\nimport { captureException, hasSpanStreamingEnabled, startSpan, withIsolationScope } from '@sentry/core';\nimport type { CloudflareOptions } from '../../client';\nimport { flushAndDispose } from '../../flush';\nimport { ensureInstrumented } from '../../instrument';\nimport { getFinalOptions } from '../../options';\nimport { addCloudResourceContext } from '../../scope-utils';\nimport { init } from '../../sdk';\nimport { instrumentContext } from '../../utils/instrumentContext';\nimport { setInvocationState } from '../../utils/invocationContext';\nimport { instrumentEnv } from './instrumentEnv';\n\nfunction wrapScheduledHandler(\n controller: ScheduledController,\n options: CloudflareOptions,\n context: ExecutionContext,\n fn: () => unknown,\n): unknown {\n return withIsolationScope(isolationScope => {\n const waitUntil = context.waitUntil.bind(context);\n\n setInvocationState(isolationScope, { ctx: context });\n\n const client = init({ ...options, ctx: context });\n isolationScope.setClient(client);\n\n addCloudResourceContext(isolationScope);\n\n const description = `Scheduled Cron ${controller.cron}`;\n\n return startSpan(\n {\n name: client && hasSpanStreamingEnabled(client) ? 'scheduled' : description,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n // override description inference by Relay to preserve the original (transaction-based) description.\n // sentry-conventions can't map the special case for the \"Scheduled Cron\" prefix and the chron string.\n [SENTRY_DESCRIPTION]: description,\n [CODE_FUNCTION_NAME]: 'scheduled',\n [FAAS_CRON]: controller.cron,\n [FAAS_TIME]: new Date(controller.scheduledTime).toISOString(),\n [FAAS_TRIGGER]: 'timer',\n [SENTRY_ORIGIN]: 'auto.faas.cloudflare.scheduled',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'task',\n },\n },\n async () => {\n try {\n return await fn();\n } catch (e) {\n captureException(e, { mechanism: { handled: false, type: 'auto.faas.cloudflare.scheduled' } });\n throw e;\n } finally {\n waitUntil(flushAndDispose(client));\n }\n },\n );\n });\n}\n\n/**\n * Instruments a scheduled handler for ExportedHandler (env/ctx come from args).\n */\nexport function instrumentExportedHandlerScheduled<T extends AnyExportedHandler>(\n handler: T,\n optionsCallback: (env: typeof cloudflareEnv) => CloudflareOptions | undefined,\n): void {\n if (!('scheduled' in handler) || typeof handler.scheduled !== 'function') {\n return;\n }\n\n handler.scheduled = ensureInstrumented(\n handler.scheduled,\n original =>\n new Proxy(original, {\n apply(target, thisArg, args: Parameters<NonNullable<T['scheduled']>>) {\n const [controller, env, ctx] = args;\n const context = instrumentContext(ctx);\n const options = getFinalOptions(optionsCallback(env), env);\n args[1] = instrumentEnv(env, options);\n args[2] = context;\n\n return wrapScheduledHandler(controller, options, context, () => target.apply(thisArg, args));\n },\n }),\n );\n}\n\n/**\n * Instruments a scheduled method for WorkerEntrypoint (options/context already available).\n */\nexport function instrumentWorkerEntrypointScheduled<T extends WorkerEntrypoint>(\n instance: T,\n options: CloudflareOptions,\n context: ExecutionContext,\n): void {\n if (!instance.scheduled) {\n return;\n }\n\n const original = instance.scheduled.bind(instance);\n instance.scheduled = new Proxy(original, {\n apply(target, thisArg, args: [ScheduledController]) {\n const [controller] = args;\n\n return wrapScheduledHandler(controller, options, context, () => Reflect.apply(target, thisArg, args));\n },\n });\n}\n"],"names":["withIsolationScope","setInvocationState","init","addCloudResourceContext","startSpan","hasSpanStreamingEnabled","SENTRY_OP","FUNCTION","SENTRY_DESCRIPTION","CODE_FUNCTION_NAME","FAAS_CRON","FAAS_TIME","FAAS_TRIGGER","SENTRY_ORIGIN","SENTRY_SEGMENT_NAME_SOURCE","captureException","flushAndDispose","ensureInstrumented","instrumentContext","options","getFinalOptions","instrumentEnv"],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const debugBuild = require('./debug-build.js');
5
+
6
+ const deferred = [];
7
+ const DEFERRED = /* @__PURE__ */ Symbol("sentryOrchestrionDeferred");
8
+ function isGlobalScopeError(error) {
9
+ return error instanceof Error && /within global scope/.test(error.message);
10
+ }
11
+ function deferChannelEvent(channel, ctx) {
12
+ if (ctx[DEFERRED]) {
13
+ return;
14
+ }
15
+ ctx[DEFERRED] = true;
16
+ deferred.push({ channel, ctx, hadError: "error" in ctx });
17
+ }
18
+ function flushDeferredChannelEvents() {
19
+ if (deferred.length === 0) {
20
+ return;
21
+ }
22
+ const pending = deferred.splice(0, deferred.length);
23
+ for (const { channel, ctx, hadError } of pending) {
24
+ try {
25
+ channel.start.publish(ctx);
26
+ if (hadError) {
27
+ channel.error.publish(ctx);
28
+ }
29
+ channel.end.publish(ctx);
30
+ } catch (error) {
31
+ debugBuild.DEBUG_BUILD && core.debug.warn("[orchestrion] failed to emit a deferred channel event", error);
32
+ }
33
+ }
34
+ }
35
+
36
+ exports.deferChannelEvent = deferChannelEvent;
37
+ exports.flushDeferredChannelEvents = flushDeferredChannelEvents;
38
+ exports.isGlobalScopeError = isGlobalScopeError;
39
+ //# sourceMappingURL=orchestrion-deferred-channels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrion-deferred-channels.js","sources":["../../../src/orchestrion-deferred-channels.ts"],"sourcesContent":["/**\n * Deferral for orchestrion channel events that could not be published when they occurred.\n *\n * On workerd, `channel.publish()`/`runStores()` throw at module/global scope, so a library\n * instantiated at module scope (`const app = new Hono()`) cannot emit its wrapping event\n * there. {@link ./orchestrion-diagnostics-channel} defers those events here;\n * {@link flushDeferredChannelEvents} emits them once a request is being handled (where\n * publish works) and the SDK's `init()` has registered subscribers.\n *\n * This module imports NO `node:*` builtin, so it is safe to pull into the request wrapper on\n * runtimes without `nodejs_compat` — there the queue is always empty (no channels were ever\n * injected) and the flush is a no-op.\n */\nimport { debug } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\n\ntype Ctx = Record<string, unknown>;\n\n// The minimal slice of a `node:diagnostics_channel` TracingChannel we emit on. Declared locally\n// (rather than imported from `node:diagnostics_channel`) so this module's graph carries no `node:`\n// specifier — `wrapRequestHandler` must load on runtimes without `nodejs_compat`, and the\n// module-graph test forbids any `node:` import reachable from it.\ninterface PublishableTracingChannel {\n start: { publish(ctx: Ctx): void };\n end: { publish(ctx: Ctx): void };\n error: { publish(ctx: Ctx): void };\n}\n\ninterface DeferredChannelEvent {\n channel: PublishableTracingChannel;\n ctx: Ctx;\n hadError: boolean;\n}\n\nconst deferred: DeferredChannelEvent[] = [];\nconst DEFERRED = Symbol('sentryOrchestrionDeferred');\n\n/** workerd's global-scope guard is the only error we degrade on; anything else is a real fault. */\nexport function isGlobalScopeError(error: unknown): boolean {\n return error instanceof Error && /within global scope/.test(error.message);\n}\n\n/** Queue a channel event that could not be published now, at most once per context object. */\nexport function deferChannelEvent(channel: PublishableTracingChannel, ctx: Ctx): void {\n if ((ctx as Record<symbol, unknown>)[DEFERRED]) {\n return;\n }\n (ctx as Record<symbol, unknown>)[DEFERRED] = true;\n deferred.push({ channel, ctx, hadError: 'error' in ctx });\n}\n\n/**\n * Emit every deferred channel event via the real channel. Called at the top of the request\n * handler, after `init()` has subscribed. Uses bare `start`/`end` publish (never `runStores`),\n * so no `bindStore` producer runs and no span is parented to this request — only the plain\n * subscribers (the instance patchers) fire. Idempotent: it drains the queue, so later requests\n * and re-entrant calls are no-ops.\n */\nexport function flushDeferredChannelEvents(): void {\n if (deferred.length === 0) {\n return;\n }\n const pending = deferred.splice(0, deferred.length);\n for (const { channel, ctx, hadError } of pending) {\n try {\n channel.start.publish(ctx);\n if (hadError) {\n channel.error.publish(ctx);\n }\n channel.end.publish(ctx);\n } catch (error) {\n DEBUG_BUILD && debug.warn('[orchestrion] failed to emit a deferred channel event', error);\n }\n }\n}\n"],"names":["DEBUG_BUILD","debug"],"mappings":";;;;;AAkCA,MAAM,WAAmC,EAAC;AAC1C,MAAM,QAAA,0BAAkB,2BAA2B,CAAA;AAG5C,SAAS,mBAAmB,KAAA,EAAyB;AAC1D,EAAA,OAAO,KAAA,YAAiB,KAAA,IAAS,qBAAA,CAAsB,IAAA,CAAK,MAAM,OAAO,CAAA;AAC3E;AAGO,SAAS,iBAAA,CAAkB,SAAoC,GAAA,EAAgB;AACpF,EAAA,IAAK,GAAA,CAAgC,QAAQ,CAAA,EAAG;AAC9C,IAAA;AAAA,EACF;AACA,EAAC,GAAA,CAAgC,QAAQ,CAAA,GAAI,IAAA;AAC7C,EAAA,QAAA,CAAS,KAAK,EAAE,OAAA,EAAS,KAAK,QAAA,EAAU,OAAA,IAAW,KAAK,CAAA;AAC1D;AASO,SAAS,0BAAA,GAAmC;AACjD,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,IAAA;AAAA,EACF;AACA,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,MAAA,CAAO,CAAA,EAAG,SAAS,MAAM,CAAA;AAClD,EAAA,KAAA,MAAW,EAAE,OAAA,EAAS,GAAA,EAAK,QAAA,MAAc,OAAA,EAAS;AAChD,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,KAAA,CAAM,QAAQ,GAAG,CAAA;AACzB,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,QAAQ,GAAG,CAAA;AAAA,MAC3B;AACA,MAAA,OAAA,CAAQ,GAAA,CAAI,QAAQ,GAAG,CAAA;AAAA,IACzB,SAAS,KAAA,EAAO;AACd,MAAAA,sBAAA,IAAeC,UAAA,CAAM,IAAA,CAAK,uDAAA,EAAyD,KAAK,CAAA;AAAA,IAC1F;AAAA,EACF;AACF;;;;;;"}