diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 751279cde693..24f3e5e9e330 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -92,6 +92,7 @@ export { inboundFiltersIntegration } from './integrations/inboundfilters'; export { linkedErrorsIntegration } from './integrations/linkederrors'; export { moduleMetadataIntegration } from './integrations/metadata'; export { requestDataIntegration } from './integrations/requestdata'; +export { serverRequestSessionIntegration } from './integrations/serverrequestsession'; export { captureConsoleIntegration } from './integrations/captureconsole'; // eslint-disable-next-line deprecation/deprecation export { debugIntegration } from './integrations/debug'; diff --git a/packages/core/src/integrations/serverrequestsession.ts b/packages/core/src/integrations/serverrequestsession.ts new file mode 100644 index 000000000000..e03b2f4b465f --- /dev/null +++ b/packages/core/src/integrations/serverrequestsession.ts @@ -0,0 +1,29 @@ +import { getIsolationScope } from '../currentScopes'; +import { startSession } from '../exports'; +import { defineIntegration } from '../integration'; + +export const serverRequestSessionIntegration = defineIntegration(() => { + return { + name: 'ServerRequestSession', + setup(client) { + client.on('preprocessEvent', event => { + const isException = + event.type === undefined && event.exception && event.exception.values && event.exception.values.length > 0; + + // If the event is of type Exception, then a request session should be captured + if (isException) { + const requestSession = getIsolationScope().getRequestSession(); + + // Ensure that this is happening within the bounds of a request, and make sure not to override + // Session Status if Errored / Crashed + if (requestSession && requestSession.status === 'ok') { + requestSession.status = 'errored'; + } + } + }); + + // TODO(v9): Remove this start session call + startSession(); + }, + }; +}); diff --git a/packages/core/src/server-runtime-client.ts b/packages/core/src/server-runtime-client.ts index 5435d5c8fff0..211f680bdbc7 100644 --- a/packages/core/src/server-runtime-client.ts +++ b/packages/core/src/server-runtime-client.ts @@ -134,11 +134,11 @@ export class ServerRuntimeClient< return super.close(timeout); } - /** Method that initialises an instance of SessionFlusher on Client */ + /** Method that initializes an instance of SessionFlusher on Client */ public initSessionFlusher(): void { const { release, environment } = this._options; if (!release) { - DEBUG_BUILD && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); + DEBUG_BUILD && logger.warn('Cannot initialize an instance of SessionFlusher if no release is provided!'); } else { this._sessionFlusher = new SessionFlusher(this, { release, diff --git a/packages/node/src/sdk/index.ts b/packages/node/src/sdk/index.ts index 1104386fb2ca..10d89f763499 100644 --- a/packages/node/src/sdk/index.ts +++ b/packages/node/src/sdk/index.ts @@ -4,7 +4,6 @@ import { dropUndefinedKeys, endSession, functionToStringIntegration, - getClient, getCurrentScope, getIntegrationsToSetup, getIsolationScope, @@ -14,8 +13,8 @@ import { logger, propagationContextFromHeaders, requestDataIntegration, + serverRequestSessionIntegration, stackParserFromStackParserOptions, - startSession, } from '@sentry/core'; import { enhanceDscWithOpenTelemetryRootSpanName, @@ -76,7 +75,7 @@ export function getDefaultIntegrationsWithoutPerformance(): Integration[] { /** Get the default integrations for the Node SDK. */ export function getDefaultIntegrations(options: Options): Integration[] { - return [ + const integrations = [ ...getDefaultIntegrationsWithoutPerformance(), // We only add performance integrations if tracing is enabled // Note that this means that without tracing enabled, e.g. `expressIntegration()` will not be added @@ -84,6 +83,13 @@ export function getDefaultIntegrations(options: Options): Integration[] { // But `transactionName` will not be set automatically ...(shouldAddPerformanceIntegrations(options) ? getAutoPerformanceIntegrations() : []), ]; + + // TODO(v9): Make this a default default integration + if (options.autoSessionTracking) { + integrations.push(serverRequestSessionIntegration()); + } + + return integrations; } function shouldAddPerformanceIntegrations(options: Options): boolean { @@ -156,8 +162,9 @@ function _init( logger.log(`Running in ${isCjs() ? 'CommonJS' : 'ESM'} mode.`); + // TODO(V9): Unconditionally call startSessionTracking if (options.autoSessionTracking) { - startSessionTracking(); + startSessionTracking(client); } client.startClientReportTracking(); @@ -308,17 +315,11 @@ function updateScopeFromEnvVariables(): void { getCurrentScope().setPropagationContext(propagationContext); } } - /** * Enable automatic Session Tracking for the node process. */ -function startSessionTracking(): void { - const client = getClient(); - if (client && client.getOptions().autoSessionTracking) { - client.initSessionFlusher(); - } - - startSession(); +function startSessionTracking(client: NodeClient): void { + client.initSessionFlusher(); // Emitted in the case of healthy sessions, error of `mechanism.handled: true` and unhandledrejections because // The 'beforeExit' event is not emitted for conditions causing explicit termination,