@sentry/browser 9.8.0 → 9.10.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/npm/cjs/client.js +0 -3
- package/build/npm/cjs/client.js.map +1 -1
- package/build/npm/cjs/diagnose-sdk.js +46 -0
- package/build/npm/cjs/diagnose-sdk.js.map +1 -0
- package/build/npm/cjs/index.js +4 -0
- package/build/npm/cjs/index.js.map +1 -1
- package/build/npm/cjs/log.js +267 -0
- package/build/npm/cjs/log.js.map +1 -0
- package/build/npm/cjs/tracing/browserTracingIntegration.js +20 -0
- package/build/npm/cjs/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/cjs/tracing/previousTrace.js +107 -0
- package/build/npm/cjs/tracing/previousTrace.js.map +1 -0
- package/build/npm/esm/client.js +1 -4
- package/build/npm/esm/client.js.map +1 -1
- package/build/npm/esm/diagnose-sdk.js +44 -0
- package/build/npm/esm/diagnose-sdk.js.map +1 -0
- package/build/npm/esm/index.js +3 -0
- package/build/npm/esm/index.js.map +1 -1
- package/build/npm/esm/log.js +260 -0
- package/build/npm/esm/log.js.map +1 -0
- package/build/npm/esm/package.json +1 -1
- package/build/npm/esm/tracing/browserTracingIntegration.js +21 -1
- package/build/npm/esm/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/esm/tracing/previousTrace.js +101 -0
- package/build/npm/esm/tracing/previousTrace.js.map +1 -0
- package/build/npm/types/client.d.ts.map +1 -1
- package/build/npm/types/diagnose-sdk.d.ts +11 -0
- package/build/npm/types/diagnose-sdk.d.ts.map +1 -0
- package/build/npm/types/index.d.ts +3 -0
- package/build/npm/types/index.d.ts.map +1 -1
- package/build/npm/types/log.d.ts +169 -0
- package/build/npm/types/log.d.ts.map +1 -0
- package/build/npm/types/tracing/browserTracingIntegration.d.ts +22 -0
- package/build/npm/types/tracing/browserTracingIntegration.d.ts.map +1 -1
- package/build/npm/types/tracing/previousTrace.d.ts +31 -0
- package/build/npm/types/tracing/previousTrace.d.ts.map +1 -0
- package/build/npm/types-ts3.8/diagnose-sdk.d.ts +11 -0
- package/build/npm/types-ts3.8/index.d.ts +3 -0
- package/build/npm/types-ts3.8/log.d.ts +169 -0
- package/build/npm/types-ts3.8/tracing/browserTracingIntegration.d.ts +22 -0
- package/build/npm/types-ts3.8/tracing/previousTrace.d.ts +31 -0
- package/package.json +7 -7
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
const helpers = require('../helpers.js');
|
|
5
|
+
require('@sentry-internal/browser-utils');
|
|
6
|
+
require('../stack-parsers.js');
|
|
7
|
+
const debugBuild = require('../debug-build.js');
|
|
8
|
+
require('../integrations/breadcrumbs.js');
|
|
9
|
+
require('../integrations/browserapierrors.js');
|
|
10
|
+
require('../integrations/browsersession.js');
|
|
11
|
+
require('../integrations/globalhandlers.js');
|
|
12
|
+
require('../integrations/httpcontext.js');
|
|
13
|
+
require('../integrations/linkederrors.js');
|
|
14
|
+
|
|
15
|
+
// 1h in seconds
|
|
16
|
+
const PREVIOUS_TRACE_MAX_DURATION = 3600;
|
|
17
|
+
|
|
18
|
+
// session storage key
|
|
19
|
+
const PREVIOUS_TRACE_KEY = 'sentry_previous_trace';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Adds a previous_trace span link to the passed span if the passed
|
|
23
|
+
* previousTraceInfo is still valid.
|
|
24
|
+
*
|
|
25
|
+
* @returns the updated previous trace info (based on the current span/trace) to
|
|
26
|
+
* be used on the next call
|
|
27
|
+
*/
|
|
28
|
+
function addPreviousTraceSpanLink(
|
|
29
|
+
previousTraceInfo,
|
|
30
|
+
span,
|
|
31
|
+
) {
|
|
32
|
+
const spanJson = core.spanToJSON(span);
|
|
33
|
+
|
|
34
|
+
if (!previousTraceInfo) {
|
|
35
|
+
return {
|
|
36
|
+
spanContext: span.spanContext(),
|
|
37
|
+
startTimestamp: spanJson.start_timestamp,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (previousTraceInfo.spanContext.traceId === spanJson.trace_id) {
|
|
42
|
+
// This means, we're still in the same trace so let's not update the previous trace info
|
|
43
|
+
// or add a link to the current span.
|
|
44
|
+
// Once we move away from the long-lived, route-based trace model, we can remove this cases
|
|
45
|
+
return previousTraceInfo;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Only add the link if the startTimeStamp of the previous trace's root span is within
|
|
49
|
+
// PREVIOUS_TRACE_MAX_DURATION (1h) of the current root span's startTimestamp
|
|
50
|
+
// This is done to
|
|
51
|
+
// - avoid adding links to "stale" traces
|
|
52
|
+
// - enable more efficient querying for previous/next traces in Sentry
|
|
53
|
+
if (Date.now() / 1000 - previousTraceInfo.startTimestamp <= PREVIOUS_TRACE_MAX_DURATION) {
|
|
54
|
+
if (debugBuild.DEBUG_BUILD) {
|
|
55
|
+
core.logger.info(
|
|
56
|
+
`Adding previous_trace ${previousTraceInfo.spanContext} link to span ${{
|
|
57
|
+
op: spanJson.op,
|
|
58
|
+
...span.spanContext(),
|
|
59
|
+
}}`,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
span.addLink({
|
|
64
|
+
context: previousTraceInfo.spanContext,
|
|
65
|
+
attributes: {
|
|
66
|
+
[core.SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE]: 'previous_trace',
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
spanContext: span.spanContext(),
|
|
73
|
+
startTimestamp: core.spanToJSON(span).start_timestamp,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Stores @param previousTraceInfo in sessionStorage.
|
|
79
|
+
*/
|
|
80
|
+
function storePreviousTraceInSessionStorage(previousTraceInfo) {
|
|
81
|
+
try {
|
|
82
|
+
helpers.WINDOW.sessionStorage.setItem(PREVIOUS_TRACE_KEY, JSON.stringify(previousTraceInfo));
|
|
83
|
+
} catch (e) {
|
|
84
|
+
// Ignore potential errors (e.g. if sessionStorage is not available)
|
|
85
|
+
debugBuild.DEBUG_BUILD && core.logger.warn('Could not store previous trace in sessionStorage', e);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Retrieves the previous trace from sessionStorage if available.
|
|
91
|
+
*/
|
|
92
|
+
function getPreviousTraceFromSessionStorage() {
|
|
93
|
+
try {
|
|
94
|
+
const previousTraceInfo = helpers.WINDOW.sessionStorage?.getItem(PREVIOUS_TRACE_KEY);
|
|
95
|
+
// @ts-expect-error - intentionally risking JSON.parse throwing when previousTraceInfo is null to save bundle size
|
|
96
|
+
return JSON.parse(previousTraceInfo);
|
|
97
|
+
} catch (e) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
exports.PREVIOUS_TRACE_KEY = PREVIOUS_TRACE_KEY;
|
|
103
|
+
exports.PREVIOUS_TRACE_MAX_DURATION = PREVIOUS_TRACE_MAX_DURATION;
|
|
104
|
+
exports.addPreviousTraceSpanLink = addPreviousTraceSpanLink;
|
|
105
|
+
exports.getPreviousTraceFromSessionStorage = getPreviousTraceFromSessionStorage;
|
|
106
|
+
exports.storePreviousTraceInSessionStorage = storePreviousTraceInSessionStorage;
|
|
107
|
+
//# sourceMappingURL=previousTrace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"previousTrace.js","sources":["../../../../src/tracing/previousTrace.ts"],"sourcesContent":["import type { Span } from '@sentry/core';\nimport { logger, SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE, spanToJSON, type SpanContextData } from '@sentry/core';\nimport { WINDOW } from '../exports';\nimport { DEBUG_BUILD } from '../debug-build';\n\nexport interface PreviousTraceInfo {\n /**\n * Span context of the previous trace's local root span\n */\n spanContext: SpanContextData;\n\n /**\n * Timestamp in seconds when the previous trace was started\n */\n startTimestamp: number;\n}\n\n// 1h in seconds\nexport const PREVIOUS_TRACE_MAX_DURATION = 3600;\n\n// session storage key\nexport const PREVIOUS_TRACE_KEY = 'sentry_previous_trace';\n\n/**\n * Adds a previous_trace span link to the passed span if the passed\n * previousTraceInfo is still valid.\n *\n * @returns the updated previous trace info (based on the current span/trace) to\n * be used on the next call\n */\nexport function addPreviousTraceSpanLink(\n previousTraceInfo: PreviousTraceInfo | undefined,\n span: Span,\n): PreviousTraceInfo {\n const spanJson = spanToJSON(span);\n\n if (!previousTraceInfo) {\n return {\n spanContext: span.spanContext(),\n startTimestamp: spanJson.start_timestamp,\n };\n }\n\n if (previousTraceInfo.spanContext.traceId === spanJson.trace_id) {\n // This means, we're still in the same trace so let's not update the previous trace info\n // or add a link to the current span.\n // Once we move away from the long-lived, route-based trace model, we can remove this cases\n return previousTraceInfo;\n }\n\n // Only add the link if the startTimeStamp of the previous trace's root span is within\n // PREVIOUS_TRACE_MAX_DURATION (1h) of the current root span's startTimestamp\n // This is done to\n // - avoid adding links to \"stale\" traces\n // - enable more efficient querying for previous/next traces in Sentry\n if (Date.now() / 1000 - previousTraceInfo.startTimestamp <= PREVIOUS_TRACE_MAX_DURATION) {\n if (DEBUG_BUILD) {\n logger.info(\n `Adding previous_trace ${previousTraceInfo.spanContext} link to span ${{\n op: spanJson.op,\n ...span.spanContext(),\n }}`,\n );\n }\n\n span.addLink({\n context: previousTraceInfo.spanContext,\n attributes: {\n [SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE]: 'previous_trace',\n },\n });\n }\n\n return {\n spanContext: span.spanContext(),\n startTimestamp: spanToJSON(span).start_timestamp,\n };\n}\n\n/**\n * Stores @param previousTraceInfo in sessionStorage.\n */\nexport function storePreviousTraceInSessionStorage(previousTraceInfo: PreviousTraceInfo): void {\n try {\n WINDOW.sessionStorage.setItem(PREVIOUS_TRACE_KEY, JSON.stringify(previousTraceInfo));\n } catch (e) {\n // Ignore potential errors (e.g. if sessionStorage is not available)\n DEBUG_BUILD && logger.warn('Could not store previous trace in sessionStorage', e);\n }\n}\n\n/**\n * Retrieves the previous trace from sessionStorage if available.\n */\nexport function getPreviousTraceFromSessionStorage(): PreviousTraceInfo | undefined {\n try {\n const previousTraceInfo = WINDOW.sessionStorage?.getItem(PREVIOUS_TRACE_KEY);\n // @ts-expect-error - intentionally risking JSON.parse throwing when previousTraceInfo is null to save bundle size\n return JSON.parse(previousTraceInfo);\n } catch (e) {\n return undefined;\n }\n}\n"],"names":["spanToJSON","DEBUG_BUILD","logger","SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE","WINDOW"],"mappings":";;;;;;;;;;;;;;AAiBA;AACO,MAAM,2BAA4B,GAAE;;AAE3C;AACO,MAAM,kBAAmB,GAAE;;AAElC;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,wBAAwB;AACxC,EAAE,iBAAiB;AACnB,EAAE,IAAI;AACN,EAAqB;AACrB,EAAE,MAAM,QAAS,GAAEA,eAAU,CAAC,IAAI,CAAC;;AAEnC,EAAE,IAAI,CAAC,iBAAiB,EAAE;AAC1B,IAAI,OAAO;AACX,MAAM,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE;AACrC,MAAM,cAAc,EAAE,QAAQ,CAAC,eAAe;AAC9C,KAAK;AACL;;AAEA,EAAE,IAAI,iBAAiB,CAAC,WAAW,CAAC,OAAA,KAAY,QAAQ,CAAC,QAAQ,EAAE;AACnE;AACA;AACA;AACA,IAAI,OAAO,iBAAiB;AAC5B;;AAEA;AACA;AACA;AACA;AACA;AACA,EAAE,IAAI,IAAI,CAAC,GAAG,EAAC,GAAI,IAAA,GAAO,iBAAiB,CAAC,cAAe,IAAG,2BAA2B,EAAE;AAC3F,IAAI,IAAIC,sBAAW,EAAE;AACrB,MAAMC,WAAM,CAAC,IAAI;AACjB,QAAQ,CAAC,sBAAsB,EAAE,iBAAiB,CAAC,WAAW,CAAC,cAAc,EAAE;AAC/E,UAAU,EAAE,EAAE,QAAQ,CAAC,EAAE;AACzB,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE;AAC/B,SAAS,CAAC,CAAA;AACA,OAAA;AACA;;AAEA,IAAA,IAAA,CAAA,OAAA,CAAA;AACA,MAAA,OAAA,EAAA,iBAAA,CAAA,WAAA;AACA,MAAA,UAAA,EAAA;AACA,QAAA,CAAAC,sCAAA,GAAA,gBAAA;AACA,OAAA;AACA,KAAA,CAAA;AACA;;AAEA,EAAA,OAAA;AACA,IAAA,WAAA,EAAA,IAAA,CAAA,WAAA,EAAA;AACA,IAAA,cAAA,EAAAH,eAAA,CAAA,IAAA,CAAA,CAAA,eAAA;AACA,GAAA;AACA;;AAEA;AACA;AACA;AACA,SAAA,kCAAA,CAAA,iBAAA,EAAA;AACA,EAAA,IAAA;AACA,IAAAI,cAAA,CAAA,cAAA,CAAA,OAAA,CAAA,kBAAA,EAAA,IAAA,CAAA,SAAA,CAAA,iBAAA,CAAA,CAAA;AACA,GAAA,CAAA,OAAA,CAAA,EAAA;AACA;AACA,IAAAH,sBAAA,IAAAC,WAAA,CAAA,IAAA,CAAA,kDAAA,EAAA,CAAA,CAAA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAAA,kCAAA,GAAA;AACA,EAAA,IAAA;AACA,IAAA,MAAA,iBAAA,GAAAE,cAAA,CAAA,cAAA,EAAA,OAAA,CAAA,kBAAA,CAAA;AACA;AACA,IAAA,OAAA,IAAA,CAAA,KAAA,CAAA,iBAAA,CAAA;AACA,GAAA,CAAA,OAAA,CAAA,EAAA;AACA,IAAA,OAAA,SAAA;AACA;AACA;;;;;;;;"}
|
package/build/npm/esm/client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Client, getSDKSource, applySdkMetadata,
|
|
1
|
+
import { Client, getSDKSource, applySdkMetadata, addAutoIpAddressToUser, addAutoIpAddressToSession } from '@sentry/core';
|
|
2
2
|
import { eventFromException, eventFromMessage } from './eventbuilder.js';
|
|
3
3
|
import { WINDOW } from './helpers.js';
|
|
4
4
|
|
|
@@ -34,9 +34,6 @@ class BrowserClient extends Client {
|
|
|
34
34
|
WINDOW.document.addEventListener('visibilitychange', () => {
|
|
35
35
|
if (WINDOW.document.visibilityState === 'hidden') {
|
|
36
36
|
this._flushOutcomes();
|
|
37
|
-
if (this._options._experiments?.enableLogs) {
|
|
38
|
-
_INTERNAL_flushLogsBuffer(this);
|
|
39
|
-
}
|
|
40
37
|
}
|
|
41
38
|
});
|
|
42
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sources":["../../../src/client.ts"],"sourcesContent":["import type {\n BrowserClientProfilingOptions,\n BrowserClientReplayOptions,\n ClientOptions,\n Event,\n EventHint,\n Options,\n ParameterizedString,\n Scope,\n SeverityLevel,\n} from '@sentry/core';\nimport {\n Client,\n addAutoIpAddressToSession,\n addAutoIpAddressToUser,\n applySdkMetadata,\n getSDKSource,\n
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../../../src/client.ts"],"sourcesContent":["import type {\n BrowserClientProfilingOptions,\n BrowserClientReplayOptions,\n ClientOptions,\n Event,\n EventHint,\n Options,\n ParameterizedString,\n Scope,\n SeverityLevel,\n} from '@sentry/core';\nimport {\n Client,\n addAutoIpAddressToSession,\n addAutoIpAddressToUser,\n applySdkMetadata,\n getSDKSource,\n} from '@sentry/core';\nimport { eventFromException, eventFromMessage } from './eventbuilder';\nimport { WINDOW } from './helpers';\nimport type { BrowserTransportOptions } from './transports/types';\n\n/**\n * Configuration options for the Sentry Browser SDK.\n * @see @sentry/core Options for more information.\n */\nexport type BrowserOptions = Options<BrowserTransportOptions> &\n BrowserClientReplayOptions &\n BrowserClientProfilingOptions & {\n /**\n * Important: Only set this option if you know what you are doing!\n *\n * By default, the SDK will check if `Sentry.init` is called in a browser extension.\n * In case it is, it will stop initialization and log a warning\n * because browser extensions require a different Sentry initialization process:\n * https://docs.sentry.io/platforms/javascript/best-practices/shared-environments/\n *\n * Setting up the SDK in a browser extension with global error monitoring is not recommended\n * and will likely flood you with errors from other web sites or extensions. This can heavily\n * impact your quota and cause interference with your and other Sentry SDKs in shared environments.\n *\n * If this check wrongfully flags your setup as a browser extension, you can set this\n * option to `true` to skip the check.\n *\n * @default false\n */\n skipBrowserExtensionCheck?: boolean;\n };\n\n/**\n * Configuration options for the Sentry Browser SDK Client class\n * @see BrowserClient for more information.\n */\nexport type BrowserClientOptions = ClientOptions<BrowserTransportOptions> &\n BrowserClientReplayOptions &\n BrowserClientProfilingOptions & {\n /** If configured, this URL will be used as base URL for lazy loading integration. */\n cdnBaseUrl?: string;\n };\n\n/**\n * The Sentry Browser SDK Client.\n *\n * @see BrowserOptions for documentation on configuration options.\n * @see SentryClient for usage documentation.\n */\nexport class BrowserClient extends Client<BrowserClientOptions> {\n /**\n * Creates a new Browser SDK instance.\n *\n * @param options Configuration options for this SDK.\n */\n public constructor(options: BrowserClientOptions) {\n const opts = {\n // We default this to true, as it is the safer scenario\n parentSpanIsAlwaysRootSpan: true,\n ...options,\n };\n const sdkSource = WINDOW.SENTRY_SDK_SOURCE || getSDKSource();\n applySdkMetadata(opts, 'browser', ['browser'], sdkSource);\n\n super(opts);\n\n if (opts.sendClientReports && WINDOW.document) {\n WINDOW.document.addEventListener('visibilitychange', () => {\n if (WINDOW.document.visibilityState === 'hidden') {\n this._flushOutcomes();\n }\n });\n }\n\n if (this._options.sendDefaultPii) {\n this.on('postprocessEvent', addAutoIpAddressToUser);\n this.on('beforeSendSession', addAutoIpAddressToSession);\n }\n }\n\n /**\n * @inheritDoc\n */\n public eventFromException(exception: unknown, hint?: EventHint): PromiseLike<Event> {\n return eventFromException(this._options.stackParser, exception, hint, this._options.attachStacktrace);\n }\n\n /**\n * @inheritDoc\n */\n public eventFromMessage(\n message: ParameterizedString,\n level: SeverityLevel = 'info',\n hint?: EventHint,\n ): PromiseLike<Event> {\n return eventFromMessage(this._options.stackParser, message, level, hint, this._options.attachStacktrace);\n }\n\n /**\n * @inheritDoc\n */\n protected _prepareEvent(\n event: Event,\n hint: EventHint,\n currentScope: Scope,\n isolationScope: Scope,\n ): PromiseLike<Event | null> {\n event.platform = event.platform || 'javascript';\n\n return super._prepareEvent(event, hint, currentScope, isolationScope);\n }\n}\n"],"names":[],"mappings":";;;;AAsBA;AACA;AACA;AACA;;AAmCA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,aAAA,SAAsB,MAAM,CAAuB;AAChE;AACA;AACA;AACA;AACA;AACA,GAAS,WAAW,CAAC,OAAO,EAAwB;AACpD,IAAI,MAAM,OAAO;AACjB;AACA,MAAM,0BAA0B,EAAE,IAAI;AACtC,MAAM,GAAG,OAAO;AAChB,KAAK;AACL,IAAI,MAAM,YAAY,MAAM,CAAC,iBAAkB,IAAG,YAAY,EAAE;AAChE,IAAI,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;;AAE7D,IAAI,KAAK,CAAC,IAAI,CAAC;;AAEf,IAAI,IAAI,IAAI,CAAC,qBAAqB,MAAM,CAAC,QAAQ,EAAE;AACnD,MAAM,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,MAAM;AACjE,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAA,KAAoB,QAAQ,EAAE;AAC1D,UAAU,IAAI,CAAC,cAAc,EAAE;AAC/B;AACA,OAAO,CAAC;AACR;;AAEA,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE;AACtC,MAAM,IAAI,CAAC,EAAE,CAAC,kBAAkB,EAAE,sBAAsB,CAAC;AACzD,MAAM,IAAI,CAAC,EAAE,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;AAC7D;AACA;;AAEA;AACA;AACA;AACA,GAAS,kBAAkB,CAAC,SAAS,EAAW,IAAI,EAAkC;AACtF,IAAI,OAAO,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;AACzG;;AAEA;AACA;AACA;AACA,GAAS,gBAAgB;AACzB,IAAI,OAAO;AACX,IAAI,KAAK,GAAkB,MAAM;AACjC,IAAI,IAAI;AACR,IAAwB;AACxB,IAAI,OAAO,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;AAC5G;;AAEA;AACA;AACA;AACA,GAAY,aAAa;AACzB,IAAI,KAAK;AACT,IAAI,IAAI;AACR,IAAI,YAAY;AAChB,IAAI,cAAc;AAClB,IAA+B;AAC/B,IAAI,KAAK,CAAC,QAAS,GAAE,KAAK,CAAC,QAAA,IAAY,YAAY;;AAEnD,IAAI,OAAO,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,CAAC;AACzE;AACA;;;;"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { getClient } from '@sentry/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A function to diagnose why the SDK might not be successfully sending data.
|
|
5
|
+
*
|
|
6
|
+
* Possible return values wrapped in a Promise:
|
|
7
|
+
* - `"no-client-active"` - There was no active client when the function was called. This possibly means that the SDK was not initialized yet.
|
|
8
|
+
* - `"sentry-unreachable"` - The Sentry SaaS servers were not reachable. This likely means that there is an ad blocker active on the page or that there are other connection issues.
|
|
9
|
+
*
|
|
10
|
+
* If the function doesn't detect an issue it resolves to `undefined`.
|
|
11
|
+
*/
|
|
12
|
+
async function diagnoseSdkConnectivity()
|
|
13
|
+
|
|
14
|
+
{
|
|
15
|
+
const client = getClient();
|
|
16
|
+
|
|
17
|
+
if (!client) {
|
|
18
|
+
return 'no-client-active';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!client.getDsn()) {
|
|
22
|
+
return 'no-dsn-configured';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
// If fetch throws, there is likely an ad blocker active or there are other connective issues.
|
|
27
|
+
await fetch(
|
|
28
|
+
// We want this to be as close as possible to an actual ingest URL so that ad blockers will actually block the request
|
|
29
|
+
// We are using the "sentry-sdks" org with id 447951 not to pollute any actual organizations.
|
|
30
|
+
'https://o447951.ingest.sentry.io/api/1337/envelope/?sentry_version=7&sentry_key=1337&sentry_client=sentry.javascript.browser%2F1.33.7',
|
|
31
|
+
{
|
|
32
|
+
body: '{}',
|
|
33
|
+
method: 'POST',
|
|
34
|
+
mode: 'cors',
|
|
35
|
+
credentials: 'omit',
|
|
36
|
+
},
|
|
37
|
+
);
|
|
38
|
+
} catch {
|
|
39
|
+
return 'sentry-unreachable';
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { diagnoseSdkConnectivity };
|
|
44
|
+
//# sourceMappingURL=diagnose-sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnose-sdk.js","sources":["../../../src/diagnose-sdk.ts"],"sourcesContent":["import { getClient } from '@sentry/core';\n\n/**\n * A function to diagnose why the SDK might not be successfully sending data.\n *\n * Possible return values wrapped in a Promise:\n * - `\"no-client-active\"` - There was no active client when the function was called. This possibly means that the SDK was not initialized yet.\n * - `\"sentry-unreachable\"` - The Sentry SaaS servers were not reachable. This likely means that there is an ad blocker active on the page or that there are other connection issues.\n *\n * If the function doesn't detect an issue it resolves to `undefined`.\n */\nexport async function diagnoseSdkConnectivity(): Promise<\n 'no-client-active' | 'sentry-unreachable' | 'no-dsn-configured' | void\n> {\n const client = getClient();\n\n if (!client) {\n return 'no-client-active';\n }\n\n if (!client.getDsn()) {\n return 'no-dsn-configured';\n }\n\n try {\n // If fetch throws, there is likely an ad blocker active or there are other connective issues.\n await fetch(\n // We want this to be as close as possible to an actual ingest URL so that ad blockers will actually block the request\n // We are using the \"sentry-sdks\" org with id 447951 not to pollute any actual organizations.\n 'https://o447951.ingest.sentry.io/api/1337/envelope/?sentry_version=7&sentry_key=1337&sentry_client=sentry.javascript.browser%2F1.33.7',\n {\n body: '{}',\n method: 'POST',\n mode: 'cors',\n credentials: 'omit',\n },\n );\n } catch {\n return 'sentry-unreachable';\n }\n}\n"],"names":[],"mappings":";;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAe,uBAAuB;;AAE7C,CAAE;AACF,EAAE,MAAM,MAAA,GAAS,SAAS,EAAE;;AAE5B,EAAE,IAAI,CAAC,MAAM,EAAE;AACf,IAAI,OAAO,kBAAkB;AAC7B;;AAEA,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE;AACxB,IAAI,OAAO,mBAAmB;AAC9B;;AAEA,EAAE,IAAI;AACN;AACA,IAAI,MAAM,KAAK;AACf;AACA;AACA,MAAM,uIAAuI;AAC7I,MAAM;AACN,QAAQ,IAAI,EAAE,IAAI;AAClB,QAAQ,MAAM,EAAE,MAAM;AACtB,QAAQ,IAAI,EAAE,MAAM;AACpB,QAAQ,WAAW,EAAE,MAAM;AAC3B,OAAO;AACP,KAAK;AACL,IAAI,MAAM;AACV,IAAI,OAAO,oBAAoB;AAC/B;AACA;;;;"}
|
package/build/npm/esm/index.js
CHANGED
|
@@ -12,6 +12,8 @@ export { httpContextIntegration } from './integrations/httpcontext.js';
|
|
|
12
12
|
export { linkedErrorsIntegration } from './integrations/linkederrors.js';
|
|
13
13
|
export { browserApiErrorsIntegration } from './integrations/browserapierrors.js';
|
|
14
14
|
export { lazyLoadIntegration } from './utils/lazyLoadIntegration.js';
|
|
15
|
+
import * as log from './log.js';
|
|
16
|
+
export { log as logger };
|
|
15
17
|
export { reportingObserverIntegration } from './integrations/reportingobserver.js';
|
|
16
18
|
export { httpClientIntegration } from './integrations/httpclient.js';
|
|
17
19
|
export { contextLinesIntegration } from './integrations/contextlines.js';
|
|
@@ -32,4 +34,5 @@ export { buildLaunchDarklyFlagUsedHandler, launchDarklyIntegration } from './int
|
|
|
32
34
|
export { OpenFeatureIntegrationHook, openFeatureIntegration } from './integrations/featureFlags/openfeature/integration.js';
|
|
33
35
|
export { unleashIntegration } from './integrations/featureFlags/unleash/integration.js';
|
|
34
36
|
export { statsigIntegration } from './integrations/featureFlags/statsig/integration.js';
|
|
37
|
+
export { diagnoseSdkConnectivity } from './diagnose-sdk.js';
|
|
35
38
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { getClient, _INTERNAL_captureLog, _INTERNAL_flushLogsBuffer } from '@sentry/core';
|
|
2
|
+
export { fmt } from '@sentry/core';
|
|
3
|
+
import { WINDOW } from './helpers.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* TODO: Make this configurable
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_FLUSH_INTERVAL = 5000;
|
|
9
|
+
|
|
10
|
+
let timeout;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* This is a global timeout that is used to flush the logs buffer.
|
|
14
|
+
* It is used to ensure that logs are flushed even if the client is not flushed.
|
|
15
|
+
*/
|
|
16
|
+
function startFlushTimeout(client) {
|
|
17
|
+
if (timeout) {
|
|
18
|
+
clearTimeout(timeout);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
timeout = setTimeout(() => {
|
|
22
|
+
_INTERNAL_flushLogsBuffer(client);
|
|
23
|
+
}, DEFAULT_FLUSH_INTERVAL);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let isClientListenerAdded = false;
|
|
27
|
+
/**
|
|
28
|
+
* This is a function that is used to add a flush listener to the client.
|
|
29
|
+
* It is used to ensure that the logger buffer is flushed when the client is flushed.
|
|
30
|
+
*/
|
|
31
|
+
function addFlushingListeners(client) {
|
|
32
|
+
if (isClientListenerAdded || !client.getOptions()._experiments?.enableLogs) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
isClientListenerAdded = true;
|
|
37
|
+
|
|
38
|
+
if (WINDOW.document) {
|
|
39
|
+
WINDOW.document.addEventListener('visibilitychange', () => {
|
|
40
|
+
if (WINDOW.document.visibilityState === 'hidden') {
|
|
41
|
+
_INTERNAL_flushLogsBuffer(client);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
client.on('flush', () => {
|
|
47
|
+
_INTERNAL_flushLogsBuffer(client);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Capture a log with the given level.
|
|
53
|
+
*
|
|
54
|
+
* @param level - The level of the log.
|
|
55
|
+
* @param message - The message to log.
|
|
56
|
+
* @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100.
|
|
57
|
+
* @param severityNumber - The severity number of the log.
|
|
58
|
+
*/
|
|
59
|
+
function captureLog(
|
|
60
|
+
level,
|
|
61
|
+
message,
|
|
62
|
+
attributes,
|
|
63
|
+
severityNumber,
|
|
64
|
+
) {
|
|
65
|
+
const client = getClient();
|
|
66
|
+
if (client) {
|
|
67
|
+
addFlushingListeners(client);
|
|
68
|
+
|
|
69
|
+
startFlushTimeout(client);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
_INTERNAL_captureLog({ level, message, attributes, severityNumber }, client, undefined);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @summary Capture a log with the `trace` level. Requires `_experiments.enableLogs` to be enabled.
|
|
77
|
+
*
|
|
78
|
+
* @param message - The message to log.
|
|
79
|
+
* @param attributes - Arbitrary structured data that stores information about the log - e.g., { userId: 100, route: '/dashboard' }.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
*
|
|
83
|
+
* ```
|
|
84
|
+
* Sentry.logger.trace('User clicked submit button', {
|
|
85
|
+
* buttonId: 'submit-form',
|
|
86
|
+
* formId: 'user-profile',
|
|
87
|
+
* timestamp: Date.now()
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @example With template strings
|
|
92
|
+
*
|
|
93
|
+
* ```
|
|
94
|
+
* Sentry.logger.trace(Sentry.logger.fmt`User ${user} navigated to ${page}`, {
|
|
95
|
+
* userId: '123',
|
|
96
|
+
* sessionId: 'abc-xyz'
|
|
97
|
+
* });
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
function trace(message, attributes) {
|
|
101
|
+
captureLog('trace', message, attributes);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @summary Capture a log with the `debug` level. Requires `_experiments.enableLogs` to be enabled.
|
|
106
|
+
*
|
|
107
|
+
* @param message - The message to log.
|
|
108
|
+
* @param attributes - Arbitrary structured data that stores information about the log - e.g., { component: 'Header', state: 'loading' }.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
*
|
|
112
|
+
* ```
|
|
113
|
+
* Sentry.logger.debug('Component mounted', {
|
|
114
|
+
* component: 'UserProfile',
|
|
115
|
+
* props: { userId: 123 },
|
|
116
|
+
* renderTime: 150
|
|
117
|
+
* });
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @example With template strings
|
|
121
|
+
*
|
|
122
|
+
* ```
|
|
123
|
+
* Sentry.logger.debug(Sentry.logger.fmt`API request to ${endpoint} failed`, {
|
|
124
|
+
* statusCode: 404,
|
|
125
|
+
* requestId: 'req-123',
|
|
126
|
+
* duration: 250
|
|
127
|
+
* });
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
function debug(message, attributes) {
|
|
131
|
+
captureLog('debug', message, attributes);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @summary Capture a log with the `info` level. Requires `_experiments.enableLogs` to be enabled.
|
|
136
|
+
*
|
|
137
|
+
* @param message - The message to log.
|
|
138
|
+
* @param attributes - Arbitrary structured data that stores information about the log - e.g., { feature: 'checkout', status: 'completed' }.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
*
|
|
142
|
+
* ```
|
|
143
|
+
* Sentry.logger.info('User completed checkout', {
|
|
144
|
+
* orderId: 'order-123',
|
|
145
|
+
* amount: 99.99,
|
|
146
|
+
* paymentMethod: 'credit_card'
|
|
147
|
+
* });
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* @example With template strings
|
|
151
|
+
*
|
|
152
|
+
* ```
|
|
153
|
+
* Sentry.logger.info(Sentry.logger.fmt`User ${user} updated profile picture`, {
|
|
154
|
+
* userId: 'user-123',
|
|
155
|
+
* imageSize: '2.5MB',
|
|
156
|
+
* timestamp: Date.now()
|
|
157
|
+
* });
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
function info(message, attributes) {
|
|
161
|
+
captureLog('info', message, attributes);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* @summary Capture a log with the `warn` level. Requires `_experiments.enableLogs` to be enabled.
|
|
166
|
+
*
|
|
167
|
+
* @param message - The message to log.
|
|
168
|
+
* @param attributes - Arbitrary structured data that stores information about the log - e.g., { browser: 'Chrome', version: '91.0' }.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
*
|
|
172
|
+
* ```
|
|
173
|
+
* Sentry.logger.warn('Browser compatibility issue detected', {
|
|
174
|
+
* browser: 'Safari',
|
|
175
|
+
* version: '14.0',
|
|
176
|
+
* feature: 'WebRTC',
|
|
177
|
+
* fallback: 'enabled'
|
|
178
|
+
* });
|
|
179
|
+
* ```
|
|
180
|
+
*
|
|
181
|
+
* @example With template strings
|
|
182
|
+
*
|
|
183
|
+
* ```
|
|
184
|
+
* Sentry.logger.warn(Sentry.logger.fmt`API endpoint ${endpoint} is deprecated`, {
|
|
185
|
+
* recommendedEndpoint: '/api/v2/users',
|
|
186
|
+
* sunsetDate: '2024-12-31',
|
|
187
|
+
* clientVersion: '1.2.3'
|
|
188
|
+
* });
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
function warn(message, attributes) {
|
|
192
|
+
captureLog('warn', message, attributes);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @summary Capture a log with the `error` level. Requires `_experiments.enableLogs` to be enabled.
|
|
197
|
+
*
|
|
198
|
+
* @param message - The message to log.
|
|
199
|
+
* @param attributes - Arbitrary structured data that stores information about the log - e.g., { error: 'NetworkError', url: '/api/data' }.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
*
|
|
203
|
+
* ```
|
|
204
|
+
* Sentry.logger.error('Failed to load user data', {
|
|
205
|
+
* error: 'NetworkError',
|
|
206
|
+
* url: '/api/users/123',
|
|
207
|
+
* statusCode: 500,
|
|
208
|
+
* retryCount: 3
|
|
209
|
+
* });
|
|
210
|
+
* ```
|
|
211
|
+
*
|
|
212
|
+
* @example With template strings
|
|
213
|
+
*
|
|
214
|
+
* ```
|
|
215
|
+
* Sentry.logger.error(Sentry.logger.fmt`Payment processing failed for order ${orderId}`, {
|
|
216
|
+
* error: 'InsufficientFunds',
|
|
217
|
+
* amount: 100.00,
|
|
218
|
+
* currency: 'USD',
|
|
219
|
+
* userId: 'user-456'
|
|
220
|
+
* });
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
function error(message, attributes) {
|
|
224
|
+
captureLog('error', message, attributes);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* @summary Capture a log with the `fatal` level. Requires `_experiments.enableLogs` to be enabled.
|
|
229
|
+
*
|
|
230
|
+
* @param message - The message to log.
|
|
231
|
+
* @param attributes - Arbitrary structured data that stores information about the log - e.g., { appState: 'corrupted', sessionId: 'abc-123' }.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
*
|
|
235
|
+
* ```
|
|
236
|
+
* Sentry.logger.fatal('Application state corrupted', {
|
|
237
|
+
* lastKnownState: 'authenticated',
|
|
238
|
+
* sessionId: 'session-123',
|
|
239
|
+
* timestamp: Date.now(),
|
|
240
|
+
* recoveryAttempted: true
|
|
241
|
+
* });
|
|
242
|
+
* ```
|
|
243
|
+
*
|
|
244
|
+
* @example With template strings
|
|
245
|
+
*
|
|
246
|
+
* ```
|
|
247
|
+
* Sentry.logger.fatal(Sentry.logger.fmt`Critical system failure in ${service}`, {
|
|
248
|
+
* service: 'payment-processor',
|
|
249
|
+
* errorCode: 'CRITICAL_FAILURE',
|
|
250
|
+
* affectedUsers: 150,
|
|
251
|
+
* timestamp: Date.now()
|
|
252
|
+
* });
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
function fatal(message, attributes) {
|
|
256
|
+
captureLog('fatal', message, attributes);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export { debug, error, fatal, info, trace, warn };
|
|
260
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sources":["../../../src/log.ts"],"sourcesContent":["import type { LogSeverityLevel, Log, Client, ParameterizedString } from '@sentry/core';\nimport { getClient, _INTERNAL_captureLog, _INTERNAL_flushLogsBuffer } from '@sentry/core';\n\nimport { WINDOW } from './helpers';\n\n/**\n * TODO: Make this configurable\n */\nconst DEFAULT_FLUSH_INTERVAL = 5000;\n\nlet timeout: ReturnType<typeof setTimeout> | undefined;\n\n/**\n * This is a global timeout that is used to flush the logs buffer.\n * It is used to ensure that logs are flushed even if the client is not flushed.\n */\nfunction startFlushTimeout(client: Client): void {\n if (timeout) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(() => {\n _INTERNAL_flushLogsBuffer(client);\n }, DEFAULT_FLUSH_INTERVAL);\n}\n\nlet isClientListenerAdded = false;\n/**\n * This is a function that is used to add a flush listener to the client.\n * It is used to ensure that the logger buffer is flushed when the client is flushed.\n */\nfunction addFlushingListeners(client: Client): void {\n if (isClientListenerAdded || !client.getOptions()._experiments?.enableLogs) {\n return;\n }\n\n isClientListenerAdded = true;\n\n if (WINDOW.document) {\n WINDOW.document.addEventListener('visibilitychange', () => {\n if (WINDOW.document.visibilityState === 'hidden') {\n _INTERNAL_flushLogsBuffer(client);\n }\n });\n }\n\n client.on('flush', () => {\n _INTERNAL_flushLogsBuffer(client);\n });\n}\n\n/**\n * Capture a log with the given level.\n *\n * @param level - The level of the log.\n * @param message - The message to log.\n * @param attributes - Arbitrary structured data that stores information about the log - e.g., userId: 100.\n * @param severityNumber - The severity number of the log.\n */\nfunction captureLog(\n level: LogSeverityLevel,\n message: ParameterizedString,\n attributes?: Log['attributes'],\n severityNumber?: Log['severityNumber'],\n): void {\n const client = getClient();\n if (client) {\n addFlushingListeners(client);\n\n startFlushTimeout(client);\n }\n\n _INTERNAL_captureLog({ level, message, attributes, severityNumber }, client, undefined);\n}\n\n/**\n * @summary Capture a log with the `trace` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * @param message - The message to log.\n * @param attributes - Arbitrary structured data that stores information about the log - e.g., { userId: 100, route: '/dashboard' }.\n *\n * @example\n *\n * ```\n * Sentry.logger.trace('User clicked submit button', {\n * buttonId: 'submit-form',\n * formId: 'user-profile',\n * timestamp: Date.now()\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.trace(Sentry.logger.fmt`User ${user} navigated to ${page}`, {\n * userId: '123',\n * sessionId: 'abc-xyz'\n * });\n * ```\n */\nexport function trace(message: ParameterizedString, attributes?: Log['attributes']): void {\n captureLog('trace', message, attributes);\n}\n\n/**\n * @summary Capture a log with the `debug` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * @param message - The message to log.\n * @param attributes - Arbitrary structured data that stores information about the log - e.g., { component: 'Header', state: 'loading' }.\n *\n * @example\n *\n * ```\n * Sentry.logger.debug('Component mounted', {\n * component: 'UserProfile',\n * props: { userId: 123 },\n * renderTime: 150\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.debug(Sentry.logger.fmt`API request to ${endpoint} failed`, {\n * statusCode: 404,\n * requestId: 'req-123',\n * duration: 250\n * });\n * ```\n */\nexport function debug(message: ParameterizedString, attributes?: Log['attributes']): void {\n captureLog('debug', message, attributes);\n}\n\n/**\n * @summary Capture a log with the `info` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * @param message - The message to log.\n * @param attributes - Arbitrary structured data that stores information about the log - e.g., { feature: 'checkout', status: 'completed' }.\n *\n * @example\n *\n * ```\n * Sentry.logger.info('User completed checkout', {\n * orderId: 'order-123',\n * amount: 99.99,\n * paymentMethod: 'credit_card'\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.info(Sentry.logger.fmt`User ${user} updated profile picture`, {\n * userId: 'user-123',\n * imageSize: '2.5MB',\n * timestamp: Date.now()\n * });\n * ```\n */\nexport function info(message: ParameterizedString, attributes?: Log['attributes']): void {\n captureLog('info', message, attributes);\n}\n\n/**\n * @summary Capture a log with the `warn` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * @param message - The message to log.\n * @param attributes - Arbitrary structured data that stores information about the log - e.g., { browser: 'Chrome', version: '91.0' }.\n *\n * @example\n *\n * ```\n * Sentry.logger.warn('Browser compatibility issue detected', {\n * browser: 'Safari',\n * version: '14.0',\n * feature: 'WebRTC',\n * fallback: 'enabled'\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.warn(Sentry.logger.fmt`API endpoint ${endpoint} is deprecated`, {\n * recommendedEndpoint: '/api/v2/users',\n * sunsetDate: '2024-12-31',\n * clientVersion: '1.2.3'\n * });\n * ```\n */\nexport function warn(message: ParameterizedString, attributes?: Log['attributes']): void {\n captureLog('warn', message, attributes);\n}\n\n/**\n * @summary Capture a log with the `error` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * @param message - The message to log.\n * @param attributes - Arbitrary structured data that stores information about the log - e.g., { error: 'NetworkError', url: '/api/data' }.\n *\n * @example\n *\n * ```\n * Sentry.logger.error('Failed to load user data', {\n * error: 'NetworkError',\n * url: '/api/users/123',\n * statusCode: 500,\n * retryCount: 3\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.error(Sentry.logger.fmt`Payment processing failed for order ${orderId}`, {\n * error: 'InsufficientFunds',\n * amount: 100.00,\n * currency: 'USD',\n * userId: 'user-456'\n * });\n * ```\n */\nexport function error(message: ParameterizedString, attributes?: Log['attributes']): void {\n captureLog('error', message, attributes);\n}\n\n/**\n * @summary Capture a log with the `fatal` level. Requires `_experiments.enableLogs` to be enabled.\n *\n * @param message - The message to log.\n * @param attributes - Arbitrary structured data that stores information about the log - e.g., { appState: 'corrupted', sessionId: 'abc-123' }.\n *\n * @example\n *\n * ```\n * Sentry.logger.fatal('Application state corrupted', {\n * lastKnownState: 'authenticated',\n * sessionId: 'session-123',\n * timestamp: Date.now(),\n * recoveryAttempted: true\n * });\n * ```\n *\n * @example With template strings\n *\n * ```\n * Sentry.logger.fatal(Sentry.logger.fmt`Critical system failure in ${service}`, {\n * service: 'payment-processor',\n * errorCode: 'CRITICAL_FAILURE',\n * affectedUsers: 150,\n * timestamp: Date.now()\n * });\n * ```\n */\nexport function fatal(message: ParameterizedString, attributes?: Log['attributes']): void {\n captureLog('fatal', message, attributes);\n}\n\nexport { fmt } from '@sentry/core';\n"],"names":[],"mappings":";;;;AAKA;AACA;AACA;AACA,MAAM,sBAAA,GAAyB,IAAI;;AAEnC,IAAI,OAAO;;AAEX;AACA;AACA;AACA;AACA,SAAS,iBAAiB,CAAC,MAAM,EAAgB;AACjD,EAAE,IAAI,OAAO,EAAE;AACf,IAAI,YAAY,CAAC,OAAO,CAAC;AACzB;;AAEA,EAAE,UAAU,UAAU,CAAC,MAAM;AAC7B,IAAI,yBAAyB,CAAC,MAAM,CAAC;AACrC,GAAG,EAAE,sBAAsB,CAAC;AAC5B;;AAEA,IAAI,qBAAA,GAAwB,KAAK;AACjC;AACA;AACA;AACA;AACA,SAAS,oBAAoB,CAAC,MAAM,EAAgB;AACpD,EAAE,IAAI,qBAAsB,IAAG,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE;AAC9E,IAAI;AACJ;;AAEA,EAAE,qBAAA,GAAwB,IAAI;;AAE9B,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE;AACvB,IAAI,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,MAAM;AAC/D,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,eAAA,KAAoB,QAAQ,EAAE;AACxD,QAAQ,yBAAyB,CAAC,MAAM,CAAC;AACzC;AACA,KAAK,CAAC;AACN;;AAEA,EAAE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM;AAC3B,IAAI,yBAAyB,CAAC,MAAM,CAAC;AACrC,GAAG,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,UAAU;AACnB,EAAE,KAAK;AACP,EAAE,OAAO;AACT,EAAE,UAAU;AACZ,EAAE,cAAc;AAChB,EAAQ;AACR,EAAE,MAAM,MAAA,GAAS,SAAS,EAAE;AAC5B,EAAE,IAAI,MAAM,EAAE;AACd,IAAI,oBAAoB,CAAC,MAAM,CAAC;;AAEhC,IAAI,iBAAiB,CAAC,MAAM,CAAC;AAC7B;;AAEA,EAAE,oBAAoB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,SAAS,CAAC;AACzF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,KAAK,CAAC,OAAO,EAAuB,UAAU,EAA4B;AAC1F,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC;AAC1C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,KAAK,CAAC,OAAO,EAAuB,UAAU,EAA4B;AAC1F,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC;AAC1C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAuB,UAAU,EAA4B;AACzF,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAuB,UAAU,EAA4B;AACzF,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,CAAC;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,KAAK,CAAC,OAAO,EAAuB,UAAU,EAA4B;AAC1F,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC;AAC1C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,KAAK,CAAC,OAAO,EAAuB,UAAU,EAA4B;AAC1F,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC;AAC1C;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"9.
|
|
1
|
+
{"type":"module","version":"9.10.0","sideEffects":false}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { startTrackingWebVitals, startTrackingINP, startTrackingLongAnimationFrames, startTrackingLongTasks, startTrackingInteractions, addHistoryInstrumentationHandler, registerInpInteractionListener, addPerformanceEntries } from '@sentry-internal/browser-utils';
|
|
2
|
-
import { TRACING_DEFAULTS, registerSpanErrorInstrumentation, GLOBAL_OBJ, getLocationHref, getClient, getIsolationScope, generateTraceId, getCurrentScope, propagationContextFromHeaders, browserPerformanceTimeOrigin, spanToJSON, logger, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startIdleSpan, getDynamicSamplingContextFromSpan, spanIsSampled, addNonEnumerableProperty, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON } from '@sentry/core';
|
|
2
|
+
import { TRACING_DEFAULTS, registerSpanErrorInstrumentation, GLOBAL_OBJ, getLocationHref, getClient, getIsolationScope, generateTraceId, getCurrentScope, propagationContextFromHeaders, getRootSpan, browserPerformanceTimeOrigin, spanToJSON, logger, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startIdleSpan, getDynamicSamplingContextFromSpan, spanIsSampled, addNonEnumerableProperty, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON } from '@sentry/core';
|
|
3
3
|
import { DEBUG_BUILD } from '../debug-build.js';
|
|
4
4
|
import { WINDOW } from '../helpers.js';
|
|
5
5
|
import { registerBackgroundTabDetection } from './backgroundtab.js';
|
|
6
6
|
import { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './request.js';
|
|
7
|
+
import { addPreviousTraceSpanLink, getPreviousTraceFromSessionStorage, storePreviousTraceInSessionStorage } from './previousTrace.js';
|
|
7
8
|
|
|
8
9
|
/* eslint-disable max-lines */
|
|
9
10
|
|
|
@@ -17,6 +18,7 @@ const DEFAULT_BROWSER_TRACING_OPTIONS = {
|
|
|
17
18
|
enableLongTask: true,
|
|
18
19
|
enableLongAnimationFrame: true,
|
|
19
20
|
enableInp: true,
|
|
21
|
+
linkPreviousTrace: 'in-memory',
|
|
20
22
|
_experiments: {},
|
|
21
23
|
...defaultRequestInstrumentationOptions,
|
|
22
24
|
};
|
|
@@ -56,6 +58,7 @@ const browserTracingIntegration = ((_options = {}) => {
|
|
|
56
58
|
enableHTTPTimings,
|
|
57
59
|
instrumentPageLoad,
|
|
58
60
|
instrumentNavigation,
|
|
61
|
+
linkPreviousTrace,
|
|
59
62
|
} = {
|
|
60
63
|
...DEFAULT_BROWSER_TRACING_OPTIONS,
|
|
61
64
|
..._options,
|
|
@@ -198,6 +201,23 @@ const browserTracingIntegration = ((_options = {}) => {
|
|
|
198
201
|
});
|
|
199
202
|
});
|
|
200
203
|
|
|
204
|
+
if (linkPreviousTrace !== 'off') {
|
|
205
|
+
let inMemoryPreviousTraceInfo = undefined;
|
|
206
|
+
|
|
207
|
+
client.on('spanStart', span => {
|
|
208
|
+
if (getRootSpan(span) !== span) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (linkPreviousTrace === 'session-storage') {
|
|
213
|
+
const updatedPreviousTraceInfo = addPreviousTraceSpanLink(getPreviousTraceFromSessionStorage(), span);
|
|
214
|
+
storePreviousTraceInSessionStorage(updatedPreviousTraceInfo);
|
|
215
|
+
} else {
|
|
216
|
+
inMemoryPreviousTraceInfo = addPreviousTraceSpanLink(inMemoryPreviousTraceInfo, span);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
201
221
|
if (WINDOW.location) {
|
|
202
222
|
if (instrumentPageLoad) {
|
|
203
223
|
const origin = browserPerformanceTimeOrigin();
|