@sentry/cloudflare 10.59.0 → 10.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/async.js +2 -1
- package/build/cjs/async.js.map +1 -1
- package/build/cjs/index.js +3 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/instrumentations/instrumentDurableObjectStorage.js +4 -0
- package/build/cjs/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
- package/build/cjs/instrumentations/instrumentSqlStorage.js +37 -0
- package/build/cjs/instrumentations/instrumentSqlStorage.js.map +1 -0
- package/build/cjs/instrumentations/worker/instrumentD1.js +58 -4
- package/build/cjs/instrumentations/worker/instrumentD1.js.map +1 -1
- package/build/cjs/instrumentations/worker/instrumentEnv.js +7 -0
- package/build/cjs/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/cjs/instrumentations/worker/instrumentR2.js +124 -0
- package/build/cjs/instrumentations/worker/instrumentR2.js.map +1 -0
- package/build/cjs/utils/isBinding.js +4 -0
- package/build/cjs/utils/isBinding.js.map +1 -1
- package/build/esm/async.js +3 -2
- package/build/esm/async.js.map +1 -1
- package/build/esm/index.js +1 -1
- package/build/esm/instrumentations/instrumentDurableObjectStorage.js +4 -0
- package/build/esm/instrumentations/instrumentDurableObjectStorage.js.map +1 -1
- package/build/esm/instrumentations/instrumentSqlStorage.js +35 -0
- package/build/esm/instrumentations/instrumentSqlStorage.js.map +1 -0
- package/build/esm/instrumentations/worker/instrumentD1.js +58 -4
- package/build/esm/instrumentations/worker/instrumentD1.js.map +1 -1
- package/build/esm/instrumentations/worker/instrumentEnv.js +8 -1
- package/build/esm/instrumentations/worker/instrumentEnv.js.map +1 -1
- package/build/esm/instrumentations/worker/instrumentR2.js +122 -0
- package/build/esm/instrumentations/worker/instrumentR2.js.map +1 -0
- package/build/esm/package.json +1 -1
- package/build/esm/utils/isBinding.js +4 -1
- package/build/esm/utils/isBinding.js.map +1 -1
- package/build/types/async.d.ts.map +1 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentDurableObjectStorage.d.ts.map +1 -1
- package/build/types/instrumentations/instrumentSqlStorage.d.ts +9 -0
- package/build/types/instrumentations/instrumentSqlStorage.d.ts.map +1 -0
- package/build/types/instrumentations/worker/instrumentD1.d.ts.map +1 -1
- package/build/types/instrumentations/worker/instrumentEnv.d.ts +1 -2
- package/build/types/instrumentations/worker/instrumentEnv.d.ts.map +1 -1
- package/build/types/instrumentations/worker/instrumentR2.d.ts +9 -0
- package/build/types/instrumentations/worker/instrumentR2.d.ts.map +1 -0
- package/build/types/utils/isBinding.d.ts +6 -1
- package/build/types/utils/isBinding.d.ts.map +1 -1
- package/build/types-ts3.8/index.d.ts +1 -1
- package/build/types-ts3.8/instrumentations/instrumentSqlStorage.d.ts +9 -0
- package/build/types-ts3.8/instrumentations/worker/instrumentEnv.d.ts +1 -2
- package/build/types-ts3.8/instrumentations/worker/instrumentR2.d.ts +9 -0
- package/build/types-ts3.8/utils/isBinding.d.ts +6 -1
- package/package.json +2 -2
package/build/cjs/async.js
CHANGED
|
@@ -54,7 +54,8 @@ function setAsyncLocalStorageAsyncContextStrategy() {
|
|
|
54
54
|
withIsolationScope,
|
|
55
55
|
withSetIsolationScope,
|
|
56
56
|
getCurrentScope: () => getScopes().scope,
|
|
57
|
-
getIsolationScope: () => getScopes().isolationScope
|
|
57
|
+
getIsolationScope: () => getScopes().isolationScope,
|
|
58
|
+
getTracingChannelBinding: () => core._INTERNAL_createTracingChannelBinding(asyncStorage, getScopes)
|
|
58
59
|
});
|
|
59
60
|
}
|
|
60
61
|
|
package/build/cjs/async.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async.js","sources":["../../src/async.ts"],"sourcesContent":["// Need to use node: prefix for cloudflare workers compatibility\n// Note: Because we are using node:async_hooks, we need to set `node_compat` in the wrangler.toml\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Scope } from '@sentry/core';\nimport {
|
|
1
|
+
{"version":3,"file":"async.js","sources":["../../src/async.ts"],"sourcesContent":["// Need to use node: prefix for cloudflare workers compatibility\n// Note: Because we are using node:async_hooks, we need to set `node_compat` in the wrangler.toml\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Scope } from '@sentry/core';\nimport {\n _INTERNAL_createTracingChannelBinding,\n getDefaultCurrentScope,\n getDefaultIsolationScope,\n setAsyncContextStrategy,\n} from '@sentry/core';\n\n/**\n * Sets the async context strategy to use AsyncLocalStorage.\n *\n * AsyncLocalStorage is only available in the cloudflare workers runtime if you set\n * compatibility_flags = [\"nodejs_compat\"] or compatibility_flags = [\"nodejs_als\"]\n *\n * @internal Only exported to be used in higher-level Sentry packages\n * @hidden Only exported to be used in higher-level Sentry packages\n */\nexport function setAsyncLocalStorageAsyncContextStrategy(): void {\n const asyncStorage = new AsyncLocalStorage<{\n scope: Scope;\n isolationScope: Scope;\n }>();\n\n function getScopes(): { scope: Scope; isolationScope: Scope } {\n const scopes = asyncStorage.getStore();\n\n if (scopes) {\n return scopes;\n }\n\n // fallback behavior:\n // if, for whatever reason, we can't find scopes on the context here, we have to fix this somehow\n return {\n scope: getDefaultCurrentScope(),\n isolationScope: getDefaultIsolationScope(),\n };\n }\n\n function withScope<T>(callback: (scope: Scope) => T): T {\n const scope = getScopes().scope.clone();\n const isolationScope = getScopes().isolationScope;\n return asyncStorage.run({ scope, isolationScope }, () => {\n return callback(scope);\n });\n }\n\n function withSetScope<T>(scope: Scope, callback: (scope: Scope) => T): T {\n const isolationScope = getScopes().isolationScope.clone();\n return asyncStorage.run({ scope, isolationScope }, () => {\n return callback(scope);\n });\n }\n\n function withIsolationScope<T>(callback: (isolationScope: Scope) => T): T {\n const scope = getScopes().scope;\n const isolationScope = getScopes().isolationScope.clone();\n return asyncStorage.run({ scope, isolationScope }, () => {\n return callback(isolationScope);\n });\n }\n\n function withSetIsolationScope<T>(isolationScope: Scope, callback: (isolationScope: Scope) => T): T {\n const scope = getScopes().scope;\n return asyncStorage.run({ scope, isolationScope }, () => {\n return callback(isolationScope);\n });\n }\n\n // In contrast to the browser, we can rely on async context isolation here\n function suppressTracing<T>(callback: () => T): T {\n return withScope(scope => {\n scope.setSDKProcessingMetadata({ __SENTRY_SUPPRESS_TRACING__: true });\n return callback();\n });\n }\n\n setAsyncContextStrategy({\n suppressTracing,\n withScope,\n withSetScope,\n withIsolationScope,\n withSetIsolationScope,\n getCurrentScope: () => getScopes().scope,\n getIsolationScope: () => getScopes().isolationScope,\n getTracingChannelBinding: () => _INTERNAL_createTracingChannelBinding(asyncStorage, getScopes),\n });\n}\n"],"names":["AsyncLocalStorage","getDefaultCurrentScope","getDefaultIsolationScope","setAsyncContextStrategy","_INTERNAL_createTracingChannelBinding"],"mappings":";;;;;AAoBO,SAAS,wCAAA,GAAiD;AAC/D,EAAA,MAAM,YAAA,GAAe,IAAIA,kCAAA,EAGtB;AAEH,EAAA,SAAS,SAAA,GAAqD;AAC5D,IAAA,MAAM,MAAA,GAAS,aAAa,QAAA,EAAS;AAErC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,OAAO,MAAA;AAAA,IACT;AAIA,IAAA,OAAO;AAAA,MACL,OAAOC,2BAAA,EAAuB;AAAA,MAC9B,gBAAgBC,6BAAA;AAAyB,KAC3C;AAAA,EACF;AAEA,EAAA,SAAS,UAAa,QAAA,EAAkC;AACtD,IAAA,MAAM,KAAA,GAAQ,SAAA,EAAU,CAAE,KAAA,CAAM,KAAA,EAAM;AACtC,IAAA,MAAM,cAAA,GAAiB,WAAU,CAAE,cAAA;AACnC,IAAA,OAAO,aAAa,GAAA,CAAI,EAAE,KAAA,EAAO,cAAA,IAAkB,MAAM;AACvD,MAAA,OAAO,SAAS,KAAK,CAAA;AAAA,IACvB,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,SAAS,YAAA,CAAgB,OAAc,QAAA,EAAkC;AACvE,IAAA,MAAM,cAAA,GAAiB,SAAA,EAAU,CAAE,cAAA,CAAe,KAAA,EAAM;AACxD,IAAA,OAAO,aAAa,GAAA,CAAI,EAAE,KAAA,EAAO,cAAA,IAAkB,MAAM;AACvD,MAAA,OAAO,SAAS,KAAK,CAAA;AAAA,IACvB,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,SAAS,mBAAsB,QAAA,EAA2C;AACxE,IAAA,MAAM,KAAA,GAAQ,WAAU,CAAE,KAAA;AAC1B,IAAA,MAAM,cAAA,GAAiB,SAAA,EAAU,CAAE,cAAA,CAAe,KAAA,EAAM;AACxD,IAAA,OAAO,aAAa,GAAA,CAAI,EAAE,KAAA,EAAO,cAAA,IAAkB,MAAM;AACvD,MAAA,OAAO,SAAS,cAAc,CAAA;AAAA,IAChC,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,SAAS,qBAAA,CAAyB,gBAAuB,QAAA,EAA2C;AAClG,IAAA,MAAM,KAAA,GAAQ,WAAU,CAAE,KAAA;AAC1B,IAAA,OAAO,aAAa,GAAA,CAAI,EAAE,KAAA,EAAO,cAAA,IAAkB,MAAM;AACvD,MAAA,OAAO,SAAS,cAAc,CAAA;AAAA,IAChC,CAAC,CAAA;AAAA,EACH;AAGA,EAAA,SAAS,gBAAmB,QAAA,EAAsB;AAChD,IAAA,OAAO,UAAU,CAAA,KAAA,KAAS;AACxB,MAAA,KAAA,CAAM,wBAAA,CAAyB,EAAE,2BAAA,EAA6B,IAAA,EAAM,CAAA;AACpE,MAAA,OAAO,QAAA,EAAS;AAAA,IAClB,CAAC,CAAA;AAAA,EACH;AAEA,EAAAC,4BAAA,CAAwB;AAAA,IACtB,eAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,kBAAA;AAAA,IACA,qBAAA;AAAA,IACA,eAAA,EAAiB,MAAM,SAAA,EAAU,CAAE,KAAA;AAAA,IACnC,iBAAA,EAAmB,MAAM,SAAA,EAAU,CAAE,cAAA;AAAA,IACrC,wBAAA,EAA0B,MAAMC,0CAAA,CAAsC,YAAA,EAAc,SAAS;AAAA,GAC9F,CAAA;AACH;;;;"}
|
package/build/cjs/index.js
CHANGED
|
@@ -26,6 +26,7 @@ exports.Scope = core.Scope;
|
|
|
26
26
|
exports.addBreadcrumb = core.addBreadcrumb;
|
|
27
27
|
exports.addEventProcessor = core.addEventProcessor;
|
|
28
28
|
exports.addIntegration = core.addIntegration;
|
|
29
|
+
exports.bindScopeToEmitter = core.bindScopeToEmitter;
|
|
29
30
|
exports.captureCheckIn = core.captureCheckIn;
|
|
30
31
|
exports.captureConsoleIntegration = core.captureConsoleIntegration;
|
|
31
32
|
exports.captureEvent = core.captureEvent;
|
|
@@ -74,6 +75,8 @@ exports.metrics = core.metrics;
|
|
|
74
75
|
exports.moduleMetadataIntegration = core.moduleMetadataIntegration;
|
|
75
76
|
exports.requestDataIntegration = core.requestDataIntegration;
|
|
76
77
|
exports.rewriteFramesIntegration = core.rewriteFramesIntegration;
|
|
78
|
+
exports.setAttribute = core.setAttribute;
|
|
79
|
+
exports.setAttributes = core.setAttributes;
|
|
77
80
|
exports.setContext = core.setContext;
|
|
78
81
|
exports.setConversationId = core.setConversationId;
|
|
79
82
|
exports.setCurrentClient = core.setCurrentClient;
|
package/build/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3
3
|
const core = require('@sentry/core');
|
|
4
4
|
const traceLinks = require('../utils/traceLinks.js');
|
|
5
5
|
const instrumentDurableObjectSyncKvStorage = require('./instrumentDurableObjectSyncKvStorage.js');
|
|
6
|
+
const instrumentSqlStorage = require('./instrumentSqlStorage.js');
|
|
6
7
|
|
|
7
8
|
const STORAGE_METHODS_TO_INSTRUMENT = ["get", "put", "delete", "list", "setAlarm", "getAlarm", "deleteAlarm"];
|
|
8
9
|
function instrumentDurableObjectStorage(storage, waitUntil) {
|
|
@@ -12,6 +13,9 @@ function instrumentDurableObjectStorage(storage, waitUntil) {
|
|
|
12
13
|
if (prop === "kv" && original != null && "get" in original && "put" in original) {
|
|
13
14
|
return instrumentDurableObjectSyncKvStorage.instrumentDurableObjectSyncKvStorage(original);
|
|
14
15
|
}
|
|
16
|
+
if (prop === "sql" && original != null && "databaseSize" in original && "exec" in original) {
|
|
17
|
+
return instrumentSqlStorage.instrumentSqlStorage(original);
|
|
18
|
+
}
|
|
15
19
|
if (typeof original !== "function") {
|
|
16
20
|
return original;
|
|
17
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentDurableObjectStorage.js","sources":["../../../src/instrumentations/instrumentDurableObjectStorage.ts"],"sourcesContent":["import type { DurableObjectStorage, SyncKvStorage } from '@cloudflare/workers-types';\nimport { isThenable, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/core';\nimport { storeSpanContext } from '../utils/traceLinks';\nimport { instrumentDurableObjectSyncKvStorage } from './instrumentDurableObjectSyncKvStorage';\n\nconst STORAGE_METHODS_TO_INSTRUMENT = ['get', 'put', 'delete', 'list', 'setAlarm', 'getAlarm', 'deleteAlarm'] as const;\n\ntype StorageMethod = (typeof STORAGE_METHODS_TO_INSTRUMENT)[number];\n\ntype WaitUntil = (promise: Promise<unknown>) => void;\n\n/**\n * Instruments DurableObjectStorage methods with Sentry spans.\n *\n * Wraps the following async methods:\n * - get, put, delete, list (KV API)\n * - setAlarm, getAlarm, deleteAlarm (Alarm API)\n *\n * When setAlarm is called, it also stores the current span context so that when\n * the alarm fires later, it can link back to the trace that called setAlarm.\n *\n * @param storage - The DurableObjectStorage instance to instrument\n * @param waitUntil - Optional waitUntil function to defer span context storage\n * @returns An instrumented DurableObjectStorage instance\n */\nexport function instrumentDurableObjectStorage(\n storage: DurableObjectStorage,\n waitUntil?: WaitUntil,\n): DurableObjectStorage {\n return new Proxy(storage, {\n get(target, prop, _receiver) {\n // Use `target` as the receiver instead of the proxy (`_receiver`).\n // Native workerd getters (e.g., `storage.sql`) validate `this` via\n // internal slots. Passing the proxy as receiver breaks that check,\n // causing \"Illegal invocation: function called with incorrect `this`\n // reference\" errors.\n const original = Reflect.get(target, prop, target);\n\n if (prop === 'kv' && original != null && 'get' in original && 'put' in original) {\n return instrumentDurableObjectSyncKvStorage(original as SyncKvStorage);\n }\n\n if (typeof original !== 'function') {\n return original;\n }\n\n const methodName = prop as string;\n if (!STORAGE_METHODS_TO_INSTRUMENT.includes(methodName as StorageMethod)) {\n return (original as (...args: unknown[]) => unknown).bind(target);\n }\n\n return function (this: unknown, ...args: unknown[]) {\n return startSpan(\n {\n // Use underscore naming to match Cloudflare's native instrumentation (e.g., \"durable_object_storage_get\")\n name: `durable_object_storage_${methodName}`,\n op: 'db',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.cloudflare.durable_object',\n 'db.system.name': 'cloudflare.durable_object.storage',\n 'db.operation.name': methodName,\n },\n },\n () => {\n const teardown = async (): Promise<void> => {\n // When setAlarm is called, store the current span context so that when the alarm\n // fires later, it can link back to the trace that called setAlarm.\n // We use the original (uninstrumented) storage (target) to avoid creating a span\n // for this internal operation. The storage is deferred via waitUntil to not block.\n if (methodName === 'setAlarm') {\n storeSpanContext(target, 'alarm');\n }\n };\n\n const result = (original as (...args: unknown[]) => unknown).apply(target, args);\n\n if (!isThenable(result)) {\n waitUntil?.(teardown());\n\n return result;\n }\n\n return result.then(\n res => {\n waitUntil?.(teardown());\n return res;\n },\n e => {\n throw e;\n },\n );\n },\n );\n };\n },\n });\n}\n"],"names":["instrumentDurableObjectSyncKvStorage","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","storeSpanContext","isThenable"],"mappings":"
|
|
1
|
+
{"version":3,"file":"instrumentDurableObjectStorage.js","sources":["../../../src/instrumentations/instrumentDurableObjectStorage.ts"],"sourcesContent":["import type { DurableObjectStorage, SyncKvStorage, SqlStorage } from '@cloudflare/workers-types';\nimport { isThenable, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/core';\nimport { storeSpanContext } from '../utils/traceLinks';\nimport { instrumentDurableObjectSyncKvStorage } from './instrumentDurableObjectSyncKvStorage';\nimport { instrumentSqlStorage } from './instrumentSqlStorage';\n\nconst STORAGE_METHODS_TO_INSTRUMENT = ['get', 'put', 'delete', 'list', 'setAlarm', 'getAlarm', 'deleteAlarm'] as const;\n\ntype StorageMethod = (typeof STORAGE_METHODS_TO_INSTRUMENT)[number];\n\ntype WaitUntil = (promise: Promise<unknown>) => void;\n\n/**\n * Instruments DurableObjectStorage methods with Sentry spans.\n *\n * Wraps the following async methods:\n * - get, put, delete, list (KV API)\n * - setAlarm, getAlarm, deleteAlarm (Alarm API)\n *\n * When setAlarm is called, it also stores the current span context so that when\n * the alarm fires later, it can link back to the trace that called setAlarm.\n *\n * @param storage - The DurableObjectStorage instance to instrument\n * @param waitUntil - Optional waitUntil function to defer span context storage\n * @returns An instrumented DurableObjectStorage instance\n */\nexport function instrumentDurableObjectStorage(\n storage: DurableObjectStorage,\n waitUntil?: WaitUntil,\n): DurableObjectStorage {\n return new Proxy(storage, {\n get(target, prop, _receiver) {\n // Use `target` as the receiver instead of the proxy (`_receiver`).\n // Native workerd getters (e.g., `storage.sql`) validate `this` via\n // internal slots. Passing the proxy as receiver breaks that check,\n // causing \"Illegal invocation: function called with incorrect `this`\n // reference\" errors.\n const original = Reflect.get(target, prop, target);\n\n if (prop === 'kv' && original != null && 'get' in original && 'put' in original) {\n return instrumentDurableObjectSyncKvStorage(original as SyncKvStorage);\n }\n\n if (prop === 'sql' && original != null && 'databaseSize' in original && 'exec' in original) {\n return instrumentSqlStorage(original as SqlStorage);\n }\n\n if (typeof original !== 'function') {\n return original;\n }\n\n const methodName = prop as string;\n if (!STORAGE_METHODS_TO_INSTRUMENT.includes(methodName as StorageMethod)) {\n return (original as (...args: unknown[]) => unknown).bind(target);\n }\n\n return function (this: unknown, ...args: unknown[]) {\n return startSpan(\n {\n // Use underscore naming to match Cloudflare's native instrumentation (e.g., \"durable_object_storage_get\")\n name: `durable_object_storage_${methodName}`,\n op: 'db',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.cloudflare.durable_object',\n 'db.system.name': 'cloudflare.durable_object.storage',\n 'db.operation.name': methodName,\n },\n },\n () => {\n const teardown = async (): Promise<void> => {\n // When setAlarm is called, store the current span context so that when the alarm\n // fires later, it can link back to the trace that called setAlarm.\n // We use the original (uninstrumented) storage (target) to avoid creating a span\n // for this internal operation. The storage is deferred via waitUntil to not block.\n if (methodName === 'setAlarm') {\n storeSpanContext(target, 'alarm');\n }\n };\n\n const result = (original as (...args: unknown[]) => unknown).apply(target, args);\n\n if (!isThenable(result)) {\n waitUntil?.(teardown());\n\n return result;\n }\n\n return result.then(\n res => {\n waitUntil?.(teardown());\n return res;\n },\n e => {\n throw e;\n },\n );\n },\n );\n };\n },\n });\n}\n"],"names":["instrumentDurableObjectSyncKvStorage","instrumentSqlStorage","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","storeSpanContext","isThenable"],"mappings":";;;;;;;AAMA,MAAM,6BAAA,GAAgC,CAAC,KAAA,EAAO,KAAA,EAAO,UAAU,MAAA,EAAQ,UAAA,EAAY,YAAY,aAAa,CAAA;AAoBrG,SAAS,8BAAA,CACd,SACA,SAAA,EACsB;AACtB,EAAA,OAAO,IAAI,MAAM,OAAA,EAAS;AAAA,IACxB,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAW;AAM3B,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,MAAM,MAAM,CAAA;AAEjD,MAAA,IAAI,SAAS,IAAA,IAAQ,QAAA,IAAY,QAAQ,KAAA,IAAS,QAAA,IAAY,SAAS,QAAA,EAAU;AAC/E,QAAA,OAAOA,0EAAqC,QAAyB,CAAA;AAAA,MACvE;AAEA,MAAA,IAAI,SAAS,KAAA,IAAS,QAAA,IAAY,QAAQ,cAAA,IAAkB,QAAA,IAAY,UAAU,QAAA,EAAU;AAC1F,QAAA,OAAOC,0CAAqB,QAAsB,CAAA;AAAA,MACpD;AAEA,MAAA,IAAI,OAAO,aAAa,UAAA,EAAY;AAClC,QAAA,OAAO,QAAA;AAAA,MACT;AAEA,MAAA,MAAM,UAAA,GAAa,IAAA;AACnB,MAAA,IAAI,CAAC,6BAAA,CAA8B,QAAA,CAAS,UAA2B,CAAA,EAAG;AACxE,QAAA,OAAQ,QAAA,CAA6C,KAAK,MAAM,CAAA;AAAA,MAClE;AAEA,MAAA,OAAO,YAA4B,IAAA,EAAiB;AAClD,QAAA,OAAOC,cAAA;AAAA,UACL;AAAA;AAAA,YAEE,IAAA,EAAM,0BAA0B,UAAU,CAAA,CAAA;AAAA,YAC1C,EAAA,EAAI,IAAA;AAAA,YACJ,UAAA,EAAY;AAAA,cACV,CAACC,qCAAgC,GAAG,mCAAA;AAAA,cACpC,gBAAA,EAAkB,mCAAA;AAAA,cAClB,mBAAA,EAAqB;AAAA;AACvB,WACF;AAAA,UACA,MAAM;AACJ,YAAA,MAAM,WAAW,YAA2B;AAK1C,cAAA,IAAI,eAAe,UAAA,EAAY;AAC7B,gBAAAC,2BAAA,CAAiB,QAAQ,OAAO,CAAA;AAAA,cAClC;AAAA,YACF,CAAA;AAEA,YAAA,MAAM,MAAA,GAAU,QAAA,CAA6C,KAAA,CAAM,MAAA,EAAQ,IAAI,CAAA;AAE/E,YAAA,IAAI,CAACC,eAAA,CAAW,MAAM,CAAA,EAAG;AACvB,cAAA,SAAA,GAAY,UAAU,CAAA;AAEtB,cAAA,OAAO,MAAA;AAAA,YACT;AAEA,YAAA,OAAO,MAAA,CAAO,IAAA;AAAA,cACZ,CAAA,GAAA,KAAO;AACL,gBAAA,SAAA,GAAY,UAAU,CAAA;AACtB,gBAAA,OAAO,GAAA;AAAA,cACT,CAAA;AAAA,cACA,CAAA,CAAA,KAAK;AACH,gBAAA,MAAM,CAAA;AAAA,cACR;AAAA,aACF;AAAA,UACF;AAAA,SACF;AAAA,MACF,CAAA;AAAA,IACF;AAAA,GACD,CAAA;AACH;;;;"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
|
|
5
|
+
function instrumentSqlStorage(sql) {
|
|
6
|
+
return new Proxy(sql, {
|
|
7
|
+
get(target, prop, _receiver) {
|
|
8
|
+
const original = Reflect.get(target, prop, target);
|
|
9
|
+
if (prop !== "exec" || typeof original !== "function") {
|
|
10
|
+
return original;
|
|
11
|
+
}
|
|
12
|
+
return function(...args) {
|
|
13
|
+
const [query, ...bindings] = args;
|
|
14
|
+
const sanitizedQuery = core._INTERNAL_sanitizeSqlQuery(query);
|
|
15
|
+
const querySummary = core._INTERNAL_getSqlQuerySummary(sanitizedQuery);
|
|
16
|
+
return core.startSpan(
|
|
17
|
+
{
|
|
18
|
+
op: "db.query",
|
|
19
|
+
name: querySummary || sanitizedQuery,
|
|
20
|
+
attributes: {
|
|
21
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.db.cloudflare.durable_object.sql",
|
|
22
|
+
"db.system.name": "cloudflare-durable-object-sql",
|
|
23
|
+
"db.operation.name": "exec",
|
|
24
|
+
"db.query.text": sanitizedQuery,
|
|
25
|
+
"db.query.summary": querySummary,
|
|
26
|
+
"cloudflare.durable_object.query.bindings": bindings.length
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
() => original.apply(target, args)
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
exports.instrumentSqlStorage = instrumentSqlStorage;
|
|
37
|
+
//# sourceMappingURL=instrumentSqlStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentSqlStorage.js","sources":["../../../src/instrumentations/instrumentSqlStorage.ts"],"sourcesContent":["import type { SqlStorage } from '@cloudflare/workers-types';\nimport {\n _INTERNAL_getSqlQuerySummary,\n _INTERNAL_sanitizeSqlQuery,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n startSpan,\n} from '@sentry/core';\n\n/**\n * Instruments the Durable Object SqlStorage `exec` method with Sentry spans.\n *\n * @param sql - The SqlStorage instance to instrument\n * @returns An instrumented SqlStorage instance\n */\nexport function instrumentSqlStorage(sql: SqlStorage): SqlStorage {\n return new Proxy(sql, {\n get(target, prop, _receiver) {\n const original = Reflect.get(target, prop, target);\n\n if (prop !== 'exec' || typeof original !== 'function') {\n return original;\n }\n\n return function (this: unknown, ...args: unknown[]) {\n const [query, ...bindings] = args as [string, ...unknown[]];\n const sanitizedQuery = _INTERNAL_sanitizeSqlQuery(query);\n const querySummary = _INTERNAL_getSqlQuerySummary(sanitizedQuery);\n\n return startSpan(\n {\n op: 'db.query',\n name: querySummary || sanitizedQuery,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.cloudflare.durable_object.sql',\n 'db.system.name': 'cloudflare-durable-object-sql',\n 'db.operation.name': 'exec',\n 'db.query.text': sanitizedQuery,\n 'db.query.summary': querySummary,\n 'cloudflare.durable_object.query.bindings': bindings.length,\n },\n },\n () => (original as (...a: unknown[]) => ReturnType<SqlStorage['exec']>).apply(target, args),\n );\n };\n },\n });\n}\n"],"names":["_INTERNAL_sanitizeSqlQuery","_INTERNAL_getSqlQuerySummary","startSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":";;;;AAcO,SAAS,qBAAqB,GAAA,EAA6B;AAChE,EAAA,OAAO,IAAI,MAAM,GAAA,EAAK;AAAA,IACpB,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAW;AAC3B,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,MAAM,MAAM,CAAA;AAEjD,MAAA,IAAI,IAAA,KAAS,MAAA,IAAU,OAAO,QAAA,KAAa,UAAA,EAAY;AACrD,QAAA,OAAO,QAAA;AAAA,MACT;AAEA,MAAA,OAAO,YAA4B,IAAA,EAAiB;AAClD,QAAA,MAAM,CAAC,KAAA,EAAO,GAAG,QAAQ,CAAA,GAAI,IAAA;AAC7B,QAAA,MAAM,cAAA,GAAiBA,gCAA2B,KAAK,CAAA;AACvD,QAAA,MAAM,YAAA,GAAeC,kCAA6B,cAAc,CAAA;AAEhE,QAAA,OAAOC,cAAA;AAAA,UACL;AAAA,YACE,EAAA,EAAI,UAAA;AAAA,YACJ,MAAM,YAAA,IAAgB,cAAA;AAAA,YACtB,UAAA,EAAY;AAAA,cACV,CAACC,qCAAgC,GAAG,uCAAA;AAAA,cACpC,gBAAA,EAAkB,+BAAA;AAAA,cAClB,mBAAA,EAAqB,MAAA;AAAA,cACrB,eAAA,EAAiB,cAAA;AAAA,cACjB,kBAAA,EAAoB,YAAA;AAAA,cACpB,4CAA4C,QAAA,CAAS;AAAA;AACvD,WACF;AAAA,UACA,MAAO,QAAA,CAAiE,KAAA,CAAM,MAAA,EAAQ,IAAI;AAAA,SAC5F;AAAA,MACF,CAAA;AAAA,IACF;AAAA,GACD,CAAA;AACH;;;;"}
|
|
@@ -76,7 +76,7 @@ function createD1Breadcrumb(query, type, d1Result) {
|
|
|
76
76
|
message: query,
|
|
77
77
|
data: {
|
|
78
78
|
...d1Result ? getAttributesFromD1Response(d1Result) : {},
|
|
79
|
-
"
|
|
79
|
+
"db.operation.name": type
|
|
80
80
|
}
|
|
81
81
|
});
|
|
82
82
|
}
|
|
@@ -85,18 +85,72 @@ function createStartSpanOptions(query, type) {
|
|
|
85
85
|
op: "db.query",
|
|
86
86
|
name: query,
|
|
87
87
|
attributes: {
|
|
88
|
-
"
|
|
88
|
+
"db.system.name": "cloudflare-d1",
|
|
89
|
+
"db.operation.name": type,
|
|
90
|
+
"db.query.text": query,
|
|
89
91
|
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.db.cloudflare.d1"
|
|
90
92
|
}
|
|
91
93
|
};
|
|
92
94
|
}
|
|
93
|
-
function
|
|
94
|
-
|
|
95
|
+
function instrumentPrepare(prepare) {
|
|
96
|
+
return new Proxy(prepare, {
|
|
95
97
|
apply(target, thisArg, args) {
|
|
96
98
|
const [query] = args;
|
|
97
99
|
return instrumentD1PreparedStatement(Reflect.apply(target, thisArg, args), query);
|
|
98
100
|
}
|
|
99
101
|
});
|
|
102
|
+
}
|
|
103
|
+
function instrumentBatch(batch) {
|
|
104
|
+
return new Proxy(batch, {
|
|
105
|
+
apply(target, thisArg, args) {
|
|
106
|
+
const statements = args[0];
|
|
107
|
+
const queryText = statements.map((statement) => statement.statement ?? "").filter(Boolean).join("\n");
|
|
108
|
+
return core.startSpan(
|
|
109
|
+
{
|
|
110
|
+
op: "db.query",
|
|
111
|
+
name: "D1 batch",
|
|
112
|
+
attributes: {
|
|
113
|
+
"db.system.name": "cloudflare-d1",
|
|
114
|
+
"db.operation.name": "batch",
|
|
115
|
+
"db.query.text": queryText || void 0,
|
|
116
|
+
"db.operation.batch.size": statements.length,
|
|
117
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.db.cloudflare.d1"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
async () => {
|
|
121
|
+
const res = await Reflect.apply(target, thisArg, args);
|
|
122
|
+
createD1Breadcrumb("D1 batch", "batch");
|
|
123
|
+
return res;
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function instrumentD1Session(session) {
|
|
130
|
+
session.prepare = instrumentPrepare(session.prepare);
|
|
131
|
+
session.batch = instrumentBatch(session.batch);
|
|
132
|
+
return session;
|
|
133
|
+
}
|
|
134
|
+
function _instrumentD1(db) {
|
|
135
|
+
db.prepare = instrumentPrepare(db.prepare);
|
|
136
|
+
db.batch = instrumentBatch(db.batch);
|
|
137
|
+
db.exec = new Proxy(db.exec, {
|
|
138
|
+
apply(target, thisArg, args) {
|
|
139
|
+
const [query] = args;
|
|
140
|
+
return core.startSpan(createStartSpanOptions(query, "exec"), async () => {
|
|
141
|
+
const res = await Reflect.apply(target, thisArg, args);
|
|
142
|
+
createD1Breadcrumb(query, "exec");
|
|
143
|
+
return res;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
if ("withSession" in db && typeof db.withSession === "function") {
|
|
148
|
+
db.withSession = new Proxy(db.withSession, {
|
|
149
|
+
apply(target, thisArg, args) {
|
|
150
|
+
return instrumentD1Session(Reflect.apply(target, thisArg, args));
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
100
154
|
return db;
|
|
101
155
|
}
|
|
102
156
|
function instrumentD1(db) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentD1.js","sources":["../../../../src/instrumentations/worker/instrumentD1.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport type { D1Database, D1PreparedStatement, D1Response } from '@cloudflare/workers-types';\nimport type { Span, SpanAttributes, StartSpanOptions } from '@sentry/core';\nimport { addBreadcrumb, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_STATUS_ERROR, startSpan } from '@sentry/core';\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\nfunction createD1Breadcrumb(query: string, type: 'first' | 'run' | 'all' | 'raw', d1Result?: D1Response): void {\n addBreadcrumb({\n category: 'query',\n message: query,\n data: {\n ...(d1Result ? getAttributesFromD1Response(d1Result) : {}),\n 'cloudflare.d1.query_type': type,\n },\n });\n}\n\nfunction createStartSpanOptions(query: string, type: 'first' | 'run' | 'all' | 'raw'): StartSpanOptions {\n return {\n op: 'db.query',\n name: query,\n attributes: {\n 'cloudflare.d1.query_type': type,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.db.cloudflare.d1',\n },\n };\n}\n\nfunction _instrumentD1(db: D1Database): D1Database {\n db.prepare = new Proxy(db.prepare, {\n apply(target, thisArg, args: Parameters<typeof db.prepare>) {\n const [query] = args;\n return instrumentD1PreparedStatement(Reflect.apply(target, thisArg, args), query);\n },\n });\n\n return db;\n}\n\nexport function instrumentD1(db: D1Database): D1Database {\n return ensureInstrumented(db, _instrumentD1);\n}\n\n// todo(v11): Remove this export\n/**\n * Instruments Cloudflare D1 bindings with Sentry.\n *\n * @deprecated `withSentry()` automatically instruments all D1 bindings via `env`\n * so this function is not needed anymore. It will be removed in the next major version of the SDK.\n *\n * @example\n *\n * ```js\n * // env.DB is the D1 DB binding configured in your `wrangler.toml`\n * const db = instrumentD1WithSentry(env.DB);\n * // Now you can use the database as usual\n * await db.prepare('SELECT * FROM table WHERE id = ?').bind(1).run();\n * ```\n */\nexport function instrumentD1WithSentry(db: D1Database): D1Database {\n return instrumentD1(db);\n}\n"],"names":["startSpan","SPAN_STATUS_ERROR","addBreadcrumb","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 type { Span, SpanAttributes, StartSpanOptions } from '@sentry/core';\nimport { addBreadcrumb, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_STATUS_ERROR, startSpan } from '@sentry/core';\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 return {\n op: 'db.query',\n name: query,\n attributes: {\n 'db.system.name': 'cloudflare-d1',\n 'db.operation.name': type,\n 'db.query.text': query,\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 op: 'db.query',\n name: 'D1 batch',\n attributes: {\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\n// todo(v11): Remove this export\n/**\n * Instruments Cloudflare D1 bindings with Sentry.\n *\n * @deprecated `withSentry()` automatically instruments all D1 bindings via `env`\n * so this function is not needed anymore. It will be removed in the next major version of the SDK.\n *\n * @example\n *\n * ```js\n * // env.DB is the D1 DB binding configured in your `wrangler.toml`\n * const db = instrumentD1WithSentry(env.DB);\n * // Now you can use the database as usual\n * await db.prepare('SELECT * FROM table WHERE id = ?').bind(1).run();\n * ```\n */\nexport function instrumentD1WithSentry(db: D1Database): D1Database {\n return instrumentD1(db);\n}\n"],"names":["startSpan","SPAN_STATUS_ERROR","addBreadcrumb","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","ensureInstrumented"],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ const rpcOptions = require('../../utils/rpcOptions.js');
|
|
|
7
7
|
const instrumentDurableObjectNamespace = require('../instrumentDurableObjectNamespace.js');
|
|
8
8
|
const instrumentFetcher = require('./instrumentFetcher.js');
|
|
9
9
|
const instrumentQueueProducer = require('./instrumentQueueProducer.js');
|
|
10
|
+
const instrumentR2 = require('./instrumentR2.js');
|
|
10
11
|
|
|
11
12
|
function isProxyable(item) {
|
|
12
13
|
return item !== null && (typeof item === "object" || typeof item === "function");
|
|
@@ -38,6 +39,12 @@ function instrumentEnv(env, options) {
|
|
|
38
39
|
instrumentedBindings.set(item, instrumented);
|
|
39
40
|
return instrumented;
|
|
40
41
|
}
|
|
42
|
+
if (isBinding.isR2Bucket(item)) {
|
|
43
|
+
const bindingName = typeof prop === "string" ? prop : String(prop);
|
|
44
|
+
const instrumented = instrumentR2.instrumentR2Bucket(item, bindingName);
|
|
45
|
+
instrumentedBindings.set(item, instrumented);
|
|
46
|
+
return instrumented;
|
|
47
|
+
}
|
|
41
48
|
if (!rpcPropagation) {
|
|
42
49
|
return item;
|
|
43
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentEnv.js","sources":["../../../../src/instrumentations/worker/instrumentEnv.ts"],"sourcesContent":["import type { CloudflareOptions } from '../../client';\nimport { isD1Database, isDurableObjectNamespace, isJSRPC, isQueue } from '../../utils/isBinding';\nimport { instrumentD1 } from './instrumentD1';\nimport { appendRpcMeta } from '../../utils/rpcMeta';\nimport { getEffectiveRpcPropagation } from '../../utils/rpcOptions';\nimport { instrumentDurableObjectNamespace, STUB_NON_RPC_METHODS } from '../instrumentDurableObjectNamespace';\nimport { instrumentFetcher } from './instrumentFetcher';\nimport { instrumentQueueProducer } from './instrumentQueueProducer';\n\nfunction isProxyable(item: unknown): item is object {\n return item !== null && (typeof item === 'object' || typeof item === 'function');\n}\n\nconst instrumentedBindings = new WeakMap<object, unknown>();\n\n/**\n * Wraps the Cloudflare `env` object in a Proxy that detects binding types\n * on property access and returns instrumented versions.\n *\n * Currently detects:\n * - DurableObjectNamespace (via `idFromName` duck-typing)\n * - Service bindings / JSRPC proxies\n * - Queue producers (via `send` + `sendBatch` duck-typing)\n
|
|
1
|
+
{"version":3,"file":"instrumentEnv.js","sources":["../../../../src/instrumentations/worker/instrumentEnv.ts"],"sourcesContent":["import type { CloudflareOptions } from '../../client';\nimport { isD1Database, isDurableObjectNamespace, isJSRPC, isQueue, isR2Bucket } from '../../utils/isBinding';\nimport { instrumentD1 } from './instrumentD1';\nimport { appendRpcMeta } from '../../utils/rpcMeta';\nimport { getEffectiveRpcPropagation } from '../../utils/rpcOptions';\nimport { instrumentDurableObjectNamespace, STUB_NON_RPC_METHODS } from '../instrumentDurableObjectNamespace';\nimport { instrumentFetcher } from './instrumentFetcher';\nimport { instrumentQueueProducer } from './instrumentQueueProducer';\nimport { instrumentR2Bucket } from './instrumentR2';\n\nfunction isProxyable(item: unknown): item is object {\n return item !== null && (typeof item === 'object' || typeof item === 'function');\n}\n\nconst instrumentedBindings = new WeakMap<object, unknown>();\n\n/**\n * Wraps the Cloudflare `env` object in a Proxy that detects binding types\n * on property access and returns instrumented versions.\n *\n * Currently detects:\n * - DurableObjectNamespace (via `idFromName` duck-typing)\n * - Service bindings / JSRPC proxies\n * - Queue producers (via `send` + `sendBatch` duck-typing)\n * - R2 Buckets (via `head` + `put` + `createMultipartUpload` duck-typing)\n *\n * @param env - The Cloudflare env object to instrument\n * @param options - Optional CloudflareOptions to control RPC trace propagation\n */\nexport function instrumentEnv<Env extends Record<string, unknown>>(env: Env, options?: CloudflareOptions): Env {\n if (!env || typeof env !== 'object') {\n return env;\n }\n\n const rpcPropagation = options ? getEffectiveRpcPropagation(options) : false;\n\n return new Proxy(env, {\n get(target, prop, receiver) {\n const item = Reflect.get(target, prop, receiver);\n\n if (!isProxyable(item)) {\n return item;\n }\n\n const cached = instrumentedBindings.get(item);\n\n if (cached) {\n return cached;\n }\n\n if (isD1Database(item)) {\n const instrumented = instrumentD1(item);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isQueue(item)) {\n const bindingName = typeof prop === 'string' ? prop : String(prop);\n const instrumented = instrumentQueueProducer(item, bindingName);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isR2Bucket(item)) {\n const bindingName = typeof prop === 'string' ? prop : String(prop);\n const instrumented = instrumentR2Bucket(item, bindingName);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (!rpcPropagation) {\n return item;\n }\n\n if (isDurableObjectNamespace(item)) {\n const instrumented = instrumentDurableObjectNamespace(item);\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n if (isJSRPC(item)) {\n const instrumented = new Proxy(item, {\n get(target, p) {\n const value = Reflect.get(target, p);\n\n if (p === 'fetch' && typeof value === 'function') {\n return instrumentFetcher((...args) => Reflect.apply(value, target, args));\n }\n\n if (typeof value === 'function' && typeof p === 'string' && !STUB_NON_RPC_METHODS.has(p)) {\n return (...args: unknown[]) => Reflect.apply(value, target, appendRpcMeta(args));\n }\n\n return value;\n },\n });\n\n instrumentedBindings.set(item, instrumented);\n return instrumented;\n }\n\n return item;\n },\n });\n}\n"],"names":["getEffectiveRpcPropagation","isD1Database","instrumentD1","isQueue","instrumentQueueProducer","isR2Bucket","instrumentR2Bucket","isDurableObjectNamespace","instrumentDurableObjectNamespace","isJSRPC","target","instrumentFetcher","STUB_NON_RPC_METHODS","appendRpcMeta"],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
|
|
5
|
+
const ORIGIN = "auto.faas.cloudflare.r2";
|
|
6
|
+
const R2_OPERATIONS = {
|
|
7
|
+
get: { spanName: "r2_get", op: "object.get", operation: "GetObject" },
|
|
8
|
+
head: { spanName: "r2_head", op: "object.head", operation: "HeadObject" },
|
|
9
|
+
put: { spanName: "r2_put", op: "object.put", operation: "PutObject" },
|
|
10
|
+
delete: { spanName: "r2_delete", op: "object.delete", operation: "DeleteObject" },
|
|
11
|
+
list: { spanName: "r2_list", op: "object.list", operation: "ListObjects" },
|
|
12
|
+
uploadPart: { spanName: "r2_uploadPart", op: "object.upload_part", operation: "UploadPart" },
|
|
13
|
+
abortMultipartUpload: {
|
|
14
|
+
spanName: "r2_abortMultipartUpload",
|
|
15
|
+
op: "object.multipart_upload.abort",
|
|
16
|
+
operation: "AbortMultipartUpload"
|
|
17
|
+
},
|
|
18
|
+
createMultipartUpload: {
|
|
19
|
+
spanName: "r2_createMultipartUpload",
|
|
20
|
+
op: "object.multipart_upload.create",
|
|
21
|
+
operation: "CreateMultipartUpload"
|
|
22
|
+
},
|
|
23
|
+
completeMultipartUpload: {
|
|
24
|
+
spanName: "r2_completeMultipartUpload",
|
|
25
|
+
op: "object.multipart_upload.complete",
|
|
26
|
+
operation: "CompleteMultipartUpload"
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
function isR2ListOptions(key) {
|
|
30
|
+
return typeof key === "object" && key !== null && !Array.isArray(key);
|
|
31
|
+
}
|
|
32
|
+
function createSpanOptions(bindingName, r2Op, key) {
|
|
33
|
+
const { spanName, op, operation } = R2_OPERATIONS[r2Op];
|
|
34
|
+
const requestKey = Array.isArray(key) ? key.join(", ") : typeof key === "string" ? key : void 0;
|
|
35
|
+
return {
|
|
36
|
+
op,
|
|
37
|
+
name: spanName,
|
|
38
|
+
attributes: {
|
|
39
|
+
"cloudflare.r2.operation": operation,
|
|
40
|
+
"cloudflare.r2.bucket": bindingName,
|
|
41
|
+
...requestKey !== void 0 && { "cloudflare.r2.request.key": requestKey },
|
|
42
|
+
...isR2ListOptions(key) && key.prefix !== void 0 && { "cloudflare.r2.request.prefix": key.prefix },
|
|
43
|
+
...isR2ListOptions(key) && key.delimiter !== void 0 && { "cloudflare.r2.request.delimiter": key.delimiter },
|
|
44
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,
|
|
45
|
+
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function instrumentR2MultipartUpload(upload, bindingName) {
|
|
50
|
+
const { key } = upload;
|
|
51
|
+
return new Proxy(upload, {
|
|
52
|
+
get(target, prop, receiver) {
|
|
53
|
+
if (prop === "uploadPart") {
|
|
54
|
+
const original = Reflect.get(target, prop, receiver);
|
|
55
|
+
return function(...args) {
|
|
56
|
+
const [partNumber] = args;
|
|
57
|
+
return core.startSpan(
|
|
58
|
+
{
|
|
59
|
+
...createSpanOptions(bindingName, "uploadPart", key),
|
|
60
|
+
attributes: {
|
|
61
|
+
...createSpanOptions(bindingName, "uploadPart", key).attributes,
|
|
62
|
+
"cloudflare.r2.request.part_number": partNumber
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
() => Reflect.apply(original, target, args)
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (prop === "abort") {
|
|
70
|
+
const original = Reflect.get(target, prop, receiver);
|
|
71
|
+
return function() {
|
|
72
|
+
return core.startSpan(
|
|
73
|
+
createSpanOptions(bindingName, "abortMultipartUpload", key),
|
|
74
|
+
() => Reflect.apply(original, target, [])
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (prop === "complete") {
|
|
79
|
+
const original = Reflect.get(target, prop, receiver);
|
|
80
|
+
return function(...args) {
|
|
81
|
+
return core.startSpan(
|
|
82
|
+
createSpanOptions(bindingName, "completeMultipartUpload", key),
|
|
83
|
+
() => Reflect.apply(original, target, args)
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return Reflect.get(target, prop, receiver);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function instrumentR2Bucket(bucket, bindingName) {
|
|
92
|
+
return new Proxy(bucket, {
|
|
93
|
+
get(target, prop, receiver) {
|
|
94
|
+
if (prop === "get" || prop === "head" || prop === "put" || prop === "delete" || prop === "list") {
|
|
95
|
+
const original = Reflect.get(target, prop, receiver);
|
|
96
|
+
return function(...args) {
|
|
97
|
+
const [key] = args;
|
|
98
|
+
return core.startSpan(createSpanOptions(bindingName, prop, key), () => Reflect.apply(original, target, args));
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (prop === "createMultipartUpload") {
|
|
102
|
+
const original = Reflect.get(target, prop, receiver);
|
|
103
|
+
return function(...args) {
|
|
104
|
+
const [key] = args;
|
|
105
|
+
return core.startSpan(createSpanOptions(bindingName, "createMultipartUpload", key), async () => {
|
|
106
|
+
const upload = await Reflect.apply(original, target, args);
|
|
107
|
+
return instrumentR2MultipartUpload(upload, bindingName);
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (prop === "resumeMultipartUpload") {
|
|
112
|
+
const original = Reflect.get(target, prop, receiver);
|
|
113
|
+
return function(...args) {
|
|
114
|
+
const upload = Reflect.apply(original, target, args);
|
|
115
|
+
return instrumentR2MultipartUpload(upload, bindingName);
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return Reflect.get(target, prop, receiver);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
exports.instrumentR2Bucket = instrumentR2Bucket;
|
|
124
|
+
//# sourceMappingURL=instrumentR2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumentR2.js","sources":["../../../../src/instrumentations/worker/instrumentR2.ts"],"sourcesContent":["import type { R2Bucket, R2ListOptions, R2MultipartUpload } from '@cloudflare/workers-types';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startSpan } from '@sentry/core';\n\nconst ORIGIN = 'auto.faas.cloudflare.r2';\n\nconst R2_OPERATIONS = {\n get: { spanName: 'r2_get', op: 'object.get', operation: 'GetObject' },\n head: { spanName: 'r2_head', op: 'object.head', operation: 'HeadObject' },\n put: { spanName: 'r2_put', op: 'object.put', operation: 'PutObject' },\n delete: { spanName: 'r2_delete', op: 'object.delete', operation: 'DeleteObject' },\n list: { spanName: 'r2_list', op: 'object.list', operation: 'ListObjects' },\n uploadPart: { spanName: 'r2_uploadPart', op: 'object.upload_part', operation: 'UploadPart' },\n abortMultipartUpload: {\n spanName: 'r2_abortMultipartUpload',\n op: 'object.multipart_upload.abort',\n operation: 'AbortMultipartUpload',\n },\n createMultipartUpload: {\n spanName: 'r2_createMultipartUpload',\n op: 'object.multipart_upload.create',\n operation: 'CreateMultipartUpload',\n },\n completeMultipartUpload: {\n spanName: 'r2_completeMultipartUpload',\n op: 'object.multipart_upload.complete',\n operation: 'CompleteMultipartUpload',\n },\n} as const;\n\ntype R2OperationKey = keyof typeof R2_OPERATIONS;\n\nfunction isR2ListOptions(key: unknown): key is R2ListOptions {\n return typeof key === 'object' && key !== null && !Array.isArray(key);\n}\n\nfunction createSpanOptions(bindingName: string, r2Op: R2OperationKey, key?: string | string[] | R2ListOptions) {\n const { spanName, op, operation } = R2_OPERATIONS[r2Op];\n const requestKey = Array.isArray(key) ? key.join(', ') : typeof key === 'string' ? key : undefined;\n\n return {\n op,\n name: spanName,\n attributes: {\n 'cloudflare.r2.operation': operation,\n 'cloudflare.r2.bucket': bindingName,\n ...(requestKey !== undefined && { 'cloudflare.r2.request.key': requestKey }),\n ...(isR2ListOptions(key) && key.prefix !== undefined && { 'cloudflare.r2.request.prefix': key.prefix }),\n ...(isR2ListOptions(key) && key.delimiter !== undefined && { 'cloudflare.r2.request.delimiter': key.delimiter }),\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN,\n },\n };\n}\n\nfunction instrumentR2MultipartUpload(upload: R2MultipartUpload, bindingName: string): R2MultipartUpload {\n const { key } = upload;\n\n return new Proxy(upload, {\n get(target, prop, receiver) {\n if (prop === 'uploadPart') {\n const original = Reflect.get(target, prop, receiver);\n\n return function (this: unknown, ...args: Parameters<R2MultipartUpload['uploadPart']>) {\n const [partNumber] = args;\n\n return startSpan(\n {\n ...createSpanOptions(bindingName, 'uploadPart', key),\n attributes: {\n ...createSpanOptions(bindingName, 'uploadPart', key).attributes,\n 'cloudflare.r2.request.part_number': partNumber,\n },\n },\n () => Reflect.apply(original, target, args),\n );\n };\n }\n\n if (prop === 'abort') {\n const original = Reflect.get(target, prop, receiver);\n\n return function (this: unknown) {\n return startSpan(createSpanOptions(bindingName, 'abortMultipartUpload', key), () =>\n Reflect.apply(original, target, []),\n );\n };\n }\n\n if (prop === 'complete') {\n const original = Reflect.get(target, prop, receiver);\n\n return function (this: unknown, ...args: Parameters<R2MultipartUpload['complete']>) {\n return startSpan(createSpanOptions(bindingName, 'completeMultipartUpload', key), () =>\n Reflect.apply(original, target, args),\n );\n };\n }\n\n return Reflect.get(target, prop, receiver);\n },\n });\n}\n\n/**\n * Wraps a Cloudflare R2 Bucket binding to create spans on bucket operations.\n *\n * Instrumented methods: get, head, put, delete, list, createMultipartUpload,\n * resumeMultipartUpload (and the resulting multipart upload operations).\n */\nexport function instrumentR2Bucket<T extends R2Bucket>(bucket: T, bindingName: string): T {\n return new Proxy(bucket, {\n get(target, prop, receiver) {\n if (prop === 'get' || prop === 'head' || prop === 'put' || prop === 'delete' || prop === 'list') {\n const original = Reflect.get(target, prop, receiver);\n\n return function (this: unknown, ...args: Parameters<R2Bucket[typeof prop]>) {\n const [key] = args;\n\n return startSpan(createSpanOptions(bindingName, prop, key), () => Reflect.apply(original, target, args));\n };\n }\n\n if (prop === 'createMultipartUpload') {\n const original = Reflect.get(target, prop, receiver) as R2Bucket['createMultipartUpload'];\n\n return function (this: unknown, ...args: Parameters<R2Bucket['createMultipartUpload']>) {\n const [key] = args;\n\n return startSpan(createSpanOptions(bindingName, 'createMultipartUpload', key), async () => {\n const upload = await Reflect.apply(original, target, args);\n return instrumentR2MultipartUpload(upload, bindingName);\n });\n };\n }\n\n if (prop === 'resumeMultipartUpload') {\n const original = Reflect.get(target, prop, receiver);\n\n return function (this: unknown, ...args: Parameters<R2Bucket['resumeMultipartUpload']>) {\n const upload = Reflect.apply(original, target, args);\n\n return instrumentR2MultipartUpload(upload, bindingName);\n };\n }\n\n return Reflect.get(target, prop, receiver);\n },\n });\n}\n"],"names":["SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","startSpan"],"mappings":"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"}
|
|
@@ -17,9 +17,13 @@ function isQueue(item) {
|
|
|
17
17
|
function isD1Database(item) {
|
|
18
18
|
return item != null && isNotJSRPC(item) && typeof item.prepare === "function" && typeof item.batch === "function" && typeof item.exec === "function";
|
|
19
19
|
}
|
|
20
|
+
function isR2Bucket(item) {
|
|
21
|
+
return item != null && isNotJSRPC(item) && typeof item.head === "function" && typeof item.put === "function" && typeof item.createMultipartUpload === "function";
|
|
22
|
+
}
|
|
20
23
|
|
|
21
24
|
exports.isD1Database = isD1Database;
|
|
22
25
|
exports.isDurableObjectNamespace = isDurableObjectNamespace;
|
|
23
26
|
exports.isJSRPC = isJSRPC;
|
|
24
27
|
exports.isQueue = isQueue;
|
|
28
|
+
exports.isR2Bucket = isR2Bucket;
|
|
25
29
|
//# sourceMappingURL=isBinding.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isBinding.js","sources":["../../../src/utils/isBinding.ts"],"sourcesContent":["/**\n * Adapted from https://github.com/evanderkoogh/otel-cf-workers/blob/effeb549f0a4ed1c55ea0c4f0d8e8e37e5494fb3/src/instrumentation/env.ts\n *\n * BSD 3-Clause License\n *\n * Copyright (c) 2023, Erwin van der Koogh\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the documentation\n * and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport type { D1Database, DurableObjectNamespace, Queue } from '@cloudflare/workers-types';\n\n/**\n * Checks if a value is a JSRPC proxy (service binding).\n *\n * JSRPC proxies return a truthy value for ANY property access, including\n * properties that don't exist. This makes other duck-type checks unreliable\n * unless we exclude JSRPC first.\n *\n * Must be checked before other binding type checks.\n */\nexport function isJSRPC(item: unknown): item is Service {\n try {\n return !!(item as Record<string, unknown>)[`__some_property_that_will_never_exist__${Math.random()}`];\n } catch {\n return false;\n }\n}\n\nconst isNotJSRPC = (item: unknown): item is Record<string, unknown> => !isJSRPC(item);\n\n/**\n * Duck-type check for DurableObjectNamespace bindings.\n * DurableObjectNamespace has `idFromName`, `idFromString`, `get`, `newUniqueId`.\n */\nexport function isDurableObjectNamespace(item: unknown): item is DurableObjectNamespace {\n return item != null && isNotJSRPC(item) && typeof item.idFromName === 'function';\n}\n\n/**\n * Duck-type check for Queue producer bindings.\n * Queue has `send` and `sendBatch` async methods.\n */\nexport function isQueue(item: unknown): item is Queue {\n return item != null && isNotJSRPC(item) && typeof item.send === 'function' && typeof item.sendBatch === 'function';\n}\n\n/**\n * Duck-type check for D1Database bindings.\n * D1Database has `prepare`, `batch`, and `exec` methods.\n */\nexport function isD1Database(item: unknown): item is D1Database {\n return (\n item != null &&\n isNotJSRPC(item) &&\n typeof item.prepare === 'function' &&\n typeof item.batch === 'function' &&\n typeof item.exec === 'function'\n );\n}\n"],"names":[],"mappings":";;AA4CO,SAAS,QAAQ,IAAA,EAAgC;AACtD,EAAA,IAAI;AACF,IAAA,OAAO,CAAC,CAAE,IAAA,CAAiC,0CAA0C,IAAA,CAAK,MAAA,EAAQ,CAAA,CAAE,CAAA;AAAA,EACtG,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,MAAM,UAAA,GAAa,CAAC,IAAA,KAAmD,CAAC,QAAQ,IAAI,CAAA;AAM7E,SAAS,yBAAyB,IAAA,EAA+C;AACtF,EAAA,OAAO,QAAQ,IAAA,IAAQ,UAAA,CAAW,IAAI,CAAA,IAAK,OAAO,KAAK,UAAA,KAAe,UAAA;AACxE;AAMO,SAAS,QAAQ,IAAA,EAA8B;AACpD,EAAA,OAAO,IAAA,IAAQ,IAAA,IAAQ,UAAA,CAAW,IAAI,CAAA,IAAK,OAAO,IAAA,CAAK,IAAA,KAAS,UAAA,IAAc,OAAO,IAAA,CAAK,SAAA,KAAc,UAAA;AAC1G;AAMO,SAAS,aAAa,IAAA,EAAmC;AAC9D,EAAA,OACE,IAAA,IAAQ,IAAA,IACR,UAAA,CAAW,IAAI,KACf,OAAO,IAAA,CAAK,OAAA,KAAY,UAAA,IACxB,OAAO,IAAA,CAAK,KAAA,KAAU,UAAA,IACtB,OAAO,KAAK,IAAA,KAAS,UAAA;AAEzB
|
|
1
|
+
{"version":3,"file":"isBinding.js","sources":["../../../src/utils/isBinding.ts"],"sourcesContent":["/**\n * Adapted from https://github.com/evanderkoogh/otel-cf-workers/blob/effeb549f0a4ed1c55ea0c4f0d8e8e37e5494fb3/src/instrumentation/env.ts\n *\n * BSD 3-Clause License\n *\n * Copyright (c) 2023, Erwin van der Koogh\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the documentation\n * and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport type { D1Database, DurableObjectNamespace, Queue, R2Bucket } from '@cloudflare/workers-types';\n\n/**\n * Checks if a value is a JSRPC proxy (service binding).\n *\n * JSRPC proxies return a truthy value for ANY property access, including\n * properties that don't exist. This makes other duck-type checks unreliable\n * unless we exclude JSRPC first.\n *\n * Must be checked before other binding type checks.\n */\nexport function isJSRPC(item: unknown): item is Service {\n try {\n return !!(item as Record<string, unknown>)[`__some_property_that_will_never_exist__${Math.random()}`];\n } catch {\n return false;\n }\n}\n\nconst isNotJSRPC = (item: unknown): item is Record<string, unknown> => !isJSRPC(item);\n\n/**\n * Duck-type check for DurableObjectNamespace bindings.\n * DurableObjectNamespace has `idFromName`, `idFromString`, `get`, `newUniqueId`.\n */\nexport function isDurableObjectNamespace(item: unknown): item is DurableObjectNamespace {\n return item != null && isNotJSRPC(item) && typeof item.idFromName === 'function';\n}\n\n/**\n * Duck-type check for Queue producer bindings.\n * Queue has `send` and `sendBatch` async methods.\n */\nexport function isQueue(item: unknown): item is Queue {\n return item != null && isNotJSRPC(item) && typeof item.send === 'function' && typeof item.sendBatch === 'function';\n}\n\n/**\n * Duck-type check for D1Database bindings.\n * D1Database has `prepare`, `batch`, and `exec` methods.\n */\nexport function isD1Database(item: unknown): item is D1Database {\n return (\n item != null &&\n isNotJSRPC(item) &&\n typeof item.prepare === 'function' &&\n typeof item.batch === 'function' &&\n typeof item.exec === 'function'\n );\n}\n\n/**\n * Duck-type check for R2 Bucket bindings.\n * R2Bucket has `head`, `put`, and `createMultipartUpload` methods.\n */\nexport function isR2Bucket(item: unknown): item is R2Bucket {\n return (\n item != null &&\n isNotJSRPC(item) &&\n typeof item.head === 'function' &&\n typeof item.put === 'function' &&\n typeof item.createMultipartUpload === 'function'\n );\n}\n"],"names":[],"mappings":";;AA4CO,SAAS,QAAQ,IAAA,EAAgC;AACtD,EAAA,IAAI;AACF,IAAA,OAAO,CAAC,CAAE,IAAA,CAAiC,0CAA0C,IAAA,CAAK,MAAA,EAAQ,CAAA,CAAE,CAAA;AAAA,EACtG,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,MAAM,UAAA,GAAa,CAAC,IAAA,KAAmD,CAAC,QAAQ,IAAI,CAAA;AAM7E,SAAS,yBAAyB,IAAA,EAA+C;AACtF,EAAA,OAAO,QAAQ,IAAA,IAAQ,UAAA,CAAW,IAAI,CAAA,IAAK,OAAO,KAAK,UAAA,KAAe,UAAA;AACxE;AAMO,SAAS,QAAQ,IAAA,EAA8B;AACpD,EAAA,OAAO,IAAA,IAAQ,IAAA,IAAQ,UAAA,CAAW,IAAI,CAAA,IAAK,OAAO,IAAA,CAAK,IAAA,KAAS,UAAA,IAAc,OAAO,IAAA,CAAK,SAAA,KAAc,UAAA;AAC1G;AAMO,SAAS,aAAa,IAAA,EAAmC;AAC9D,EAAA,OACE,IAAA,IAAQ,IAAA,IACR,UAAA,CAAW,IAAI,KACf,OAAO,IAAA,CAAK,OAAA,KAAY,UAAA,IACxB,OAAO,IAAA,CAAK,KAAA,KAAU,UAAA,IACtB,OAAO,KAAK,IAAA,KAAS,UAAA;AAEzB;AAMO,SAAS,WAAW,IAAA,EAAiC;AAC1D,EAAA,OACE,IAAA,IAAQ,IAAA,IACR,UAAA,CAAW,IAAI,KACf,OAAO,IAAA,CAAK,IAAA,KAAS,UAAA,IACrB,OAAO,IAAA,CAAK,GAAA,KAAQ,UAAA,IACpB,OAAO,KAAK,qBAAA,KAA0B,UAAA;AAE1C;;;;;;;;"}
|
package/build/esm/async.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
-
import { setAsyncContextStrategy, getDefaultIsolationScope, getDefaultCurrentScope } from '@sentry/core';
|
|
2
|
+
import { setAsyncContextStrategy, _INTERNAL_createTracingChannelBinding, getDefaultIsolationScope, getDefaultCurrentScope } from '@sentry/core';
|
|
3
3
|
|
|
4
4
|
function setAsyncLocalStorageAsyncContextStrategy() {
|
|
5
5
|
const asyncStorage = new AsyncLocalStorage();
|
|
@@ -52,7 +52,8 @@ function setAsyncLocalStorageAsyncContextStrategy() {
|
|
|
52
52
|
withIsolationScope,
|
|
53
53
|
withSetIsolationScope,
|
|
54
54
|
getCurrentScope: () => getScopes().scope,
|
|
55
|
-
getIsolationScope: () => getScopes().isolationScope
|
|
55
|
+
getIsolationScope: () => getScopes().isolationScope,
|
|
56
|
+
getTracingChannelBinding: () => _INTERNAL_createTracingChannelBinding(asyncStorage, getScopes)
|
|
56
57
|
});
|
|
57
58
|
}
|
|
58
59
|
|
package/build/esm/async.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async.js","sources":["../../src/async.ts"],"sourcesContent":["// Need to use node: prefix for cloudflare workers compatibility\n// Note: Because we are using node:async_hooks, we need to set `node_compat` in the wrangler.toml\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Scope } from '@sentry/core';\nimport {
|
|
1
|
+
{"version":3,"file":"async.js","sources":["../../src/async.ts"],"sourcesContent":["// Need to use node: prefix for cloudflare workers compatibility\n// Note: Because we are using node:async_hooks, we need to set `node_compat` in the wrangler.toml\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Scope } from '@sentry/core';\nimport {\n _INTERNAL_createTracingChannelBinding,\n getDefaultCurrentScope,\n getDefaultIsolationScope,\n setAsyncContextStrategy,\n} from '@sentry/core';\n\n/**\n * Sets the async context strategy to use AsyncLocalStorage.\n *\n * AsyncLocalStorage is only available in the cloudflare workers runtime if you set\n * compatibility_flags = [\"nodejs_compat\"] or compatibility_flags = [\"nodejs_als\"]\n *\n * @internal Only exported to be used in higher-level Sentry packages\n * @hidden Only exported to be used in higher-level Sentry packages\n */\nexport function setAsyncLocalStorageAsyncContextStrategy(): void {\n const asyncStorage = new AsyncLocalStorage<{\n scope: Scope;\n isolationScope: Scope;\n }>();\n\n function getScopes(): { scope: Scope; isolationScope: Scope } {\n const scopes = asyncStorage.getStore();\n\n if (scopes) {\n return scopes;\n }\n\n // fallback behavior:\n // if, for whatever reason, we can't find scopes on the context here, we have to fix this somehow\n return {\n scope: getDefaultCurrentScope(),\n isolationScope: getDefaultIsolationScope(),\n };\n }\n\n function withScope<T>(callback: (scope: Scope) => T): T {\n const scope = getScopes().scope.clone();\n const isolationScope = getScopes().isolationScope;\n return asyncStorage.run({ scope, isolationScope }, () => {\n return callback(scope);\n });\n }\n\n function withSetScope<T>(scope: Scope, callback: (scope: Scope) => T): T {\n const isolationScope = getScopes().isolationScope.clone();\n return asyncStorage.run({ scope, isolationScope }, () => {\n return callback(scope);\n });\n }\n\n function withIsolationScope<T>(callback: (isolationScope: Scope) => T): T {\n const scope = getScopes().scope;\n const isolationScope = getScopes().isolationScope.clone();\n return asyncStorage.run({ scope, isolationScope }, () => {\n return callback(isolationScope);\n });\n }\n\n function withSetIsolationScope<T>(isolationScope: Scope, callback: (isolationScope: Scope) => T): T {\n const scope = getScopes().scope;\n return asyncStorage.run({ scope, isolationScope }, () => {\n return callback(isolationScope);\n });\n }\n\n // In contrast to the browser, we can rely on async context isolation here\n function suppressTracing<T>(callback: () => T): T {\n return withScope(scope => {\n scope.setSDKProcessingMetadata({ __SENTRY_SUPPRESS_TRACING__: true });\n return callback();\n });\n }\n\n setAsyncContextStrategy({\n suppressTracing,\n withScope,\n withSetScope,\n withIsolationScope,\n withSetIsolationScope,\n getCurrentScope: () => getScopes().scope,\n getIsolationScope: () => getScopes().isolationScope,\n getTracingChannelBinding: () => _INTERNAL_createTracingChannelBinding(asyncStorage, getScopes),\n });\n}\n"],"names":[],"mappings":";;;AAoBO,SAAS,wCAAA,GAAiD;AAC/D,EAAA,MAAM,YAAA,GAAe,IAAI,iBAAA,EAGtB;AAEH,EAAA,SAAS,SAAA,GAAqD;AAC5D,IAAA,MAAM,MAAA,GAAS,aAAa,QAAA,EAAS;AAErC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,OAAO,MAAA;AAAA,IACT;AAIA,IAAA,OAAO;AAAA,MACL,OAAO,sBAAA,EAAuB;AAAA,MAC9B,gBAAgB,wBAAA;AAAyB,KAC3C;AAAA,EACF;AAEA,EAAA,SAAS,UAAa,QAAA,EAAkC;AACtD,IAAA,MAAM,KAAA,GAAQ,SAAA,EAAU,CAAE,KAAA,CAAM,KAAA,EAAM;AACtC,IAAA,MAAM,cAAA,GAAiB,WAAU,CAAE,cAAA;AACnC,IAAA,OAAO,aAAa,GAAA,CAAI,EAAE,KAAA,EAAO,cAAA,IAAkB,MAAM;AACvD,MAAA,OAAO,SAAS,KAAK,CAAA;AAAA,IACvB,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,SAAS,YAAA,CAAgB,OAAc,QAAA,EAAkC;AACvE,IAAA,MAAM,cAAA,GAAiB,SAAA,EAAU,CAAE,cAAA,CAAe,KAAA,EAAM;AACxD,IAAA,OAAO,aAAa,GAAA,CAAI,EAAE,KAAA,EAAO,cAAA,IAAkB,MAAM;AACvD,MAAA,OAAO,SAAS,KAAK,CAAA;AAAA,IACvB,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,SAAS,mBAAsB,QAAA,EAA2C;AACxE,IAAA,MAAM,KAAA,GAAQ,WAAU,CAAE,KAAA;AAC1B,IAAA,MAAM,cAAA,GAAiB,SAAA,EAAU,CAAE,cAAA,CAAe,KAAA,EAAM;AACxD,IAAA,OAAO,aAAa,GAAA,CAAI,EAAE,KAAA,EAAO,cAAA,IAAkB,MAAM;AACvD,MAAA,OAAO,SAAS,cAAc,CAAA;AAAA,IAChC,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,SAAS,qBAAA,CAAyB,gBAAuB,QAAA,EAA2C;AAClG,IAAA,MAAM,KAAA,GAAQ,WAAU,CAAE,KAAA;AAC1B,IAAA,OAAO,aAAa,GAAA,CAAI,EAAE,KAAA,EAAO,cAAA,IAAkB,MAAM;AACvD,MAAA,OAAO,SAAS,cAAc,CAAA;AAAA,IAChC,CAAC,CAAA;AAAA,EACH;AAGA,EAAA,SAAS,gBAAmB,QAAA,EAAsB;AAChD,IAAA,OAAO,UAAU,CAAA,KAAA,KAAS;AACxB,MAAA,KAAA,CAAM,wBAAA,CAAyB,EAAE,2BAAA,EAA6B,IAAA,EAAM,CAAA;AACpE,MAAA,OAAO,QAAA,EAAS;AAAA,IAClB,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,uBAAA,CAAwB;AAAA,IACtB,eAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,kBAAA;AAAA,IACA,qBAAA;AAAA,IACA,eAAA,EAAiB,MAAM,SAAA,EAAU,CAAE,KAAA;AAAA,IACnC,iBAAA,EAAmB,MAAM,SAAA,EAAU,CAAE,cAAA;AAAA,IACrC,wBAAA,EAA0B,MAAM,qCAAA,CAAsC,YAAA,EAAc,SAAS;AAAA,GAC9F,CAAA;AACH;;;;"}
|
package/build/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, close, consoleIntegration, consoleLoggingIntegration, continueTrace, createConsolaReporter, createLangChainCallbackHandler, createTransport, dedupeIntegration, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, growthbookIntegration, inboundFiltersIntegration, instrumentAnthropicAiClient, instrumentCreateReactAgent, instrumentGoogleGenAIClient, instrumentLangChainEmbeddings, instrumentLangGraph, instrumentOpenAiClient, instrumentPostgresJsSql, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, logger, metrics, moduleMetadataIntegration, requestDataIntegration, rewriteFramesIntegration, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanStreamingIntegration, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSpan, startSpanManual, supabaseIntegration, suppressTracing, trpcMiddleware, updateSpanName, withActiveSpan, withIsolationScope, withMonitor, withScope, withStreamedSpan, wrapMcpServerWithSentry, zodErrorsIntegration } from '@sentry/core';
|
|
1
|
+
export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, bindScopeToEmitter, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, close, consoleIntegration, consoleLoggingIntegration, continueTrace, createConsolaReporter, createLangChainCallbackHandler, createTransport, dedupeIntegration, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, getTraceMetaTags, growthbookIntegration, inboundFiltersIntegration, instrumentAnthropicAiClient, instrumentCreateReactAgent, instrumentGoogleGenAIClient, instrumentLangChainEmbeddings, instrumentLangGraph, instrumentOpenAiClient, instrumentPostgresJsSql, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, linkedErrorsIntegration, logger, metrics, moduleMetadataIntegration, requestDataIntegration, rewriteFramesIntegration, setAttribute, setAttributes, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanStreamingIntegration, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSpan, startSpanManual, supabaseIntegration, suppressTracing, trpcMiddleware, updateSpanName, withActiveSpan, withIsolationScope, withMonitor, withScope, withStreamedSpan, wrapMcpServerWithSentry, zodErrorsIntegration } from '@sentry/core';
|
|
2
2
|
export { withSentry } from './withSentry.js';
|
|
3
3
|
export { instrumentDurableObjectWithSentry } from './durableobject.js';
|
|
4
4
|
export { sentryPagesPlugin } from './pages-plugin.js';
|