Skip to content

Commit 117a3b4

Browse files
author
Luca Forstner
authored
feat(node)!: Collect request sessions via HTTP instrumentation (getsentry#14658)
1 parent 6d006bf commit 117a3b4

File tree

25 files changed

+366
-1060
lines changed

25 files changed

+366
-1060
lines changed

.size-limit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ module.exports = [
1515
path: 'packages/browser/build/npm/esm/index.js',
1616
import: createImport('init'),
1717
gzip: true,
18-
limit: '24 KB',
18+
limit: '24.1 KB',
1919
modifyWebpackConfig: function (config) {
2020
const webpack = require('webpack');
2121
const TerserPlugin = require('terser-webpack-plugin');

dev-packages/node-integration-tests/suites/sessions/server.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
11
import { loggingTransport } from '@sentry-internal/node-integration-tests';
2-
import type { SessionFlusher } from '@sentry/core';
32
import * as Sentry from '@sentry/node';
43

54
Sentry.init({
65
dsn: 'https://[email protected]/1337',
76
release: '1.0',
87
transport: loggingTransport,
8+
integrations: [
9+
Sentry.httpIntegration({
10+
// Flush after 2 seconds (to avoid waiting for the default 60s)
11+
sessionFlushingDelayMS: 2_000,
12+
}),
13+
],
914
});
1015

1116
import { startExpressServerAndSendPortToRunner } from '@sentry-internal/node-integration-tests';
1217
import express from 'express';
1318

1419
const app = express();
1520

16-
// eslint-disable-next-line deprecation/deprecation
17-
const flusher = (Sentry.getClient() as Sentry.NodeClient)['_sessionFlusher'] as SessionFlusher;
18-
19-
// Flush after 2 seconds (to avoid waiting for the default 60s)
20-
setTimeout(() => {
21-
flusher?.flush();
22-
}, 2000);
23-
2421
app.get('/test/success', (_req, res) => {
2522
res.send('Success!');
2623
});

docs/migration/v8-to-v9.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ The Sentry metrics beta has ended and the metrics API has been removed from the
218218
- Deprecated `RequestSessionStatus` type. No replacements.
219219
- Deprecated `SessionFlusherLike` type. No replacements.
220220
- Deprecated `SessionFlusher`. No replacements.
221+
- Deprecated `initSessionFlusher` on `ServerRuntimeClient`. No replacements. The `httpIntegration` will flush sessions by itself.
221222

222223
## `@sentry/nestjs`
223224

packages/core/src/baseclient.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import type {
3232
} from './types-hoist';
3333

3434
import { getEnvelopeEndpointWithUrlEncodedAuth } from './api';
35+
import { DEFAULT_ENVIRONMENT } from './constants';
3536
import { getCurrentScope, getIsolationScope, getTraceContextFromScope } from './currentScopes';
3637
import { DEBUG_BUILD } from './debug-build';
3738
import { createEventEnvelope, createSessionEnvelope } from './envelope';
@@ -55,6 +56,7 @@ import { prepareEvent } from './utils/prepareEvent';
5556
import { showSpanDropWarning } from './utils/spanUtils';
5657

5758
const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been captured.";
59+
const MISSING_RELEASE_FOR_SESSION_ERROR = 'Discarded session because of missing or non-string release';
5860

5961
/**
6062
* Base implementation for all JavaScript SDK clients.
@@ -236,13 +238,9 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
236238
* @inheritDoc
237239
*/
238240
public captureSession(session: Session): void {
239-
if (!(typeof session.release === 'string')) {
240-
DEBUG_BUILD && logger.warn('Discarded session because of missing or non-string release');
241-
} else {
242-
this.sendSession(session);
243-
// After sending, we set init false to indicate it's not the first occurrence
244-
updateSession(session, { init: false });
245-
}
241+
this.sendSession(session);
242+
// After sending, we set init false to indicate it's not the first occurrence
243+
updateSession(session, { init: false });
246244
}
247245

248246
/**
@@ -371,6 +369,25 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
371369
* @inheritDoc
372370
*/
373371
public sendSession(session: Session | SessionAggregates): void {
372+
// Backfill release and environment on session
373+
const { release: clientReleaseOption, environment: clientEnvironmentOption = DEFAULT_ENVIRONMENT } = this._options;
374+
if ('aggregates' in session) {
375+
const sessionAttrs = session.attrs || {};
376+
if (!sessionAttrs.release && !clientReleaseOption) {
377+
DEBUG_BUILD && logger.warn(MISSING_RELEASE_FOR_SESSION_ERROR);
378+
return;
379+
}
380+
sessionAttrs.release = sessionAttrs.release || clientReleaseOption;
381+
sessionAttrs.environment = sessionAttrs.environment || clientEnvironmentOption;
382+
} else {
383+
if (!session.release && !clientReleaseOption) {
384+
DEBUG_BUILD && logger.warn(MISSING_RELEASE_FOR_SESSION_ERROR);
385+
return;
386+
}
387+
session.release = session.release || clientReleaseOption;
388+
session.environment = session.environment || clientEnvironmentOption;
389+
}
390+
374391
const env = createSessionEnvelope(session, this._dsn, this._options._metadata, this._options.tunnel);
375392

376393
// sendEnvelope should not throw

packages/core/src/exports.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import type {
1414
User,
1515
} from './types-hoist';
1616

17-
import { DEFAULT_ENVIRONMENT } from './constants';
1817
import { getClient, getCurrentScope, getIsolationScope, withIsolationScope } from './currentScopes';
1918
import { DEBUG_BUILD } from './debug-build';
2019
import type { CaptureContext } from './scope';
@@ -265,18 +264,13 @@ export function addEventProcessor(callback: EventProcessor): void {
265264
* @returns the new active session
266265
*/
267266
export function startSession(context?: SessionContext): Session {
268-
const client = getClient();
269267
const isolationScope = getIsolationScope();
270268
const currentScope = getCurrentScope();
271269

272-
const { release, environment = DEFAULT_ENVIRONMENT } = (client && client.getOptions()) || {};
273-
274270
// Will fetch userAgent if called from browser sdk
275271
const { userAgent } = GLOBAL_OBJ.navigator || {};
276272

277273
const session = makeSession({
278-
release,
279-
environment,
280274
user: currentScope.getUser() || isolationScope.getUser(),
281275
...(userAgent && { userAgent }),
282276
...context,

packages/core/src/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ export {
4747
export { setAsyncContextStrategy } from './asyncContext';
4848
export { getGlobalSingleton, getMainCarrier } from './carrier';
4949
export { makeSession, closeSession, updateSession } from './session';
50-
// eslint-disable-next-line deprecation/deprecation
51-
export { SessionFlusher } from './sessionflusher';
5250
export { Scope } from './scope';
5351
export type { CaptureContext, ScopeContext, ScopeData } from './scope';
5452
export { notifyEventProcessors } from './eventProcessors';

packages/core/src/scope.ts

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import type {
1212
Extras,
1313
Primitive,
1414
PropagationContext,
15-
RequestSession,
1615
Session,
1716
SeverityLevel,
1817
Span,
@@ -50,11 +49,17 @@ export interface ScopeContext {
5049
contexts: Contexts;
5150
tags: { [key: string]: Primitive };
5251
fingerprint: string[];
53-
// eslint-disable-next-line deprecation/deprecation
54-
requestSession: RequestSession;
5552
propagationContext: PropagationContext;
5653
}
5754

55+
// TODO(v9): Add `normalizedRequest`
56+
export interface SdkProcessingMetadata {
57+
[key: string]: unknown;
58+
requestSession?: {
59+
status: 'ok' | 'errored' | 'crashed';
60+
};
61+
}
62+
5863
/**
5964
* Normalized data of the Scope, ready to be used.
6065
*/
@@ -67,7 +72,7 @@ export interface ScopeData {
6772
contexts: Contexts;
6873
attachments: Attachment[];
6974
propagationContext: PropagationContext;
70-
sdkProcessingMetadata: { [key: string]: unknown };
75+
sdkProcessingMetadata: SdkProcessingMetadata;
7176
fingerprint: string[];
7277
level?: SeverityLevel;
7378
transactionName?: string;
@@ -112,7 +117,7 @@ export class Scope {
112117
* A place to stash data which is needed at some point in the SDK's event processing pipeline but which shouldn't get
113118
* sent to Sentry
114119
*/
115-
protected _sdkProcessingMetadata: { [key: string]: unknown };
120+
protected _sdkProcessingMetadata: SdkProcessingMetadata;
116121

117122
/** Fingerprint */
118123
protected _fingerprint?: string[];
@@ -131,10 +136,6 @@ export class Scope {
131136
/** Session */
132137
protected _session?: Session;
133138

134-
/** Request Mode Session Status */
135-
// eslint-disable-next-line deprecation/deprecation
136-
protected _requestSession?: RequestSession;
137-
138139
/** The client on this scope */
139140
protected _client?: Client;
140141

@@ -183,7 +184,6 @@ export class Scope {
183184
newScope._transactionName = this._transactionName;
184185
newScope._fingerprint = this._fingerprint;
185186
newScope._eventProcessors = [...this._eventProcessors];
186-
newScope._requestSession = this._requestSession;
187187
newScope._attachments = [...this._attachments];
188188
newScope._sdkProcessingMetadata = { ...this._sdkProcessingMetadata };
189189
newScope._propagationContext = { ...this._propagationContext };
@@ -271,27 +271,6 @@ export class Scope {
271271
return this._user;
272272
}
273273

274-
/**
275-
* Get the request session from this scope.
276-
*
277-
* @deprecated Use `getSession()` and `setSession()` instead of `getRequestSession()` and `setRequestSession()`;
278-
*/
279-
// eslint-disable-next-line deprecation/deprecation
280-
public getRequestSession(): RequestSession | undefined {
281-
return this._requestSession;
282-
}
283-
284-
/**
285-
* Set the request session for this scope.
286-
*
287-
* @deprecated Use `getSession()` and `setSession()` instead of `getRequestSession()` and `setRequestSession()`;
288-
*/
289-
// eslint-disable-next-line deprecation/deprecation
290-
public setRequestSession(requestSession?: RequestSession): this {
291-
this._requestSession = requestSession;
292-
return this;
293-
}
294-
295274
/**
296275
* Set an object that will be merged into existing tags on the scope,
297276
* and will be sent as tags data with the event.
@@ -422,13 +401,12 @@ export class Scope {
422401

423402
const scopeToMerge = typeof captureContext === 'function' ? captureContext(this) : captureContext;
424403

425-
const [scopeInstance, requestSession] =
404+
const scopeInstance =
426405
scopeToMerge instanceof Scope
427-
? // eslint-disable-next-line deprecation/deprecation
428-
[scopeToMerge.getScopeData(), scopeToMerge.getRequestSession()]
406+
? scopeToMerge.getScopeData()
429407
: isPlainObject(scopeToMerge)
430-
? [captureContext as ScopeContext, (captureContext as ScopeContext).requestSession]
431-
: [];
408+
? (captureContext as ScopeContext)
409+
: undefined;
432410

433411
const { tags, extra, user, contexts, level, fingerprint = [], propagationContext } = scopeInstance || {};
434412

@@ -452,10 +430,6 @@ export class Scope {
452430
this._propagationContext = propagationContext;
453431
}
454432

455-
if (requestSession) {
456-
this._requestSession = requestSession;
457-
}
458-
459433
return this;
460434
}
461435

@@ -473,7 +447,6 @@ export class Scope {
473447
this._level = undefined;
474448
this._transactionName = undefined;
475449
this._fingerprint = undefined;
476-
this._requestSession = undefined;
477450
this._session = undefined;
478451
_setSpanForScope(this, undefined);
479452
this._attachments = [];

0 commit comments

Comments
 (0)