From 4583f80fc30442ad393e94e1c1786117f9bccf51 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 20 Sep 2023 14:14:29 +0200 Subject: [PATCH 01/15] fix(core): Ensure global event processors are always applied to event (#9064) Even if no scope is passed. I guess this is kind of behavior changing, but I'd argue it is just fixing an unexpected behaviour that's not actually intuitive/logical - that global event processors are only applied if a scope is provided. --- packages/core/src/utils/prepareEvent.ts | 5 ++++- packages/node/test/manual/release-health/runner.js | 2 +- .../session-aggregates/aggregates-disable-single-session.js | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/core/src/utils/prepareEvent.ts b/packages/core/src/utils/prepareEvent.ts index 13a164dbaf76..ae70b8639991 100644 --- a/packages/core/src/utils/prepareEvent.ts +++ b/packages/core/src/utils/prepareEvent.ts @@ -2,7 +2,7 @@ import type { Client, ClientOptions, Event, EventHint, StackFrame, StackParser } import { dateTimestampInSeconds, GLOBAL_OBJ, normalize, resolvedSyncPromise, truncate, uuid4 } from '@sentry/utils'; import { DEFAULT_ENVIRONMENT } from '../constants'; -import { notifyEventProcessors } from '../eventProcessors'; +import { getGlobalEventProcessors, notifyEventProcessors } from '../eventProcessors'; import { Scope } from '../scope'; /** @@ -74,6 +74,9 @@ export function prepareEvent( // In case we have a hub we reassign it. result = finalScope.applyToEvent(prepared, hint); + } else { + // Apply global event processors even if there is no scope + result = notifyEventProcessors(getGlobalEventProcessors(), prepared, hint); } return result diff --git a/packages/node/test/manual/release-health/runner.js b/packages/node/test/manual/release-health/runner.js index c8ecab182859..713ae5d10c3f 100644 --- a/packages/node/test/manual/release-health/runner.js +++ b/packages/node/test/manual/release-health/runner.js @@ -15,7 +15,7 @@ for (const dir of scenariosDirs) { const processes = scenarios.map(([filename, filepath]) => { return new Promise(resolve => { - const scenarioProcess = spawn('node', [filepath]); + const scenarioProcess = spawn('node', [filepath], { timeout: 10000 }); const output = []; const errors = []; diff --git a/packages/node/test/manual/release-health/session-aggregates/aggregates-disable-single-session.js b/packages/node/test/manual/release-health/session-aggregates/aggregates-disable-single-session.js index dc6aa4485dcb..a9a16809ad41 100644 --- a/packages/node/test/manual/release-health/session-aggregates/aggregates-disable-single-session.js +++ b/packages/node/test/manual/release-health/session-aggregates/aggregates-disable-single-session.js @@ -12,6 +12,9 @@ function cleanUpAndExitSuccessfully() { } function assertSessionAggregates(session, expected) { + if (!session.aggregates) { + return; + } // For loop is added here just in the rare occasion that the session count do not land in the same aggregate // bucket session.aggregates.forEach(function (_, idx) { From 42ddf41df71bc08c7dd34f6794105591d48d9b60 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 20 Sep 2023 15:04:34 +0200 Subject: [PATCH 02/15] fix(core): Run client eventProcessors before global ones (#9032) I noticed that while from an API POV the current behavior makes kind-of sense IMHO: 1. Run global event processors 2. Run scope event processors 3. Run client event processors It is potentially breaking, as if we rewrite integrations to use the new client processors, their processing will run after any user global event processors, leading to potentially unexpected outcomes. So this PR changes this to instead run them in this order: 1. Run client event processors 2. Run global event processors 3. Run scope event processors Which should be more stable for now. In v8, we should update this to run a more sensible order: 1. Global 2. Client 3. Scope --- packages/core/src/scope.ts | 13 ++++++-- packages/core/src/utils/prepareEvent.ts | 40 ++++++++++++------------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/packages/core/src/scope.ts b/packages/core/src/scope.ts index ba4ccac23adb..48e1701ab3cb 100644 --- a/packages/core/src/scope.ts +++ b/packages/core/src/scope.ts @@ -467,7 +467,11 @@ export class Scope implements ScopeInterface { * @param hint Object containing additional information about the original exception, for use by the event processors. * @hidden */ - public applyToEvent(event: Event, hint: EventHint = {}): PromiseLike { + public applyToEvent( + event: Event, + hint: EventHint = {}, + additionalEventProcessors?: EventProcessor[], + ): PromiseLike { if (this._extra && Object.keys(this._extra).length) { event.extra = { ...this._extra, ...event.extra }; } @@ -517,7 +521,12 @@ export class Scope implements ScopeInterface { propagationContext: this._propagationContext, }; - return notifyEventProcessors([...getGlobalEventProcessors(), ...this._eventProcessors], event, hint); + // TODO (v8): Update this order to be: Global > Client > Scope + return notifyEventProcessors( + [...(additionalEventProcessors || []), ...getGlobalEventProcessors(), ...this._eventProcessors], + event, + hint, + ); } /** diff --git a/packages/core/src/utils/prepareEvent.ts b/packages/core/src/utils/prepareEvent.ts index ae70b8639991..6e473a9b1cb1 100644 --- a/packages/core/src/utils/prepareEvent.ts +++ b/packages/core/src/utils/prepareEvent.ts @@ -55,6 +55,8 @@ export function prepareEvent( // We prepare the result here with a resolved Event. let result = resolvedSyncPromise(prepared); + const clientEventProcessors = client && client.getEventProcessors ? client.getEventProcessors() : []; + // This should be the last thing called, since we want that // {@link Hub.addEventProcessor} gets the finished prepared event. // @@ -73,31 +75,27 @@ export function prepareEvent( } // In case we have a hub we reassign it. - result = finalScope.applyToEvent(prepared, hint); + result = finalScope.applyToEvent(prepared, hint, clientEventProcessors); } else { - // Apply global event processors even if there is no scope - result = notifyEventProcessors(getGlobalEventProcessors(), prepared, hint); + // Apply client & global event processors even if there is no scope + // TODO (v8): Update the order to be Global > Client + result = notifyEventProcessors([...clientEventProcessors, ...getGlobalEventProcessors()], prepared, hint); } - return result - .then(evt => { - // Process client-scoped event processors - return client && client.getEventProcessors ? notifyEventProcessors(client.getEventProcessors(), evt, hint) : evt; - }) - .then(evt => { - if (evt) { - // We apply the debug_meta field only after all event processors have ran, so that if any event processors modified - // file names (e.g.the RewriteFrames integration) the filename -> debug ID relationship isn't destroyed. - // This should not cause any PII issues, since we're only moving data that is already on the event and not adding - // any new data - applyDebugMeta(evt); - } + return result.then(evt => { + if (evt) { + // We apply the debug_meta field only after all event processors have ran, so that if any event processors modified + // file names (e.g.the RewriteFrames integration) the filename -> debug ID relationship isn't destroyed. + // This should not cause any PII issues, since we're only moving data that is already on the event and not adding + // any new data + applyDebugMeta(evt); + } - if (typeof normalizeDepth === 'number' && normalizeDepth > 0) { - return normalizeEvent(evt, normalizeDepth, normalizeMaxBreadth); - } - return evt; - }); + if (typeof normalizeDepth === 'number' && normalizeDepth > 0) { + return normalizeEvent(evt, normalizeDepth, normalizeMaxBreadth); + } + return evt; + }); } /** From 3ae909b2c9e0288b9d83769ce9c96d7f8ed6185c Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 20 Sep 2023 16:32:10 +0200 Subject: [PATCH 03/15] ref(node-experimental): Use sdk-trace-base instead of sdk-trace-node (#9070) Also update all OTEL dependencies to latest to align these properly. The sdk-trace-node package actually just wraps sdk-trace-base, adds some default exports (that we do not need) + sets the async local storage context manager by default (which we overwrite anyhow). So we can cut down on one dependency there and make this a tiny bit easier. I also made a central `OtelSpan` type in node-experimental to avoid using this everywhere throughout the codebase. --- packages/node-experimental/package.json | 32 +- .../src/integrations/http.ts | 3 +- .../node-experimental/src/sdk/initOtel.ts | 5 +- packages/node-experimental/src/types.ts | 3 + .../src/utils/addOriginToSpan.ts | 1 + .../src/utils/getRequestSpanData.ts | 3 +- packages/opentelemetry-node/package.json | 8 +- .../test/spanprocessor.test.ts | 4 +- yarn.lock | 418 ++++++++---------- 9 files changed, 215 insertions(+), 262 deletions(-) diff --git a/packages/node-experimental/package.json b/packages/node-experimental/package.json index 83ec589d8e4d..be0370637f3d 100644 --- a/packages/node-experimental/package.json +++ b/packages/node-experimental/package.json @@ -23,22 +23,22 @@ "access": "public" }, "dependencies": { - "@opentelemetry/api": "~1.4.1", - "@opentelemetry/context-async-hooks": "~1.15.0", - "@opentelemetry/instrumentation": "~0.41.0", - "@opentelemetry/instrumentation-express": "~0.33.0", - "@opentelemetry/instrumentation-fastify": "~0.32.0", - "@opentelemetry/instrumentation-graphql": "~0.35.0", - "@opentelemetry/instrumentation-http": "~0.41.0", - "@opentelemetry/instrumentation-mongodb": "~0.36.0", - "@opentelemetry/instrumentation-mongoose": "~0.33.0", - "@opentelemetry/instrumentation-mysql": "~0.34.0", - "@opentelemetry/instrumentation-mysql2": "~0.34.0", - "@opentelemetry/instrumentation-nestjs-core": "~0.33.0", - "@opentelemetry/instrumentation-pg": "~0.36.0", - "@opentelemetry/sdk-trace-node": "~1.15.0", - "@opentelemetry/semantic-conventions": "~1.15.0", - "@prisma/instrumentation": "~5.0.0", + "@opentelemetry/api": "~1.6.0", + "@opentelemetry/context-async-hooks": "~1.17.0", + "@opentelemetry/instrumentation": "~0.43.0", + "@opentelemetry/instrumentation-express": "~0.33.1", + "@opentelemetry/instrumentation-fastify": "~0.32.2", + "@opentelemetry/instrumentation-graphql": "~0.35.1", + "@opentelemetry/instrumentation-http": "~0.43.0", + "@opentelemetry/instrumentation-mongodb": "~0.37.0", + "@opentelemetry/instrumentation-mongoose": "~0.33.1", + "@opentelemetry/instrumentation-mysql": "~0.34.1", + "@opentelemetry/instrumentation-mysql2": "~0.34.1", + "@opentelemetry/instrumentation-nestjs-core": "~0.33.1", + "@opentelemetry/instrumentation-pg": "~0.36.1", + "@opentelemetry/sdk-trace-base": "~1.17.0", + "@opentelemetry/semantic-conventions": "~1.17.0", + "@prisma/instrumentation": "~5.3.1", "@sentry/core": "7.70.0", "@sentry/node": "7.70.0", "@sentry/opentelemetry-node": "7.70.0", diff --git a/packages/node-experimental/src/integrations/http.ts b/packages/node-experimental/src/integrations/http.ts index 2b1fc465049b..d2a3e35397be 100644 --- a/packages/node-experimental/src/integrations/http.ts +++ b/packages/node-experimental/src/integrations/http.ts @@ -2,7 +2,6 @@ import type { Attributes } from '@opentelemetry/api'; import { SpanKind } from '@opentelemetry/api'; import { registerInstrumentations } from '@opentelemetry/instrumentation'; import { HttpInstrumentation } from '@opentelemetry/instrumentation-http'; -import type { Span as OtelSpan } from '@opentelemetry/sdk-trace-node'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import { hasTracingEnabled, Transaction } from '@sentry/core'; import { getCurrentHub } from '@sentry/node'; @@ -10,7 +9,7 @@ import { _INTERNAL_getSentrySpan } from '@sentry/opentelemetry-node'; import type { EventProcessor, Hub, Integration } from '@sentry/types'; import type { ClientRequest, IncomingMessage, ServerResponse } from 'http'; -import type { NodeExperimentalClient } from '../types'; +import type { NodeExperimentalClient, OtelSpan } from '../types'; import { getRequestSpanData } from '../utils/getRequestSpanData'; interface TracingOptions { diff --git a/packages/node-experimental/src/sdk/initOtel.ts b/packages/node-experimental/src/sdk/initOtel.ts index 44ae76329dd2..eaa5937b1ddb 100644 --- a/packages/node-experimental/src/sdk/initOtel.ts +++ b/packages/node-experimental/src/sdk/initOtel.ts @@ -1,5 +1,5 @@ import { diag, DiagLogLevel } from '@opentelemetry/api'; -import { AlwaysOnSampler, NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; +import { AlwaysOnSampler, BasicTracerProvider } from '@opentelemetry/sdk-trace-base'; import { getCurrentHub } from '@sentry/core'; import { SentryPropagator, SentrySpanProcessor } from '@sentry/opentelemetry-node'; import { logger } from '@sentry/utils'; @@ -26,14 +26,13 @@ export function initOtel(): () => void { } // Create and configure NodeTracerProvider - const provider = new NodeTracerProvider({ + const provider = new BasicTracerProvider({ sampler: new AlwaysOnSampler(), }); provider.addSpanProcessor(new SentrySpanProcessor()); // We use a custom context manager to keep context in sync with sentry scope const contextManager = new SentryContextManager(); - contextManager.enable(); // Initialize the provider provider.register({ diff --git a/packages/node-experimental/src/types.ts b/packages/node-experimental/src/types.ts index 65e3d905be72..0fd9a6922a78 100644 --- a/packages/node-experimental/src/types.ts +++ b/packages/node-experimental/src/types.ts @@ -1,4 +1,5 @@ import type { Tracer } from '@opentelemetry/api'; +import type { Span as OtelSpan } from '@opentelemetry/sdk-trace-base'; import type { NodeClient, NodeOptions } from '@sentry/node'; import type { Breadcrumb, Transaction } from '@sentry/types'; @@ -24,3 +25,5 @@ export interface TransactionWithBreadcrumbs extends Transaction { /** Add a breadcrumb to this transaction. */ addBreadcrumb(breadcrumb: Breadcrumb, maxBreadcrumbs?: number): void; } + +export type { OtelSpan }; diff --git a/packages/node-experimental/src/utils/addOriginToSpan.ts b/packages/node-experimental/src/utils/addOriginToSpan.ts index c327043f0816..4320d31d7fce 100644 --- a/packages/node-experimental/src/utils/addOriginToSpan.ts +++ b/packages/node-experimental/src/utils/addOriginToSpan.ts @@ -1,3 +1,4 @@ +// We are using the broader OtelSpan type from api here, as this is also what integrations etc. use import type { Span as OtelSpan } from '@opentelemetry/api'; import { _INTERNAL_getSentrySpan } from '@sentry/opentelemetry-node'; import type { SpanOrigin } from '@sentry/types'; diff --git a/packages/node-experimental/src/utils/getRequestSpanData.ts b/packages/node-experimental/src/utils/getRequestSpanData.ts index d238077bd9df..ca89f5a2b976 100644 --- a/packages/node-experimental/src/utils/getRequestSpanData.ts +++ b/packages/node-experimental/src/utils/getRequestSpanData.ts @@ -1,8 +1,9 @@ -import type { Span as OtelSpan } from '@opentelemetry/sdk-trace-base'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import type { SanitizedRequestData } from '@sentry/types'; import { getSanitizedUrlString, parseUrl } from '@sentry/utils'; +import type { OtelSpan } from '../types'; + /** * Get sanitizied request data from an OTEL span. */ diff --git a/packages/opentelemetry-node/package.json b/packages/opentelemetry-node/package.json index 516c8db5856b..9c1e54430fb5 100644 --- a/packages/opentelemetry-node/package.json +++ b/packages/opentelemetry-node/package.json @@ -34,11 +34,11 @@ "@opentelemetry/semantic-conventions": "1.x" }, "devDependencies": { - "@opentelemetry/api": "^1.4.1", + "@opentelemetry/api": "^1.6.0", "@opentelemetry/core": "^1.7.0", - "@opentelemetry/sdk-trace-base": "^1.15.0", - "@opentelemetry/sdk-trace-node": "^1.15.0", - "@opentelemetry/semantic-conventions": "^1.7.0", + "@opentelemetry/sdk-trace-base": "^1.17.0", + "@opentelemetry/sdk-trace-node": "^1.17.0", + "@opentelemetry/semantic-conventions": "^1.17.0", "@sentry/node": "7.70.0" }, "scripts": { diff --git a/packages/opentelemetry-node/test/spanprocessor.test.ts b/packages/opentelemetry-node/test/spanprocessor.test.ts index 3b87068c76f7..ea6e0833a395 100644 --- a/packages/opentelemetry-node/test/spanprocessor.test.ts +++ b/packages/opentelemetry-node/test/spanprocessor.test.ts @@ -275,7 +275,7 @@ describe('SentrySpanProcessor', () => { 'service.name': 'test-service', 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', - 'telemetry.sdk.version': '1.15.0', + 'telemetry.sdk.version': '1.17.0', }, }, }); @@ -300,7 +300,7 @@ describe('SentrySpanProcessor', () => { 'service.name': 'test-service', 'telemetry.sdk.language': 'nodejs', 'telemetry.sdk.name': 'opentelemetry', - 'telemetry.sdk.version': '1.15.0', + 'telemetry.sdk.version': '1.17.0', }, }, }); diff --git a/yarn.lock b/yarn.lock index d283d72b7ad2..94290bdb6a55 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3802,7 +3802,7 @@ dependencies: "@opentelemetry/context-base" "^0.14.0" -"@opentelemetry/api@1.4.1", "@opentelemetry/api@^1.4.1", "@opentelemetry/api@~1.4.1": +"@opentelemetry/api@1.4.1": version "1.4.1" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== @@ -3814,17 +3814,15 @@ dependencies: "@opentelemetry/context-base" "^0.12.0" -"@opentelemetry/context-async-hooks@1.15.0": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.15.0.tgz#134ecbe9096227f72e3178a15287a420a13746a0" - integrity sha512-sfxQOyAyV3WsKswGX0Yx3P+e7t3EtxpF/PC+6e4+rqs88oUfTaP3214iz4GQuuzV9yCG8DRWTZ96J6E/iD0qeA== - dependencies: - tslib "^2.3.1" +"@opentelemetry/api@^1.6.0", "@opentelemetry/api@~1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.6.0.tgz#de2c6823203d6f319511898bb5de7e70f5267e19" + integrity sha512-OWlrQAnWn9577PhVgqjUvMr1pg57Bc4jv0iL4w0PRuOSRvq67rvHW9Ie/dZVMvCzhSCB+UxhcY/PmCmFj33Q+g== -"@opentelemetry/context-async-hooks@~1.15.0": - version "1.15.2" - resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.15.2.tgz#116bd5fef231137198d5bf551e8c0521fbdfe928" - integrity sha512-VAMHG67srGFQDG/N2ns5AyUT9vUcoKpZ/NpJ5fDQIPfJd7t3ju+aHwvDsMcrYBWuCh03U3Ky6o16+872CZchBg== +"@opentelemetry/context-async-hooks@1.17.0", "@opentelemetry/context-async-hooks@~1.17.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.17.0.tgz#d198319785bc81533f1a096e86d7f81ce57346ed" + integrity sha512-bDIRCgpKniSyhORU0fTL9ISW6ucU9nruKyXKwYrEBep/2f3uLz8LFyF51ZUK9QxIwBHw6WJudK/2UqttWzER4w== "@opentelemetry/context-base@^0.12.0": version "0.12.0" @@ -3836,20 +3834,19 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.14.0.tgz#c67fc20a4d891447ca1a855d7d70fa79a3533001" integrity sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw== -"@opentelemetry/core@1.14.0": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.14.0.tgz#64e876b29cb736c984d54164cd47433f513eafd3" - integrity sha512-MnMZ+sxsnlzloeuXL2nm5QcNczt/iO82UOeQQDHhV83F2fP3sgntW2evvtoxJki0MBLxEsh5ADD7PR/Hn5uzjw== +"@opentelemetry/core@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.2.tgz#5b170bf223a2333884bbc2d29d95812cdbda7c9f" + integrity sha512-+gBv15ta96WqkHZaPpcDHiaz0utiiHZVfm2YOYSqFGrUaJpPkMoSuLBB58YFQGi6Rsb9EHos84X6X5+9JspmLw== dependencies: - "@opentelemetry/semantic-conventions" "1.14.0" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/core@1.15.0", "@opentelemetry/core@^1.1.0", "@opentelemetry/core@^1.8.0": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.15.0.tgz#2ba928df0443732825a72a766c2edae9a7f9863f" - integrity sha512-GGTS6BytfaN8OgbCUOnxg/a9WVsVUj0484zXHZuBzvIXx7V4Tmkb0IHnnhS7Q0cBLNLgjNuvrCpQaP8fIvO4bg== +"@opentelemetry/core@1.17.0", "@opentelemetry/core@^1.1.0", "@opentelemetry/core@^1.7.0", "@opentelemetry/core@^1.8.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.17.0.tgz#6a72425f5f953dc68b4c7c66d947c018173d30d2" + integrity sha512-tfnl3h+UefCgx1aeN2xtrmr6BmdWGKXypk0pflQR0urFS40aE88trnkOMc2HTJZbMrqEEl4HsaBeFhwLVXsrJg== dependencies: - "@opentelemetry/semantic-conventions" "1.15.0" - tslib "^2.3.1" + "@opentelemetry/semantic-conventions" "1.17.0" "@opentelemetry/core@^0.12.0": version "0.12.0" @@ -3860,180 +3857,149 @@ "@opentelemetry/context-base" "^0.12.0" semver "^7.1.3" -"@opentelemetry/core@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.7.0.tgz#83bdd1b7a4ceafcdffd6590420657caec5f7b34c" - integrity sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ== - dependencies: - "@opentelemetry/semantic-conventions" "1.7.0" - -"@opentelemetry/instrumentation-express@~0.33.0": - version "0.33.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.33.0.tgz#d972ef43420759761f7dbfe78a6ae159cd925a69" - integrity sha512-Cem3AssubzUoBK5ab89rBt2kY90i/FFyQwMC9wPjBQldkOaT4cR+5ufvWritXRfoPltqEeX2imLavujNH6EzCw== +"@opentelemetry/instrumentation-express@~0.33.1": + version "0.33.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.33.1.tgz#0710f839d2a395014d2ffef9390074bb60009841" + integrity sha512-awrpiTZWnLOCJ4TeDMTrs6/gH/oXbNipoPx3WUKQlA1yfMlpNynqokTyCYv1n10Zu9Y2P/nIhoNnUw0ywp61nA== dependencies: "@opentelemetry/core" "^1.8.0" - "@opentelemetry/instrumentation" "^0.41.0" + "@opentelemetry/instrumentation" "^0.41.2" "@opentelemetry/semantic-conventions" "^1.0.0" - "@types/express" "4.17.13" - tslib "^2.3.1" + "@types/express" "4.17.17" -"@opentelemetry/instrumentation-fastify@~0.32.0": - version "0.32.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.32.0.tgz#9f0846282f5f428b3ec9a749c1111cf2f153986d" - integrity sha512-M0zRI5+FfA2UnNk9YSeofhZkM5X46w2lDW/1pVahpIlfyPoEbOdRO2YrfR6Y9t9emR62IKk4tN/IcSgXIK2RRg== +"@opentelemetry/instrumentation-fastify@~0.32.2": + version "0.32.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.32.2.tgz#4af882938d3c05f7c7f5f860095e568728a2d838" + integrity sha512-DKa7SgxTtZ0O1ngGtAdwr/g8XguYw6KvLNME+J8rt6QpWQM+xytS0bg4atZAyt6aeYr/kO1sMrGXSlHEEYWIhg== dependencies: "@opentelemetry/core" "^1.8.0" - "@opentelemetry/instrumentation" "^0.41.0" + "@opentelemetry/instrumentation" "^0.41.2" "@opentelemetry/semantic-conventions" "^1.0.0" - tslib "^2.3.1" -"@opentelemetry/instrumentation-graphql@~0.35.0": - version "0.35.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.35.0.tgz#45d2df2be320c7289aff49cabfbbfa8791670b19" - integrity sha512-hKuOXTzB8UBaxVteKU2nMRGnUPt6bD9SSBBLYaDOGGPF1Gs4XsiuMMRuyXomMIudelM7flPpbuqiP9YoSJuXQQ== +"@opentelemetry/instrumentation-graphql@~0.35.1": + version "0.35.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.35.1.tgz#e49ec2256bcc4820458688abac0212ac781864c0" + integrity sha512-bAM4W5wU0lZ1UIKK/5b4p8LEU8N6W+VgpcnUIK7GTTDxdhcWTd3Q6oyS6nauhZSzEnAEmmJVXaLQAGIU4sEkyA== dependencies: - "@opentelemetry/instrumentation" "^0.41.0" - tslib "^2.3.1" + "@opentelemetry/instrumentation" "^0.41.2" -"@opentelemetry/instrumentation-http@~0.41.0": - version "0.41.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.41.0.tgz#c92ffcb9581544d76d17540f7df442fad8601035" - integrity sha512-O/YTVH4xE96rxRYoo14vayM9s0MUTtMASMAtYS3yvXMJETgc5aFnTrWezKQ6VJ2Lew5qfm1ZISzFURLSUM0qTw== +"@opentelemetry/instrumentation-http@~0.43.0": + version "0.43.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.43.0.tgz#c21cf8b407e26c912448b110f340ad1eb657a316" + integrity sha512-Ho3IFQFuD0xmcVc0Uq9AvYvROSOuydn4XWRT/h/GO0VCwOeYz/WCwUJvRdS3m1B3AZ4iGJ0q/nhsATp2JX3/gA== dependencies: - "@opentelemetry/core" "1.15.0" - "@opentelemetry/instrumentation" "0.41.0" - "@opentelemetry/semantic-conventions" "1.15.0" - semver "^7.5.1" - tslib "^2.3.1" + "@opentelemetry/core" "1.17.0" + "@opentelemetry/instrumentation" "0.43.0" + "@opentelemetry/semantic-conventions" "1.17.0" + semver "^7.5.2" -"@opentelemetry/instrumentation-mongodb@~0.36.0": - version "0.36.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.36.0.tgz#2ee2acffb1869d9dc3a89e9b879be987e18c1b11" - integrity sha512-bisDLBO0JqydPh4rkgrbYhnFOd4T2ZAnFAnBFll9TB1jJEHTeeobdBThuwxvur5q5ZfbjevreUcMydG6UBNMaA== +"@opentelemetry/instrumentation-mongodb@~0.37.0": + version "0.37.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.37.0.tgz#a7cf4bd9cd5b1053182ec1458c91456812432f55" + integrity sha512-Fwuwf7Fsx/F3QXtU6hbxU4D6DtT33YkAr0+fjtR7qTEcAU0YOxCZfy4tlX2jxjxR1ze8tKfaAWhXBxXwLMWT3g== dependencies: - "@opentelemetry/instrumentation" "^0.41.0" + "@opentelemetry/instrumentation" "^0.41.2" "@opentelemetry/sdk-metrics" "^1.9.1" "@opentelemetry/semantic-conventions" "^1.0.0" - tslib "^2.3.1" -"@opentelemetry/instrumentation-mongoose@~0.33.0": - version "0.33.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.33.0.tgz#8063740274120105f559bcf663125d3f7cc00cb4" - integrity sha512-IB4zCJ7vsiILx5hjPH7PtlvKIVN84m3rER8zu7xeaMpfpzD5/khj6et0x1aE+KzPS49nIOZx3qmH67MocSNevg== +"@opentelemetry/instrumentation-mongoose@~0.33.1": + version "0.33.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.33.1.tgz#0e37eed215fb7fbf8adc0e70199bb8992cb1ea21" + integrity sha512-IzYcEZSmlaOlkyACt8gTl0z3eEQafxzEAt/+W+FdNBiUdm81qpVx/1bpzJwSgIsgcLf27Dl5WsPmrSAi4+Bcng== dependencies: "@opentelemetry/core" "^1.8.0" - "@opentelemetry/instrumentation" "^0.41.0" + "@opentelemetry/instrumentation" "^0.41.2" "@opentelemetry/semantic-conventions" "^1.0.0" - tslib "^2.3.1" -"@opentelemetry/instrumentation-mysql2@~0.34.0": - version "0.34.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.34.0.tgz#48f560b7169128195d19114451c3a5c907b7833a" - integrity sha512-wEJ9BcZTT/60a69V5GS/XlQx+JyoOKKYYR/kdZ2p/XY/UI+kELPSWiLZAR00YLYi33g0zVZlKG3gfHU1KFn5sQ== +"@opentelemetry/instrumentation-mysql2@~0.34.1": + version "0.34.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.34.1.tgz#d7ce741a7d9a7da270fa791e1c64d8cedd58b5b7" + integrity sha512-SPwgLI2H+gH+GP7b5cWQlFqO/7UeHvw6ZzFKxwLr4vy8wmxYF4aBMLc8qVO8bdXFHd114v0IzOIAvpG6sl/zYQ== dependencies: - "@opentelemetry/instrumentation" "^0.41.0" + "@opentelemetry/instrumentation" "^0.41.2" "@opentelemetry/semantic-conventions" "^1.0.0" - tslib "^2.3.1" + "@opentelemetry/sql-common" "^0.40.0" -"@opentelemetry/instrumentation-mysql@~0.34.0": - version "0.34.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.34.0.tgz#437294f3c8b02ad76b3d56e77f28d9af6cf19c91" - integrity sha512-muBzhaSk3to1XK2aSMFTP9lW6YALebQ8ick9raDBESiLf8JREZDJWVlhfaigeJGBk53tUBZ3Ty1g1Cfe15+OhQ== +"@opentelemetry/instrumentation-mysql@~0.34.1": + version "0.34.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.34.1.tgz#9703d21615dd5ee6b9eda1d74029ba75eec46c9a" + integrity sha512-zQq7hN3ILm1vIJCGeKHRc4pTK8LOmkTt8oKWf0v+whFs7axieIhXZMoCqIBm6BigLy3Trg5iaKyuSrx7kO6q2g== dependencies: - "@opentelemetry/instrumentation" "^0.41.0" + "@opentelemetry/instrumentation" "^0.41.2" "@opentelemetry/semantic-conventions" "^1.0.0" - "@types/mysql" "2.15.19" - tslib "^2.3.1" + "@types/mysql" "2.15.21" -"@opentelemetry/instrumentation-nestjs-core@~0.33.0": - version "0.33.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.33.0.tgz#f2d64f033f9a84c2ba4ce85c0ec1381ec542b452" - integrity sha512-/c1nipi2XLt2TQlFpKNof44o99H7BmdOWiZBAdIATJpvOKPbn+Ggt4OQQdtmxFyzMX13dTxgtpQ5RX2Orvxz2Q== +"@opentelemetry/instrumentation-nestjs-core@~0.33.1": + version "0.33.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.33.1.tgz#a6e0175bcda25e455339a5527268e746be969297" + integrity sha512-Y5Khvp8ODA6TuDcZKAc63cYDeeZAA/n0ceF0pcVCJwA2NBeD0hmTrCJXES2cvt7wVbHV/SYCu7OpYDQkNjbBWw== dependencies: - "@opentelemetry/instrumentation" "^0.41.0" + "@opentelemetry/instrumentation" "^0.41.2" "@opentelemetry/semantic-conventions" "^1.0.0" - tslib "^2.3.1" -"@opentelemetry/instrumentation-pg@~0.36.0": - version "0.36.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.36.0.tgz#43270d2849a0e074ec6eb705dc12216e5c7cc84c" - integrity sha512-S9RmzTILWTl7AVfdp/e8lWQTlpwrpoPbpxAfEJ1ENzTlPMmdw0jWPAQTgrTLQa6cpzhiypDHts3g2b6hc1zFYQ== +"@opentelemetry/instrumentation-pg@~0.36.1": + version "0.36.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.36.1.tgz#66e3aa10948c6e3188d04676dbf304ae8571ce2f" + integrity sha512-k8L7RSRTQ6e+DbHEXZB8Tmf/efkQnWKeClpZb3TEdb34Pvme4PmcpG2zb6JtM99nNrshNlVDLCZ90U3xDneTbw== dependencies: "@opentelemetry/core" "^1.8.0" - "@opentelemetry/instrumentation" "^0.41.0" + "@opentelemetry/instrumentation" "^0.41.2" "@opentelemetry/semantic-conventions" "^1.0.0" "@opentelemetry/sql-common" "^0.40.0" "@types/pg" "8.6.1" "@types/pg-pool" "2.0.3" - tslib "^2.3.1" -"@opentelemetry/instrumentation@0.40.0": - version "0.40.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.40.0.tgz#13d5f2d60c3fafef124ab6961a32204f7ef8bb25" - integrity sha512-23TzBKPflUS1uEq5SXymnQKQDSda35KvHjnvxdcDQGE+wg6hwDHgScUCWiBmZW4sxAaPcANfs+Wc9B7yDuyT6Q== - dependencies: - "@types/shimmer" "^1.0.2" - import-in-the-middle "1.3.5" - require-in-the-middle "^7.1.0" - semver "^7.3.2" - shimmer "^1.2.1" - -"@opentelemetry/instrumentation@0.41.0": - version "0.41.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.0.tgz#a67a7f6d215d8802c2e956907a913b793037e04d" - integrity sha512-Ut9SnZfi7MexOk+GHCMjEtYHogIb6v1dfbnq+oTbQj0lOQUSNLtlO6bXwUdtmPhbvrx6bC0AGr1L6g3rNimv9w== +"@opentelemetry/instrumentation@0.41.2", "@opentelemetry/instrumentation@^0.41.2": + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" + integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== dependencies: "@types/shimmer" "^1.0.2" - import-in-the-middle "1.4.1" + import-in-the-middle "1.4.2" require-in-the-middle "^7.1.1" semver "^7.5.1" shimmer "^1.2.1" - tslib "^2.3.1" -"@opentelemetry/instrumentation@^0.41.0", "@opentelemetry/instrumentation@~0.41.0": - version "0.41.2" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" - integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== +"@opentelemetry/instrumentation@0.43.0", "@opentelemetry/instrumentation@~0.43.0": + version "0.43.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.43.0.tgz#749521415df03396f969bf42341fcb4acd2e9c7b" + integrity sha512-S1uHE+sxaepgp+t8lvIDuRgyjJWisAb733198kwQTUc9ZtYQ2V2gmyCtR1x21ePGVLoMiX/NWY7WA290hwkjJQ== dependencies: "@types/shimmer" "^1.0.2" import-in-the-middle "1.4.2" require-in-the-middle "^7.1.1" - semver "^7.5.1" + semver "^7.5.2" shimmer "^1.2.1" -"@opentelemetry/propagator-b3@1.15.0": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-b3/-/propagator-b3-1.15.0.tgz#502c3b7030646e7654ce243ae24b67aeac405a53" - integrity sha512-YafSIITpCmo76VdlJ/GvS5x+uuRWCU5BqCOV9CITi11Tk4aqTxMR3pXlMoPYQWstUUgacQf4dGcdvdS+1rkDWQ== +"@opentelemetry/propagator-b3@1.17.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-b3/-/propagator-b3-1.17.0.tgz#32509a8214b7ced7709fd06c0ee5a0d86adcc51f" + integrity sha512-oklstXImtaly4vDaL+rGtX41YXZR50jp5a7CSEPMcStp1B7ozdZ5G2I5wftrDvOlOcLt/TIkGWDCr/OkVN7kWg== dependencies: - "@opentelemetry/core" "1.15.0" - tslib "^2.3.1" + "@opentelemetry/core" "1.17.0" -"@opentelemetry/propagator-jaeger@1.15.0": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.15.0.tgz#098cfebe885f8c0f4ed3073aa9a7c0aa253086c8" - integrity sha512-OU6WNxuqjxNZoRcIBCsmvTBktAPuBUj1bh+DI+oYAvzwP2NXLavSDJWjVMGTJQDgZuR7lFijmx9EfwyAO9x37Q== +"@opentelemetry/propagator-jaeger@1.17.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.17.0.tgz#a89dbc34447db0b5029b719baaa111f268b52265" + integrity sha512-iZzu8K0QkZZ16JH9yox6hZk7/Rxc4SPeGU37pvlB9DtzfNxAEX1FMK9zvowv3ve7r2uzZNpa7JGVUwpy5ewdHQ== dependencies: - "@opentelemetry/core" "1.15.0" - tslib "^2.3.1" + "@opentelemetry/core" "1.17.0" -"@opentelemetry/resources@1.14.0": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.14.0.tgz#d6b0a4e71c2706d33c8c6ec7a7b8fea6ad27ddea" - integrity sha512-qRfWIgBxxl3z47E036Aey0Lj2ZjlFb27Q7Xnj1y1z/P293RXJZGLtcfn/w8JF7v1Q2hs3SDGxz7Wb9Dko1YUQA== +"@opentelemetry/resources@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.2.tgz#0c9e26cb65652a1402834a3c030cce6028d6dd9d" + integrity sha512-xmMRLenT9CXmm5HMbzpZ1hWhaUowQf8UB4jMjFlAxx1QzQcsD3KFNAVX/CAWzFPtllTyTplrA4JrQ7sCH3qmYw== dependencies: - "@opentelemetry/core" "1.14.0" - "@opentelemetry/semantic-conventions" "1.14.0" + "@opentelemetry/core" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" -"@opentelemetry/resources@1.15.0": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.15.0.tgz#748a6ae9017636b8b30f5dee1fff3e166e51f63d" - integrity sha512-Sb8A6ZXHXDlgHv32UNRE3y8McWE3vkb5dsSttYArYa5ZpwjiF5ge0vnnKUUnG7bY0AgF9VBIOORZE8gsrnD2WA== +"@opentelemetry/resources@1.17.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.17.0.tgz#ee29144cfd7d194c69698c8153dbadec7fe6819f" + integrity sha512-+u0ciVnj8lhuL/qGRBPeVYvk7fL+H/vOddfvmOeJaA1KC+5/3UED1c9KoZQlRsNT5Kw1FaK8LkY2NVLYfOVZQw== dependencies: - "@opentelemetry/core" "1.15.0" - "@opentelemetry/semantic-conventions" "1.15.0" - tslib "^2.3.1" + "@opentelemetry/core" "1.17.0" + "@opentelemetry/semantic-conventions" "1.17.0" "@opentelemetry/resources@^0.12.0": version "0.12.0" @@ -4044,63 +4010,53 @@ "@opentelemetry/core" "^0.12.0" "@opentelemetry/sdk-metrics@^1.9.1": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.15.0.tgz#e47ad688882fc2daedcbbe3db16a5c110feb23e8" - integrity sha512-fFUnAcPvlXO39nlIduGuaeCuiZyFtSLCn9gW/0djFRO5DFst4m4gcT6+llXvNWuUvtGB49s56NP10B9IZRN0Rw== + version "1.17.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.17.0.tgz#e51d39e0bb749780d17f9b1df12f0490438dec1a" + integrity sha512-HlWM27yGmYuwCoVRe3yg2PqKnIsq0kEF0HQgvkeDWz2NYkq9fFaSspR6kvjxUTbghAlZrabiqbgyKoYpYaXS3w== dependencies: - "@opentelemetry/core" "1.15.0" - "@opentelemetry/resources" "1.15.0" + "@opentelemetry/core" "1.17.0" + "@opentelemetry/resources" "1.17.0" lodash.merge "^4.6.2" - tslib "^2.3.1" -"@opentelemetry/sdk-trace-base@1.14.0": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.14.0.tgz#831af08f002228a11e577ff860eb6059c8b80fb7" - integrity sha512-NzRGt3PS+HPKfQYMb6Iy8YYc5OKA73qDwci/6ujOIvyW9vcqBJSWbjZ8FeLEAmuatUB5WrRhEKu9b0sIiIYTrQ== - dependencies: - "@opentelemetry/core" "1.14.0" - "@opentelemetry/resources" "1.14.0" - "@opentelemetry/semantic-conventions" "1.14.0" - -"@opentelemetry/sdk-trace-base@1.15.0", "@opentelemetry/sdk-trace-base@^1.15.0": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.0.tgz#92340ded8f9fec1aaa63afb40c6e7e01769c2852" - integrity sha512-udt1c9VHipbZwvCPIQR1VLg25Z4AMR/g0X8KmcInbFruGWQ/lptVPkz3yvWAsGSta5yHNQ3uoPwcyCygGnQ6Lg== - dependencies: - "@opentelemetry/core" "1.15.0" - "@opentelemetry/resources" "1.15.0" - "@opentelemetry/semantic-conventions" "1.15.0" - tslib "^2.3.1" - -"@opentelemetry/sdk-trace-node@^1.15.0", "@opentelemetry/sdk-trace-node@~1.15.0": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.15.0.tgz#2d49eafb070a6a53e8df7e91dab30ec2370ba310" - integrity sha512-TKBx9oThZUVKkoGpXhFT/XUgpjq28TWwc6j3JlsL+cJX77DKBnVC+2H+kdVVJHRzyfqDx4LEJJVCwQO3K+cbXA== - dependencies: - "@opentelemetry/context-async-hooks" "1.15.0" - "@opentelemetry/core" "1.15.0" - "@opentelemetry/propagator-b3" "1.15.0" - "@opentelemetry/propagator-jaeger" "1.15.0" - "@opentelemetry/sdk-trace-base" "1.15.0" - semver "^7.5.1" - tslib "^2.3.1" - -"@opentelemetry/semantic-conventions@1.14.0": - version "1.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.14.0.tgz#6a729b7f372ce30f77a3f217c09bc216f863fccb" - integrity sha512-rJfCY8rCWz3cb4KI6pEofnytvMPuj3YLQwoscCCYZ5DkdiPjo15IQ0US7+mjcWy9H3fcZIzf2pbJZ7ck/h4tug== - -"@opentelemetry/semantic-conventions@1.15.0", "@opentelemetry/semantic-conventions@^1.0.0", "@opentelemetry/semantic-conventions@~1.15.0": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.0.tgz#e6173daa5fd61f353b02c858001388bf26e9d059" - integrity sha512-f3wwFrFyCpGrFBrFs7lCUJSCSCGyeKG52c+EKeobs3Dd29M75yO6GYkt6PkYPfDawxSlV5p+4yJPPk8tPObzTQ== - dependencies: - tslib "^2.3.1" +"@opentelemetry/sdk-trace-base@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.15.2.tgz#4821f94033c55a6c8bbd35ae387b715b6108517a" + integrity sha512-BEaxGZbWtvnSPchV98qqqqa96AOcb41pjgvhfzDij10tkBhIu9m0Jd6tZ1tJB5ZHfHbTffqYVYE0AOGobec/EQ== + dependencies: + "@opentelemetry/core" "1.15.2" + "@opentelemetry/resources" "1.15.2" + "@opentelemetry/semantic-conventions" "1.15.2" + +"@opentelemetry/sdk-trace-base@1.17.0", "@opentelemetry/sdk-trace-base@^1.17.0", "@opentelemetry/sdk-trace-base@~1.17.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.17.0.tgz#05a21763c9efa72903c20b8930293cdde344b681" + integrity sha512-2T5HA1/1iE36Q9eg6D4zYlC4Y4GcycI1J6NsHPKZY9oWfAxWsoYnRlkPfUqyY5XVtocCo/xHpnJvGNHwzT70oQ== + dependencies: + "@opentelemetry/core" "1.17.0" + "@opentelemetry/resources" "1.17.0" + "@opentelemetry/semantic-conventions" "1.17.0" + +"@opentelemetry/sdk-trace-node@^1.17.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.17.0.tgz#c2f23665e5a6878a7ad6a372dac72e7ab05c4eb5" + integrity sha512-Twlaje+t16b5j62CfcaKU869rP9oyBG/sVQWBI5+kDaWuP/YIFnF4LbovaEahK9GwAnW8vPIn6iYLAl/jZBidA== + dependencies: + "@opentelemetry/context-async-hooks" "1.17.0" + "@opentelemetry/core" "1.17.0" + "@opentelemetry/propagator-b3" "1.17.0" + "@opentelemetry/propagator-jaeger" "1.17.0" + "@opentelemetry/sdk-trace-base" "1.17.0" + semver "^7.5.2" + +"@opentelemetry/semantic-conventions@1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.2.tgz#3bafb5de3e20e841dff6cb3c66f4d6e9694c4241" + integrity sha512-CjbOKwk2s+3xPIMcd5UNYQzsf+v94RczbdNix9/kQh38WiQkM90sUOi3if8eyHFgiBjBjhwXrA7W3ydiSQP9mw== -"@opentelemetry/semantic-conventions@1.7.0", "@opentelemetry/semantic-conventions@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz#af80a1ef7cf110ea3a68242acd95648991bcd763" - integrity sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA== +"@opentelemetry/semantic-conventions@1.17.0", "@opentelemetry/semantic-conventions@^1.0.0", "@opentelemetry/semantic-conventions@^1.17.0", "@opentelemetry/semantic-conventions@~1.17.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.17.0.tgz#af10baa9f05ce1e64a14065fc138b5739bfb65f6" + integrity sha512-+fguCd2d8d2qruk0H0DsCEy2CTK3t0Tugg7MhZ/UQMvmewbZLNnJ6heSYyzIZWG5IPfAXzoj4f4F/qpM7l4VBA== "@opentelemetry/semantic-conventions@^0.12.0": version "0.12.0" @@ -4170,14 +4126,14 @@ resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-3.15.1-1.461d6a05159055555eb7dfb337c9fb271cbd4d7e.tgz#bf5e2373ca68ce7556b967cb4965a7095e93fe53" integrity sha512-e3k2Vd606efd1ZYy2NQKkT4C/pn31nehyLhVug6To/q8JT8FpiMrDy7zmm3KLF0L98NOQQcutaVtAPhzKhzn9w== -"@prisma/instrumentation@~5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-5.0.0.tgz#6112461d0ffa401b9278c26d3fef027b0b42820d" - integrity sha512-GUt9ztQXriBmxPIDBd20eBHOX+LaF3zj4ot6mpMB/2YkceU4MvicdEoaX2VkF3r/xM7TatCF9IR2d35wOIv2GA== +"@prisma/instrumentation@~5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-5.3.1.tgz#438b8f1b8b14b190dd7bf1bbc903af4c40856648" + integrity sha512-g4epN9WdsyvX24nuoY7ie9uEsLuNUvYA2ShY9D1Ouz0STMltq1iCWAHugKXYKdKFRtoNP8Vo/QtVLQEEqvNQJQ== dependencies: "@opentelemetry/api" "1.4.1" - "@opentelemetry/instrumentation" "0.40.0" - "@opentelemetry/sdk-trace-base" "1.14.0" + "@opentelemetry/instrumentation" "0.41.2" + "@opentelemetry/sdk-trace-base" "1.15.2" "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" @@ -5235,15 +5191,15 @@ "@types/qs" "*" "@types/range-parser" "*" -"@types/express@4.17.13": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== +"@types/express-serve-static-core@^4.17.33": + version "4.17.36" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz#baa9022119bdc05a4adfe740ffc97b5f9360e545" + integrity sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q== dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" + "@types/node" "*" "@types/qs" "*" - "@types/serve-static" "*" + "@types/range-parser" "*" + "@types/send" "*" "@types/express@4.17.14", "@types/express@^4.17.14", "@types/express@^4.17.2": version "4.17.14" @@ -5255,6 +5211,16 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/express@4.17.17": + version "4.17.17" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" + integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + "@types/fs-extra@^5.0.5": version "5.1.0" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.1.0.tgz#2a325ef97901504a3828718c390d34b8426a10a1" @@ -5419,14 +5385,7 @@ "@types/bson" "*" "@types/node" "*" -"@types/mysql@2.15.19": - version "2.15.19" - resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.19.tgz#d158927bb7c1a78f77e56de861a3b15cae0e7aed" - integrity sha512-wSRg2QZv14CWcZXkgdvHbbV2ACufNy5EgI8mBBxnJIptchv7DBy/h53VMa2jDhyo0C9MO4iowE6z9vF8Ja1DkQ== - dependencies: - "@types/node" "*" - -"@types/mysql@^2.15.21": +"@types/mysql@2.15.21", "@types/mysql@^2.15.21": version "2.15.21" resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.21.tgz#7516cba7f9d077f980100c85fd500c8210bd5e45" integrity sha512-NPotx5CVful7yB+qZbWtXL2fA4e7aEHkihHLjklc6ID8aq7bhguHgeIoC1EmSNTAuCgI6ZXrjt2ZSaXnYX0EUg== @@ -5627,6 +5586,14 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== +"@types/send@*": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.1.tgz#ed4932b8a2a805f1fe362a70f4e62d0ac994e301" + integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + "@types/serve-static@*": version "1.13.9" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e" @@ -15903,23 +15870,6 @@ import-from@^2.1.0: dependencies: resolve-from "^3.0.0" -import-in-the-middle@1.3.5: - version "1.3.5" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.3.5.tgz#78384fbcfc7c08faf2b1f61cb94e7dd25651df9c" - integrity sha512-yzHlBqi1EBFrkieAnSt8eTgO5oLSl+YJ7qaOpUH/PMqQOMZoQ/RmDlwnTLQrwYto+gHYjRG+i/IbsB1eDx32NQ== - dependencies: - module-details-from-path "^1.0.3" - -import-in-the-middle@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.1.tgz#31b25123bc35d556986a172bb398a3e6c32af9be" - integrity sha512-hGG0PcCsykVo8MBVH8l0uEWLWW6DXMgJA9jvC0yps6M3uIJ8L/tagTCbyF8Ud5TtqJ8/jmZL1YkyySyeVkVQrA== - dependencies: - acorn "^8.8.2" - acorn-import-assertions "^1.9.0" - cjs-module-lexer "^1.2.2" - module-details-from-path "^1.0.3" - import-in-the-middle@1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" @@ -24266,7 +24216,7 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -require-in-the-middle@^7.1.0, require-in-the-middle@^7.1.1: +require-in-the-middle@^7.1.1: version "7.2.0" resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== @@ -25049,7 +24999,7 @@ semver@7.5.3: dependencies: lru-cache "^6.0.0" -semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.1, semver@^7.5.3: +semver@7.x, semver@^7.0.0, semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.1, semver@^7.5.2, semver@^7.5.3: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== From 27cf07fa8117e1c2df4e1ed5041d9f85606d8301 Mon Sep 17 00:00:00 2001 From: Onur Temizkan Date: Wed, 20 Sep 2023 18:09:10 +0100 Subject: [PATCH 04/15] fix(react): Compare location against `basename`-prefixed route. (#9076) Co-authored-by: Abhijeet Prasad --- packages/react/src/reactrouterv6.tsx | 12 ++--- packages/react/test/reactrouterv6.4.test.tsx | 46 +++++++++++++++++++- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/packages/react/src/reactrouterv6.tsx b/packages/react/src/reactrouterv6.tsx index bd127ca1010a..792d36385566 100644 --- a/packages/react/src/reactrouterv6.tsx +++ b/packages/react/src/reactrouterv6.tsx @@ -78,6 +78,7 @@ function getNormalizedName( routes: RouteObject[], location: Location, branches: RouteMatch[], + basename: string = '', ): [string, TransactionSource] { if (!routes || routes.length === 0) { return [location.pathname, 'url']; @@ -99,7 +100,8 @@ function getNormalizedName( if (path) { const newPath = path[0] === '/' || pathBuilder[pathBuilder.length - 1] === '/' ? path : `/${path}`; pathBuilder += newPath; - if (branch.pathname === location.pathname) { + + if (basename + branch.pathname === location.pathname) { if ( // If the route defined on the element is something like // Product} /> @@ -108,9 +110,9 @@ function getNormalizedName( // We should not count wildcard operators in the url segments calculation pathBuilder.slice(-2) !== '/*' ) { - return [newPath, 'route']; + return [basename + newPath, 'route']; } - return [pathBuilder, 'route']; + return [basename + pathBuilder, 'route']; } } } @@ -131,7 +133,7 @@ function updatePageloadTransaction( : (_matchRoutes(routes, location, basename) as unknown as RouteMatch[]); if (activeTransaction && branches) { - activeTransaction.setName(...getNormalizedName(routes, location, branches)); + activeTransaction.setName(...getNormalizedName(routes, location, branches, basename)); } } @@ -149,7 +151,7 @@ function handleNavigation( activeTransaction.finish(); } - const [name, source] = getNormalizedName(routes, location, branches); + const [name, source] = getNormalizedName(routes, location, branches, basename); activeTransaction = _customStartTransaction({ name, op: 'navigation', diff --git a/packages/react/test/reactrouterv6.4.test.tsx b/packages/react/test/reactrouterv6.4.test.tsx index 19a714f853a3..a5c35169c283 100644 --- a/packages/react/test/reactrouterv6.4.test.tsx +++ b/packages/react/test/reactrouterv6.4.test.tsx @@ -307,7 +307,51 @@ describe('React Router v6.4', () => { op: 'navigation', origin: 'auto.navigation.react.reactrouterv6', tags: { 'routing.instrumentation': 'react-router-v6' }, - metadata: { source: 'url' }, + metadata: { source: 'route' }, + }); + }); + + it('works with parameterized paths and `basename`', () => { + const [mockStartTransaction] = createInstrumentation(); + const sentryCreateBrowserRouter = wrapCreateBrowserRouter(createMemoryRouter as CreateRouterFunction); + + const router = sentryCreateBrowserRouter( + [ + { + path: '/', + element: , + }, + { + path: ':orgId', + children: [ + { + path: 'users', + children: [ + { + path: ':userId', + element:
User
, + }, + ], + }, + ], + }, + ], + { + initialEntries: ['/admin'], + basename: '/admin', + }, + ); + + // @ts-expect-error router is fine + render(); + + expect(mockStartTransaction).toHaveBeenCalledTimes(2); + expect(mockStartTransaction).toHaveBeenLastCalledWith({ + name: '/admin/:orgId/users/:userId', + op: 'navigation', + origin: 'auto.navigation.react.reactrouterv6', + tags: { 'routing.instrumentation': 'react-router-v6' }, + metadata: { source: 'route' }, }); }); }); From 94c68e037f925de2a6aad2919ef6f2c0a61497d0 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 21 Sep 2023 09:23:15 +0200 Subject: [PATCH 05/15] ref(browser): Refactor browser integrations to use `processEvent` (#9022) This refactors browser integrations to use the new `processEvent` hook on the Integrations interface. It also updates Replay to register it's event processor on the client, not globally. This is also needed to ensure the order is somewhat stable, as global processors are run separately from the client ones. --- packages/browser/src/integrations/dedupe.ts | 44 +++++----- .../browser/src/integrations/httpcontext.ts | 47 ++++++----- packages/browser/src/profiling/integration.ts | 2 +- .../src/coreHandlers/handleGlobalEvent.ts | 81 ++++++++++--------- .../replay/src/util/addGlobalListeners.ts | 7 +- 5 files changed, 91 insertions(+), 90 deletions(-) diff --git a/packages/browser/src/integrations/dedupe.ts b/packages/browser/src/integrations/dedupe.ts index 673ded6484cb..c7a5cb5470b3 100644 --- a/packages/browser/src/integrations/dedupe.ts +++ b/packages/browser/src/integrations/dedupe.ts @@ -1,4 +1,4 @@ -import type { Event, EventProcessor, Exception, Hub, Integration, StackFrame } from '@sentry/types'; +import type { Event, Exception, Integration, StackFrame } from '@sentry/types'; import { logger } from '@sentry/utils'; /** Deduplication filter */ @@ -22,36 +22,30 @@ export class Dedupe implements Integration { this.name = Dedupe.id; } + /** @inheritDoc */ + public setupOnce(_addGlobaleventProcessor: unknown, _getCurrentHub: unknown): void { + // noop + } + /** * @inheritDoc */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { - const eventProcessor: EventProcessor = currentEvent => { - // We want to ignore any non-error type events, e.g. transactions or replays - // These should never be deduped, and also not be compared against as _previousEvent. - if (currentEvent.type) { - return currentEvent; - } + public processEvent(currentEvent: Event): Event | null { + // We want to ignore any non-error type events, e.g. transactions or replays + // These should never be deduped, and also not be compared against as _previousEvent. + if (currentEvent.type) { + return currentEvent; + } - const self = getCurrentHub().getIntegration(Dedupe); - if (self) { - // Juuust in case something goes wrong - try { - if (_shouldDropEvent(currentEvent, self._previousEvent)) { - __DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.'); - return null; - } - } catch (_oO) { - return (self._previousEvent = currentEvent); - } - - return (self._previousEvent = currentEvent); + // Juuust in case something goes wrong + try { + if (_shouldDropEvent(currentEvent, this._previousEvent)) { + __DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.'); + return null; } - return currentEvent; - }; + } catch (_oO) {} // eslint-disable-line no-empty - eventProcessor.id = this.name; - addGlobalEventProcessor(eventProcessor); + return (this._previousEvent = currentEvent); } } diff --git a/packages/browser/src/integrations/httpcontext.ts b/packages/browser/src/integrations/httpcontext.ts index f37963b46619..34e7029e504d 100644 --- a/packages/browser/src/integrations/httpcontext.ts +++ b/packages/browser/src/integrations/httpcontext.ts @@ -1,4 +1,3 @@ -import { addGlobalEventProcessor, getCurrentHub } from '@sentry/core'; import type { Event, Integration } from '@sentry/types'; import { WINDOW } from '../helpers'; @@ -23,28 +22,28 @@ export class HttpContext implements Integration { * @inheritDoc */ public setupOnce(): void { - addGlobalEventProcessor((event: Event) => { - if (getCurrentHub().getIntegration(HttpContext)) { - // if none of the information we want exists, don't bother - if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) { - return event; - } - - // grab as much info as exists and add it to the event - const url = (event.request && event.request.url) || (WINDOW.location && WINDOW.location.href); - const { referrer } = WINDOW.document || {}; - const { userAgent } = WINDOW.navigator || {}; - - const headers = { - ...(event.request && event.request.headers), - ...(referrer && { Referer: referrer }), - ...(userAgent && { 'User-Agent': userAgent }), - }; - const request = { ...event.request, ...(url && { url }), headers }; - - return { ...event, request }; - } - return event; - }); + // noop + } + + /** @inheritDoc */ + public preprocessEvent(event: Event): void { + // if none of the information we want exists, don't bother + if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) { + return; + } + + // grab as much info as exists and add it to the event + const url = (event.request && event.request.url) || (WINDOW.location && WINDOW.location.href); + const { referrer } = WINDOW.document || {}; + const { userAgent } = WINDOW.navigator || {}; + + const headers = { + ...(event.request && event.request.headers), + ...(referrer && { Referer: referrer }), + ...(userAgent && { 'User-Agent': userAgent }), + }; + const request = { ...event.request, ...(url && { url }), headers }; + + event.request = request; } } diff --git a/packages/browser/src/profiling/integration.ts b/packages/browser/src/profiling/integration.ts index 0d506b7493cd..dc7cb4d15120 100644 --- a/packages/browser/src/profiling/integration.ts +++ b/packages/browser/src/profiling/integration.ts @@ -35,7 +35,7 @@ export class BrowserProfilingIntegration implements Integration { /** * @inheritDoc */ - public setupOnce(addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { + public setupOnce(_addGlobalEventProcessor: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { this.getCurrentHub = getCurrentHub; const client = this.getCurrentHub().getClient() as BrowserClient; diff --git a/packages/replay/src/coreHandlers/handleGlobalEvent.ts b/packages/replay/src/coreHandlers/handleGlobalEvent.ts index 539845dc40fc..c2e134a86acb 100644 --- a/packages/replay/src/coreHandlers/handleGlobalEvent.ts +++ b/packages/replay/src/coreHandlers/handleGlobalEvent.ts @@ -16,51 +16,54 @@ export function handleGlobalEventListener( ): (event: Event, hint: EventHint) => Event | null { const afterSendHandler = includeAfterSendEventHandling ? handleAfterSendEvent(replay) : undefined; - return (event: Event, hint: EventHint) => { - // Do nothing if replay has been disabled - if (!replay.isEnabled()) { - return event; - } + return Object.assign( + (event: Event, hint: EventHint) => { + // Do nothing if replay has been disabled + if (!replay.isEnabled()) { + return event; + } - if (isReplayEvent(event)) { - // Replays have separate set of breadcrumbs, do not include breadcrumbs - // from core SDK - delete event.breadcrumbs; - return event; - } + if (isReplayEvent(event)) { + // Replays have separate set of breadcrumbs, do not include breadcrumbs + // from core SDK + delete event.breadcrumbs; + return event; + } - // We only want to handle errors & transactions, nothing else - if (!isErrorEvent(event) && !isTransactionEvent(event)) { - return event; - } + // We only want to handle errors & transactions, nothing else + if (!isErrorEvent(event) && !isTransactionEvent(event)) { + return event; + } - // Unless `captureExceptions` is enabled, we want to ignore errors coming from rrweb - // As there can be a bunch of stuff going wrong in internals there, that we don't want to bubble up to users - if (isRrwebError(event, hint) && !replay.getOptions()._experiments.captureExceptions) { - __DEBUG_BUILD__ && logger.log('[Replay] Ignoring error from rrweb internals', event); - return null; - } + // Unless `captureExceptions` is enabled, we want to ignore errors coming from rrweb + // As there can be a bunch of stuff going wrong in internals there, that we don't want to bubble up to users + if (isRrwebError(event, hint) && !replay.getOptions()._experiments.captureExceptions) { + __DEBUG_BUILD__ && logger.log('[Replay] Ignoring error from rrweb internals', event); + return null; + } - // When in buffer mode, we decide to sample here. - // Later, in `handleAfterSendEvent`, if the replayId is set, we know that we sampled - // And convert the buffer session to a full session - const isErrorEventSampled = shouldSampleForBufferEvent(replay, event); + // When in buffer mode, we decide to sample here. + // Later, in `handleAfterSendEvent`, if the replayId is set, we know that we sampled + // And convert the buffer session to a full session + const isErrorEventSampled = shouldSampleForBufferEvent(replay, event); - // Tag errors if it has been sampled in buffer mode, or if it is session mode - // Only tag transactions if in session mode - const shouldTagReplayId = isErrorEventSampled || replay.recordingMode === 'session'; + // Tag errors if it has been sampled in buffer mode, or if it is session mode + // Only tag transactions if in session mode + const shouldTagReplayId = isErrorEventSampled || replay.recordingMode === 'session'; - if (shouldTagReplayId) { - event.tags = { ...event.tags, replayId: replay.getSessionId() }; - } + if (shouldTagReplayId) { + event.tags = { ...event.tags, replayId: replay.getSessionId() }; + } - // In cases where a custom client is used that does not support the new hooks (yet), - // we manually call this hook method here - if (afterSendHandler) { - // Pretend the error had a 200 response so we always capture it - afterSendHandler(event, { statusCode: 200 }); - } + // In cases where a custom client is used that does not support the new hooks (yet), + // we manually call this hook method here + if (afterSendHandler) { + // Pretend the error had a 200 response so we always capture it + afterSendHandler(event, { statusCode: 200 }); + } - return event; - }; + return event; + }, + { id: 'Replay' }, + ); } diff --git a/packages/replay/src/util/addGlobalListeners.ts b/packages/replay/src/util/addGlobalListeners.ts index 6e73b270bb93..0948561f7852 100644 --- a/packages/replay/src/util/addGlobalListeners.ts +++ b/packages/replay/src/util/addGlobalListeners.ts @@ -26,7 +26,12 @@ export function addGlobalListeners(replay: ReplayContainer): void { // Tag all (non replay) events that get sent to Sentry with the current // replay ID so that we can reference them later in the UI - addGlobalEventProcessor(handleGlobalEventListener(replay, !hasHooks(client))); + const eventProcessor = handleGlobalEventListener(replay, !hasHooks(client)); + if (client && client.addEventProcessor) { + client.addEventProcessor(eventProcessor); + } else { + addGlobalEventProcessor(eventProcessor); + } // If a custom client has no hooks yet, we continue to use the "old" implementation if (hasHooks(client)) { From ef2ed6b92db7207017390c51928b2b0189677857 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Thu, 21 Sep 2023 14:00:51 +0200 Subject: [PATCH 06/15] docs: Fix comments describing different import styles in readme (#9081) --- packages/bun/README.md | 4 ++-- packages/node-experimental/README.md | 4 ++-- packages/node/README.md | 4 ++-- packages/vercel-edge/README.md | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/bun/README.md b/packages/bun/README.md index 170059f193f5..56c795793532 100644 --- a/packages/bun/README.md +++ b/packages/bun/README.md @@ -23,9 +23,9 @@ To use this SDK, call `init(options)` as early as possible in the main entry mod hook into the environment. Note that you can turn off almost all side effects using the respective options. ```javascript -// ES5 Syntax +// CJS Syntax const Sentry = require('@sentry/bun'); -// ES6 Syntax +// ESM Syntax import * as Sentry from '@sentry/bun'; Sentry.init({ diff --git a/packages/node-experimental/README.md b/packages/node-experimental/README.md index 461a04f28bfb..5bebaa336e17 100644 --- a/packages/node-experimental/README.md +++ b/packages/node-experimental/README.md @@ -30,9 +30,9 @@ yarn add @sentry/node-experimental ## Usage ```js -// ES5 Syntax +// CJS Syntax const Sentry = require('@sentry/node-experimental'); -// ES6 Syntax +// ESM Syntax import * as Sentry from '@sentry/node-experimental'; Sentry.init({ diff --git a/packages/node/README.md b/packages/node/README.md index e6ef857edc8a..cab92a553d25 100644 --- a/packages/node/README.md +++ b/packages/node/README.md @@ -21,9 +21,9 @@ To use this SDK, call `init(options)` as early as possible in the main entry mod hook into the environment. Note that you can turn off almost all side effects using the respective options. ```javascript -// ES5 Syntax +// CJS syntax const Sentry = require('@sentry/node'); -// ES6 Syntax +// ESM syntax import * as Sentry from '@sentry/node'; Sentry.init({ diff --git a/packages/vercel-edge/README.md b/packages/vercel-edge/README.md index d3e7849ffdab..e6e893bc5044 100644 --- a/packages/vercel-edge/README.md +++ b/packages/vercel-edge/README.md @@ -23,9 +23,9 @@ To use this SDK, call `init(options)` as early as possible in the main entry mod hook into the environment. Note that you can turn off almost all side effects using the respective options. ```javascript -// ES5 Syntax +// CJS Syntax const Sentry = require('@sentry/vercel-edge'); -// ES6 Syntax +// ESM Syntax import * as Sentry from '@sentry/vercel-edge'; Sentry.init({ From 685d3b25226aa27fb40eec269c2ee7e167232ff0 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 21 Sep 2023 09:58:23 -0400 Subject: [PATCH 07/15] chore: publish bun to release registry (#9073) --- .craft.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.craft.yml b/.craft.yml index 44efac4303c8..67ee97b3e411 100644 --- a/.craft.yml +++ b/.craft.yml @@ -176,3 +176,5 @@ targets: onlyIfPresent: /^sentry-sveltekit-\d.*\.tgz$/ 'npm:@sentry/opentelemetry-node': onlyIfPresent: /^sentry-opentelemetry-node-\d.*\.tgz$/ + 'npm:@sentry/bun': + onlyIfPresent: /^sentry-bun-\d.*\.tgz$/ From 8001498fa7682534ef7fb5c19875d2c39197ec6d Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 21 Sep 2023 11:44:23 -0400 Subject: [PATCH 08/15] feat(bun): Instrument Bun.serve (#9080) --- packages/bun/src/index.ts | 3 + packages/bun/src/integrations/bunserver.ts | 132 ++++++++++++++++++ packages/bun/src/integrations/index.ts | 1 + packages/bun/src/sdk.ts | 3 + packages/bun/test/helpers.ts | 14 ++ .../bun/test/integrations/bunserver.test.ts | 126 +++++++++++++++++ packages/bun/tsconfig.test.json | 2 +- 7 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 packages/bun/src/integrations/bunserver.ts create mode 100644 packages/bun/src/integrations/index.ts create mode 100644 packages/bun/test/helpers.ts create mode 100644 packages/bun/test/integrations/bunserver.test.ts diff --git a/packages/bun/src/index.ts b/packages/bun/src/index.ts index 7be879568dec..d1c4a69f0ae5 100644 --- a/packages/bun/src/index.ts +++ b/packages/bun/src/index.ts @@ -69,9 +69,12 @@ export { defaultIntegrations, init } from './sdk'; import { Integrations as CoreIntegrations } from '@sentry/core'; import { Integrations as NodeIntegrations } from '@sentry/node'; +import * as BunIntegrations from './integrations'; + const INTEGRATIONS = { ...CoreIntegrations, ...NodeIntegrations, + ...BunIntegrations, }; export { INTEGRATIONS as Integrations }; diff --git a/packages/bun/src/integrations/bunserver.ts b/packages/bun/src/integrations/bunserver.ts new file mode 100644 index 000000000000..915856f473db --- /dev/null +++ b/packages/bun/src/integrations/bunserver.ts @@ -0,0 +1,132 @@ +import { captureException, getCurrentHub, runWithAsyncContext, startSpan, Transaction } from '@sentry/core'; +import type { Integration } from '@sentry/types'; +import { addExceptionMechanism, getSanitizedUrlString, parseUrl, tracingContextFromHeaders } from '@sentry/utils'; + +function sendErrorToSentry(e: unknown): unknown { + captureException(e, scope => { + scope.addEventProcessor(event => { + addExceptionMechanism(event, { + type: 'bun', + handled: false, + data: { + function: 'serve', + }, + }); + return event; + }); + + return scope; + }); + + return e; +} + +/** + * Instruments `Bun.serve` to automatically create transactions and capture errors. + */ +export class BunServer implements Integration { + /** + * @inheritDoc + */ + public static id: string = 'BunServer'; + + /** + * @inheritDoc + */ + public name: string = BunServer.id; + + /** + * @inheritDoc + */ + public setupOnce(): void { + instrumentBunServe(); + } +} + +/** + * Instruments Bun.serve by patching it's options. + */ +export function instrumentBunServe(): void { + Bun.serve = new Proxy(Bun.serve, { + apply(serveTarget, serveThisArg, serveArgs: Parameters) { + instrumentBunServeOptions(serveArgs[0]); + return serveTarget.apply(serveThisArg, serveArgs); + }, + }); +} + +/** + * Instruments Bun.serve `fetch` option to automatically create spans and capture errors. + */ +function instrumentBunServeOptions(serveOptions: Parameters[0]): void { + serveOptions.fetch = new Proxy(serveOptions.fetch, { + apply(fetchTarget, fetchThisArg, fetchArgs: Parameters) { + return runWithAsyncContext(() => { + const hub = getCurrentHub(); + + const request = fetchArgs[0]; + const upperCaseMethod = request.method.toUpperCase(); + if (upperCaseMethod === 'OPTIONS' || upperCaseMethod === 'HEAD') { + return fetchTarget.apply(fetchThisArg, fetchArgs); + } + + const sentryTrace = request.headers.get('sentry-trace') || ''; + const baggage = request.headers.get('baggage'); + const { traceparentData, dynamicSamplingContext, propagationContext } = tracingContextFromHeaders( + sentryTrace, + baggage, + ); + hub.getScope().setPropagationContext(propagationContext); + + const parsedUrl = parseUrl(request.url); + const data: Record = { + 'http.request.method': request.method || 'GET', + }; + if (parsedUrl.search) { + data['http.query'] = parsedUrl.search; + } + + const url = getSanitizedUrlString(parsedUrl); + return startSpan( + { + op: 'http.server', + name: `${request.method} ${parsedUrl.path || '/'}`, + origin: 'auto.http.bun.serve', + ...traceparentData, + data, + metadata: { + source: 'url', + dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext, + request: { + url, + method: request.method, + headers: request.headers.toJSON(), + }, + }, + }, + async span => { + try { + const response = await (fetchTarget.apply(fetchThisArg, fetchArgs) as ReturnType< + typeof serveOptions.fetch + >); + if (response && response.status) { + span?.setHttpStatus(response.status); + span?.setData('http.response.status_code', response.status); + if (span instanceof Transaction) { + span.setContext('response', { + headers: response.headers.toJSON(), + status_code: response.status, + }); + } + } + return response; + } catch (e) { + sendErrorToSentry(e); + throw e; + } + }, + ); + }); + }, + }); +} diff --git a/packages/bun/src/integrations/index.ts b/packages/bun/src/integrations/index.ts new file mode 100644 index 000000000000..95d17cf80e66 --- /dev/null +++ b/packages/bun/src/integrations/index.ts @@ -0,0 +1 @@ +export { BunServer } from './bunserver'; diff --git a/packages/bun/src/sdk.ts b/packages/bun/src/sdk.ts index 11c7827b3faf..d512e7208bf5 100644 --- a/packages/bun/src/sdk.ts +++ b/packages/bun/src/sdk.ts @@ -3,6 +3,7 @@ import { Integrations as CoreIntegrations } from '@sentry/core'; import { init as initNode, Integrations as NodeIntegrations } from '@sentry/node'; import { BunClient } from './client'; +import { BunServer } from './integrations'; import { makeFetchTransport } from './transports'; import type { BunOptions } from './types'; @@ -25,6 +26,8 @@ export const defaultIntegrations = [ new NodeIntegrations.RequestData(), // Misc new NodeIntegrations.LinkedErrors(), + // Bun Specific + new BunServer(), ]; /** diff --git a/packages/bun/test/helpers.ts b/packages/bun/test/helpers.ts new file mode 100644 index 000000000000..32d4e4d716ac --- /dev/null +++ b/packages/bun/test/helpers.ts @@ -0,0 +1,14 @@ +import { createTransport } from '@sentry/core'; +import { resolvedSyncPromise } from '@sentry/utils'; + +import type { BunClientOptions } from '../src/types'; + +export function getDefaultBunClientOptions(options: Partial = {}): BunClientOptions { + return { + integrations: [], + transport: () => createTransport({ recordDroppedEvent: () => undefined }, _ => resolvedSyncPromise({})), + stackParser: () => [], + instrumenter: 'sentry', + ...options, + }; +} diff --git a/packages/bun/test/integrations/bunserver.test.ts b/packages/bun/test/integrations/bunserver.test.ts new file mode 100644 index 000000000000..23253c729590 --- /dev/null +++ b/packages/bun/test/integrations/bunserver.test.ts @@ -0,0 +1,126 @@ +import { Hub, makeMain } from '@sentry/core'; +// eslint-disable-next-line import/no-unresolved +import { beforeAll, beforeEach, describe, expect, test } from 'bun:test'; + +import { BunClient } from '../../src/client'; +import { instrumentBunServe } from '../../src/integrations/bunserver'; +import { getDefaultBunClientOptions } from '../helpers'; + +// Fun fact: Bun = 2 21 14 :) +const DEFAULT_PORT = 22114; + +describe('Bun Serve Integration', () => { + let hub: Hub; + let client: BunClient; + + beforeAll(() => { + instrumentBunServe(); + }); + + beforeEach(() => { + const options = getDefaultBunClientOptions({ tracesSampleRate: 1, debug: true }); + client = new BunClient(options); + hub = new Hub(client); + makeMain(hub); + }); + + test('generates a transaction around a request', async () => { + client.on('finishTransaction', transaction => { + expect(transaction.status).toBe('ok'); + expect(transaction.tags).toEqual({ + 'http.status_code': '200', + }); + expect(transaction.op).toEqual('http.server'); + expect(transaction.name).toEqual('GET /'); + }); + + const server = Bun.serve({ + async fetch(_req) { + return new Response('Bun!'); + }, + port: DEFAULT_PORT, + }); + + await fetch('http://localhost:22114/'); + + server.stop(); + }); + + test('generates a post transaction', async () => { + client.on('finishTransaction', transaction => { + expect(transaction.status).toBe('ok'); + expect(transaction.tags).toEqual({ + 'http.status_code': '200', + }); + expect(transaction.op).toEqual('http.server'); + expect(transaction.name).toEqual('POST /'); + }); + + const server = Bun.serve({ + async fetch(_req) { + return new Response('Bun!'); + }, + port: DEFAULT_PORT, + }); + + await fetch('http://localhost:22114/', { + method: 'POST', + }); + + server.stop(); + }); + + test('continues a trace', async () => { + const TRACE_ID = '12312012123120121231201212312012'; + const PARENT_SPAN_ID = '1121201211212012'; + const PARENT_SAMPLED = '1'; + + const SENTRY_TRACE_HEADER = `${TRACE_ID}-${PARENT_SPAN_ID}-${PARENT_SAMPLED}`; + const SENTRY_BAGGAGE_HEADER = 'sentry-version=1.0,sentry-environment=production'; + + client.on('finishTransaction', transaction => { + expect(transaction.traceId).toBe(TRACE_ID); + expect(transaction.parentSpanId).toBe(PARENT_SPAN_ID); + expect(transaction.sampled).toBe(true); + + expect(transaction.metadata?.dynamicSamplingContext).toStrictEqual({ version: '1.0', environment: 'production' }); + }); + + const server = Bun.serve({ + async fetch(_req) { + return new Response('Bun!'); + }, + port: DEFAULT_PORT, + }); + + await fetch('http://localhost:22114/', { + headers: { 'sentry-trace': SENTRY_TRACE_HEADER, baggage: SENTRY_BAGGAGE_HEADER }, + }); + + server.stop(); + }); + + test('does not create transactions for OPTIONS or HEAD requests', async () => { + client.on('finishTransaction', () => { + // This will never run, but we want to make sure it doesn't run. + expect(false).toEqual(true); + }); + + const server = Bun.serve({ + async fetch(_req) { + return new Response('Bun!'); + }, + port: DEFAULT_PORT, + }); + + await fetch('http://localhost:22114/', { + method: 'OPTIONS', + }); + + await fetch('http://localhost:22114/', { + method: 'HEAD', + }); + + server.stop(); + }); +}); diff --git a/packages/bun/tsconfig.test.json b/packages/bun/tsconfig.test.json index 87f6afa06b86..e5d8bb0fb535 100644 --- a/packages/bun/tsconfig.test.json +++ b/packages/bun/tsconfig.test.json @@ -5,7 +5,7 @@ "compilerOptions": { // should include all types from `./tsconfig.json` plus types for all test frameworks used - "types": ["node", "jest"] + "types": ["bun-types", "jest"] // other package-specific, test-specific options } From 1f8de57df02408273d4d270d1494fd3e7b5f67d2 Mon Sep 17 00:00:00 2001 From: Jorrit Schippers Date: Thu, 21 Sep 2023 18:55:19 +0200 Subject: [PATCH 09/15] fix(react): Add actual error name to boundary error name (#9065) Previously, the error name would always be `React ErrorBoundary Error`, because `errorBoundaryError.name` refers to the name of the Error object that was just created. --- packages/react/src/errorboundary.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/errorboundary.tsx b/packages/react/src/errorboundary.tsx index 3d894fc699a8..66006b06d7b6 100644 --- a/packages/react/src/errorboundary.tsx +++ b/packages/react/src/errorboundary.tsx @@ -128,7 +128,7 @@ class ErrorBoundary extends React.Component Date: Thu, 21 Sep 2023 17:16:00 +0000 Subject: [PATCH 10/15] build(deps): bump graphql from 16.3.0 to 16.8.1 Bumps [graphql](https://github.com/graphql/graphql-js) from 16.3.0 to 16.8.1. - [Release notes](https://github.com/graphql/graphql-js/releases) - [Commits](https://github.com/graphql/graphql-js/compare/v16.3.0...v16.8.1) --- updated-dependencies: - dependency-name: graphql dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 94290bdb6a55..774b6abcc4dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15076,9 +15076,9 @@ graphql-tag@^2.11.0: tslib "^2.1.0" graphql@^16.3.0: - version "16.3.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05" - integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A== + version "16.8.1" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" + integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== graphviz@0.0.9: version "0.0.9" From d94e72a11977142b113befe528068ff86db793b8 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 22 Sep 2023 08:12:37 +0200 Subject: [PATCH 11/15] ref(node-experimental): Reorder files into `opentelemetry` folder (#9084) To keep things better together, and in preparation for follow up PRs with more OTEL-specific stuff. Nothing functionally changes here, this is just to keep follow up PRs more readable as there is a lot going on... --- packages/node-experimental/src/constants.ts | 3 +++ .../contextManager.ts} | 6 ++---- packages/node-experimental/src/sdk/initOtel.ts | 2 +- .../node-experimental/src/sdk/otelAsyncContextStrategy.ts | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 packages/node-experimental/src/constants.ts rename packages/node-experimental/src/{sdk/otelContextManager.ts => opentelemetry/contextManager.ts} (91%) diff --git a/packages/node-experimental/src/constants.ts b/packages/node-experimental/src/constants.ts new file mode 100644 index 000000000000..dc714590556a --- /dev/null +++ b/packages/node-experimental/src/constants.ts @@ -0,0 +1,3 @@ +import { createContextKey } from '@opentelemetry/api'; + +export const OTEL_CONTEXT_HUB_KEY = createContextKey('sentry_hub'); diff --git a/packages/node-experimental/src/sdk/otelContextManager.ts b/packages/node-experimental/src/opentelemetry/contextManager.ts similarity index 91% rename from packages/node-experimental/src/sdk/otelContextManager.ts rename to packages/node-experimental/src/opentelemetry/contextManager.ts index c8eadfb85f65..438a2c49fac7 100644 --- a/packages/node-experimental/src/sdk/otelContextManager.ts +++ b/packages/node-experimental/src/opentelemetry/contextManager.ts @@ -1,11 +1,9 @@ import type { Context } from '@opentelemetry/api'; -import * as api from '@opentelemetry/api'; import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks'; import type { Carrier, Hub } from '@sentry/core'; -import { ensureHubOnCarrier, getCurrentHub, getHubFromCarrier } from './hub'; - -export const OTEL_CONTEXT_HUB_KEY = api.createContextKey('sentry_hub'); +import { OTEL_CONTEXT_HUB_KEY } from '../constants'; +import { ensureHubOnCarrier, getCurrentHub, getHubFromCarrier } from './../sdk/hub'; function createNewHub(parent: Hub | undefined): Hub { const carrier: Carrier = {}; diff --git a/packages/node-experimental/src/sdk/initOtel.ts b/packages/node-experimental/src/sdk/initOtel.ts index eaa5937b1ddb..b58eec81880e 100644 --- a/packages/node-experimental/src/sdk/initOtel.ts +++ b/packages/node-experimental/src/sdk/initOtel.ts @@ -5,7 +5,7 @@ import { SentryPropagator, SentrySpanProcessor } from '@sentry/opentelemetry-nod import { logger } from '@sentry/utils'; import type { NodeExperimentalClient } from '../types'; -import { SentryContextManager } from './otelContextManager'; +import { SentryContextManager } from './../opentelemetry/contextManager'; /** * Initialize OpenTelemetry for Node. diff --git a/packages/node-experimental/src/sdk/otelAsyncContextStrategy.ts b/packages/node-experimental/src/sdk/otelAsyncContextStrategy.ts index 455dc4717422..7e4ca5cd4da0 100644 --- a/packages/node-experimental/src/sdk/otelAsyncContextStrategy.ts +++ b/packages/node-experimental/src/sdk/otelAsyncContextStrategy.ts @@ -2,7 +2,7 @@ import * as api from '@opentelemetry/api'; import type { Hub, RunWithAsyncContextOptions } from '@sentry/core'; import { setAsyncContextStrategy } from '@sentry/core'; -import { OTEL_CONTEXT_HUB_KEY } from './otelContextManager'; +import { OTEL_CONTEXT_HUB_KEY } from '../constants'; /** * Sets the async context strategy to use follow the OTEL context under the hood. From 0532541680170e0463779d7bc6d7a772b9ab61a1 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Fri, 22 Sep 2023 15:28:29 -0400 Subject: [PATCH 12/15] chore: Publish @sentry/vercel-edge to release registry (#9074) --- .craft.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.craft.yml b/.craft.yml index 67ee97b3e411..5efdae48aa01 100644 --- a/.craft.yml +++ b/.craft.yml @@ -178,3 +178,5 @@ targets: onlyIfPresent: /^sentry-opentelemetry-node-\d.*\.tgz$/ 'npm:@sentry/bun': onlyIfPresent: /^sentry-bun-\d.*\.tgz$/ + 'npm:@sentry/vercel-edge': + onlyIfPresent: /^sentry-vercel-edge-\d.*\.tgz$/ From 705be9baee79660c66d7c722c8d0693a0a3c84f1 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Mon, 25 Sep 2023 12:48:01 +0200 Subject: [PATCH 13/15] ref(opentelemetry-node): Extract `maybeCaptureExceptionForTimedEvent` (#9099) Also add tests for this. This can then be reused e.g. by node-experimental in a later step. --- .../opentelemetry-node/src/spanprocessor.ts | 43 +---- .../utils/captureExceptionForTimedEvent.ts | 55 +++++++ .../captureExceptionForTimedEvent.test.ts | 147 ++++++++++++++++++ 3 files changed, 206 insertions(+), 39 deletions(-) create mode 100644 packages/opentelemetry-node/src/utils/captureExceptionForTimedEvent.ts create mode 100644 packages/opentelemetry-node/test/utils/captureExceptionForTimedEvent.test.ts diff --git a/packages/opentelemetry-node/src/spanprocessor.ts b/packages/opentelemetry-node/src/spanprocessor.ts index 7adc0ee31e5f..5a0b47358ed2 100644 --- a/packages/opentelemetry-node/src/spanprocessor.ts +++ b/packages/opentelemetry-node/src/spanprocessor.ts @@ -1,12 +1,12 @@ import type { Context } from '@opentelemetry/api'; import { SpanKind, trace } from '@opentelemetry/api'; import type { Span as OtelSpan, SpanProcessor as OtelSpanProcessor } from '@opentelemetry/sdk-trace-base'; -import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import { addGlobalEventProcessor, addTracingExtensions, getCurrentHub, Transaction } from '@sentry/core'; import type { DynamicSamplingContext, Span as SentrySpan, TraceparentData, TransactionContext } from '@sentry/types'; -import { isString, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; import { SENTRY_DYNAMIC_SAMPLING_CONTEXT_KEY, SENTRY_TRACE_PARENT_CONTEXT_KEY } from './constants'; +import { maybeCaptureExceptionForTimedEvent } from './utils/captureExceptionForTimedEvent'; import { isSentryRequestSpan } from './utils/isSentryRequest'; import { mapOtelStatus } from './utils/mapOtelStatus'; import { parseSpanDescription } from './utils/parseOtelSpanDescription'; @@ -109,44 +109,9 @@ export class SentrySpanProcessor implements OtelSpanProcessor { return; } + const hub = getCurrentHub(); otelSpan.events.forEach(event => { - if (event.name !== 'exception') { - return; - } - - const attributes = event.attributes; - if (!attributes) { - return; - } - - const message = attributes[SemanticAttributes.EXCEPTION_MESSAGE]; - const syntheticError = new Error(message as string | undefined); - - const stack = attributes[SemanticAttributes.EXCEPTION_STACKTRACE]; - if (isString(stack)) { - syntheticError.stack = stack; - } - - const type = attributes[SemanticAttributes.EXCEPTION_TYPE]; - if (isString(type)) { - syntheticError.name = type; - } - - getCurrentHub().captureException(syntheticError, { - captureContext: { - contexts: { - otel: { - attributes: otelSpan.attributes, - resource: otelSpan.resource.attributes, - }, - trace: { - trace_id: otelSpan.spanContext().traceId, - span_id: otelSpan.spanContext().spanId, - parent_span_id: otelSpan.parentSpanId, - }, - }, - }, - }); + maybeCaptureExceptionForTimedEvent(hub, event, otelSpan); }); if (sentrySpan instanceof Transaction) { diff --git a/packages/opentelemetry-node/src/utils/captureExceptionForTimedEvent.ts b/packages/opentelemetry-node/src/utils/captureExceptionForTimedEvent.ts new file mode 100644 index 000000000000..3dde27e49e9f --- /dev/null +++ b/packages/opentelemetry-node/src/utils/captureExceptionForTimedEvent.ts @@ -0,0 +1,55 @@ +import type { Span as OtelSpan, TimedEvent } from '@opentelemetry/sdk-trace-base'; +import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import type { Hub } from '@sentry/types'; +import { isString } from '@sentry/utils'; + +/** + * Maybe capture a Sentry exception for an OTEL timed event. + * This will check if the event is exception-like and in that case capture it as an exception. + */ +export function maybeCaptureExceptionForTimedEvent(hub: Hub, event: TimedEvent, otelSpan?: OtelSpan): void { + if (event.name !== 'exception') { + return; + } + + const attributes = event.attributes; + if (!attributes) { + return; + } + + const message = attributes[SemanticAttributes.EXCEPTION_MESSAGE]; + + if (typeof message !== 'string') { + return; + } + + const syntheticError = new Error(message); + + const stack = attributes[SemanticAttributes.EXCEPTION_STACKTRACE]; + if (isString(stack)) { + syntheticError.stack = stack; + } + + const type = attributes[SemanticAttributes.EXCEPTION_TYPE]; + if (isString(type)) { + syntheticError.name = type; + } + + hub.captureException(syntheticError, { + captureContext: otelSpan + ? { + contexts: { + otel: { + attributes: otelSpan.attributes, + resource: otelSpan.resource.attributes, + }, + trace: { + trace_id: otelSpan.spanContext().traceId, + span_id: otelSpan.spanContext().spanId, + parent_span_id: otelSpan.parentSpanId, + }, + }, + } + : undefined, + }); +} diff --git a/packages/opentelemetry-node/test/utils/captureExceptionForTimedEvent.test.ts b/packages/opentelemetry-node/test/utils/captureExceptionForTimedEvent.test.ts new file mode 100644 index 000000000000..4d0c39b3a8b9 --- /dev/null +++ b/packages/opentelemetry-node/test/utils/captureExceptionForTimedEvent.test.ts @@ -0,0 +1,147 @@ +import type { Span as OtelSpan, TimedEvent } from '@opentelemetry/sdk-trace-base'; +import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import type { Hub } from '@sentry/types'; + +import { maybeCaptureExceptionForTimedEvent } from '../../src/utils/captureExceptionForTimedEvent'; + +describe('maybeCaptureExceptionForTimedEvent', () => { + it('ignores non-exception events', async () => { + const event: TimedEvent = { + time: [12345, 0], + name: 'test event', + }; + + const captureException = jest.fn(); + const hub = { + captureException, + } as unknown as Hub; + + maybeCaptureExceptionForTimedEvent(hub, event); + + expect(captureException).not.toHaveBeenCalled(); + }); + + it('ignores exception events without EXCEPTION_MESSAGE', async () => { + const event: TimedEvent = { + time: [12345, 0], + name: 'exception', + }; + + const captureException = jest.fn(); + const hub = { + captureException, + } as unknown as Hub; + + maybeCaptureExceptionForTimedEvent(hub, event); + + expect(captureException).not.toHaveBeenCalled(); + }); + + it('captures exception from event with EXCEPTION_MESSAGE', async () => { + const event: TimedEvent = { + time: [12345, 0], + name: 'exception', + attributes: { + [SemanticAttributes.EXCEPTION_MESSAGE]: 'test-message', + }, + }; + + const captureException = jest.fn(); + const hub = { + captureException, + } as unknown as Hub; + + maybeCaptureExceptionForTimedEvent(hub, event); + + expect(captureException).toHaveBeenCalledTimes(1); + expect(captureException).toHaveBeenCalledWith(expect.objectContaining({ message: 'test-message' }), { + captureContext: undefined, + }); + expect(captureException).toHaveBeenCalledWith(expect.any(Error), { + captureContext: undefined, + }); + }); + + it('captures stack and type, if available', async () => { + const event: TimedEvent = { + time: [12345, 0], + name: 'exception', + attributes: { + [SemanticAttributes.EXCEPTION_MESSAGE]: 'test-message', + [SemanticAttributes.EXCEPTION_STACKTRACE]: 'test-stack', + [SemanticAttributes.EXCEPTION_TYPE]: 'test-type', + }, + }; + + const captureException = jest.fn(); + const hub = { + captureException, + } as unknown as Hub; + + maybeCaptureExceptionForTimedEvent(hub, event); + + expect(captureException).toHaveBeenCalledTimes(1); + expect(captureException).toHaveBeenCalledWith( + expect.objectContaining({ message: 'test-message', name: 'test-type', stack: 'test-stack' }), + { + captureContext: undefined, + }, + ); + expect(captureException).toHaveBeenCalledWith(expect.any(Error), { + captureContext: undefined, + }); + }); + + it('captures span context, if available', async () => { + const event: TimedEvent = { + time: [12345, 0], + name: 'exception', + attributes: { + [SemanticAttributes.EXCEPTION_MESSAGE]: 'test-message', + }, + }; + + const span = { + parentSpanId: 'test-parent-span-id', + attributes: { + 'test-attr1': 'test-value1', + }, + resource: { + attributes: { + 'test-attr2': 'test-value2', + }, + }, + spanContext: () => { + return { spanId: 'test-span-id', traceId: 'test-trace-id' }; + }, + } as unknown as OtelSpan; + + const captureException = jest.fn(); + const hub = { + captureException, + } as unknown as Hub; + + maybeCaptureExceptionForTimedEvent(hub, event, span); + + expect(captureException).toHaveBeenCalledTimes(1); + expect(captureException).toHaveBeenCalledWith(expect.objectContaining({ message: 'test-message' }), { + captureContext: { + contexts: { + otel: { + attributes: { + 'test-attr1': 'test-value1', + }, + resource: { + 'test-attr2': 'test-value2', + }, + }, + trace: { + trace_id: 'test-trace-id', + span_id: 'test-span-id', + parent_span_id: 'test-parent-span-id', + }, + }, + }, + }); + }); +}); From 622186ceddb98fd786c06775f22e3e15b1e2b959 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 25 Sep 2023 13:33:20 +0200 Subject: [PATCH 14/15] fix(nextjs): Use webpack module paths to attempt to resolve internal request async storage module (#9100) --- .../src/config/loaders/wrappingLoader.ts | 29 ++----------------- packages/nextjs/src/config/types.ts | 1 + packages/nextjs/src/config/webpack.ts | 29 +++++++++++++++++++ 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/packages/nextjs/src/config/loaders/wrappingLoader.ts b/packages/nextjs/src/config/loaders/wrappingLoader.ts index ebeb6c90294b..7fc882794e5c 100644 --- a/packages/nextjs/src/config/loaders/wrappingLoader.ts +++ b/packages/nextjs/src/config/loaders/wrappingLoader.ts @@ -15,9 +15,6 @@ const SENTRY_WRAPPER_MODULE_NAME = 'sentry-wrapper-module'; // Needs to end in .cjs in order for the `commonjs` plugin to pick it up const WRAPPING_TARGET_MODULE_NAME = '__SENTRY_WRAPPING_TARGET_FILE__.cjs'; -// This module is non-public API and may break -const nextjsRequestAsyncStorageModulePath = getRequestAsyncLocalStorageModule(); - const apiWrapperTemplatePath = path.resolve(__dirname, '..', 'templates', 'apiWrapperTemplate.js'); const apiWrapperTemplateCode = fs.readFileSync(apiWrapperTemplatePath, { encoding: 'utf8' }); @@ -51,32 +48,9 @@ type LoaderOptions = { wrappingTargetKind: 'page' | 'api-route' | 'middleware' | 'server-component' | 'sentry-init' | 'route-handler'; sentryConfigFilePath?: string; vercelCronsConfig?: VercelCronsConfig; + nextjsRequestAsyncStorageModulePath?: string; }; -function getRequestAsyncLocalStorageModule(): string | undefined { - try { - // Original location of that module - // https://github.com/vercel/next.js/blob/46151dd68b417e7850146d00354f89930d10b43b/packages/next/src/client/components/request-async-storage.ts - const location = 'next/dist/client/components/request-async-storage'; - require.resolve(location); - return location; - } catch { - // noop - } - - try { - // Introduced in Next.js 13.4.20 - // https://github.com/vercel/next.js/blob/e1bc270830f2fc2df3542d4ef4c61b916c802df3/packages/next/src/client/components/request-async-storage.external.ts - const location = 'next/dist/client/components/request-async-storage.external'; - require.resolve(location); - return location; - } catch { - // noop - } - - return undefined; -} - /** * Replace the loaded file with a wrapped version the original file. In the wrapped version, the original file is loaded, * any data-fetching functions (`getInitialProps`, `getStaticProps`, and `getServerSideProps`) or API routes it contains @@ -98,6 +72,7 @@ export default function wrappingLoader( wrappingTargetKind, sentryConfigFilePath, vercelCronsConfig, + nextjsRequestAsyncStorageModulePath, } = 'getOptions' in this ? this.getOptions() : this.query; this.async(); diff --git a/packages/nextjs/src/config/types.ts b/packages/nextjs/src/config/types.ts index cd82a3290c1e..7b439a3c5d44 100644 --- a/packages/nextjs/src/config/types.ts +++ b/packages/nextjs/src/config/types.ts @@ -163,6 +163,7 @@ export type WebpackConfigObject = { target: string; context: string; resolve?: { + modules?: string[]; alias?: { [key: string]: string | boolean }; }; module?: { diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 5ca49b798aca..dc8a77a4494c 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -126,6 +126,7 @@ export function constructWebpackConfigFunction( pageExtensionRegex, excludeServerRoutes: userSentryOptions.excludeServerRoutes, sentryConfigFilePath: getUserConfigFilePath(projectDir, runtime), + nextjsRequestAsyncStorageModulePath: getRequestAsyncLocalStorageModuleLocation(rawNewConfig.resolve?.modules), }; const normalizeLoaderResourcePath = (resourcePath: string): string => { @@ -975,3 +976,31 @@ function addValueInjectionLoader( }, ); } + +function getRequestAsyncLocalStorageModuleLocation(modules: string[] | undefined): string | undefined { + if (modules === undefined) { + return undefined; + } + + try { + // Original location of that module + // https://github.com/vercel/next.js/blob/46151dd68b417e7850146d00354f89930d10b43b/packages/next/src/client/components/request-async-storage.ts + const location = 'next/dist/client/components/request-async-storage'; + require.resolve(location, { paths: modules }); + return location; + } catch { + // noop + } + + try { + // Introduced in Next.js 13.4.20 + // https://github.com/vercel/next.js/blob/e1bc270830f2fc2df3542d4ef4c61b916c802df3/packages/next/src/client/components/request-async-storage.external.ts + const location = 'next/dist/client/components/request-async-storage.external'; + require.resolve(location, { paths: modules }); + return location; + } catch { + // noop + } + + return undefined; +} From 90b0c1f5819302e780ff798c7974b7e48bb7b1d1 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 25 Sep 2023 14:03:31 +0200 Subject: [PATCH 15/15] meta(changelog): Update changelog for 7.71.0 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 819c17ef6f5a..724c0730ee83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ - "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott +## 7.71.0 + +- feat(bun): Instrument Bun.serve (#9080) +- fix(core): Ensure global event processors are always applied to event (#9064) +- fix(core): Run client eventProcessors before global ones (#9032) +- fix(nextjs): Use webpack module paths to attempt to resolve internal request async storage module (#9100) +- fix(react): Add actual error name to boundary error name (#9065) +- fix(react): Compare location against `basename`-prefixed route. (#9076) +- ref(browser): Refactor browser integrations to use `processEvent` (#9022) + +Work in this release contributed by @jorrit. Thank you for your contribution! + ## 7.70.0 ### Important Changes