Skip to content

Commit 045d8b4

Browse files
authored
feat(core): Deprecate APIs around RequestSessions (#14566)
1 parent c6ae78b commit 045d8b4

File tree

17 files changed

+114
-10
lines changed

17 files changed

+114
-10
lines changed

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

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import express from 'express';
1313

1414
const app = express();
1515

16+
// eslint-disable-next-line deprecation/deprecation
1617
const flusher = (Sentry.getClient() as Sentry.NodeClient)['_sessionFlusher'] as SessionFlusher;
1718

1819
// Flush after 2 seconds (to avoid waiting for the default 60s)

docs/migration/draft-v9-migration-guide.md

+7
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@
4747
- Deprecated `addTracingHeadersToFetchRequest` method - this was only meant for internal use and is not needed anymore.
4848
- Deprecated `generatePropagationContext()` in favor of using `generateTraceId()` directly.
4949
- Deprecated `spanId` field on `propagationContext` - this field will be removed in v9, and should neither be read or set anymore.
50+
- Deprecated `RequestSession` type. No replacements.
51+
- Deprecated `RequestSessionStatus` type. No replacements.
52+
- Deprecated `SessionFlusherLike` type. No replacements.
53+
- Deprecated `SessionFlusher`. No replacements.
5054

5155
## `@sentry/nestjs`
5256

@@ -69,6 +73,9 @@
6973
- **The `@sentry/types` package has been deprecated. Import everything from `@sentry/core` instead.**
7074

7175
- Deprecated `Request` in favor of `RequestEventData`.
76+
- Deprecated `RequestSession`. No replacements.
77+
- Deprecated `RequestSessionStatus`. No replacements.
78+
- Deprecated `SessionFlusherLike`. No replacements.
7279

7380
## `@sentry/nuxt`
7481

packages/core/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export {
4747
export { setAsyncContextStrategy } from './asyncContext';
4848
export { getMainCarrier } from './carrier';
4949
export { makeSession, closeSession, updateSession } from './session';
50+
// eslint-disable-next-line deprecation/deprecation
5051
export { SessionFlusher } from './sessionflusher';
5152
export { Scope } from './scope';
5253
export { notifyEventProcessors } from './eventProcessors';

packages/core/src/scope.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class ScopeClass implements ScopeInterface {
9494
protected _session?: Session;
9595

9696
/** Request Mode Session Status */
97+
// eslint-disable-next-line deprecation/deprecation
9798
protected _requestSession?: RequestSession;
9899

99100
/** The client on this scope */
@@ -230,13 +231,15 @@ class ScopeClass implements ScopeInterface {
230231
/**
231232
* @inheritDoc
232233
*/
234+
// eslint-disable-next-line deprecation/deprecation
233235
public getRequestSession(): RequestSession | undefined {
234236
return this._requestSession;
235237
}
236238

237239
/**
238240
* @inheritDoc
239241
*/
242+
// eslint-disable-next-line deprecation/deprecation
240243
public setRequestSession(requestSession?: RequestSession): this {
241244
this._requestSession = requestSession;
242245
return this;
@@ -358,7 +361,8 @@ class ScopeClass implements ScopeInterface {
358361

359362
const [scopeInstance, requestSession] =
360363
scopeToMerge instanceof Scope
361-
? [scopeToMerge.getScopeData(), scopeToMerge.getRequestSession()]
364+
? // eslint-disable-next-line deprecation/deprecation
365+
[scopeToMerge.getScopeData(), scopeToMerge.getRequestSession()]
362366
: isPlainObject(scopeToMerge)
363367
? [captureContext as ScopeContext, (captureContext as ScopeContext).requestSession]
364368
: [];

packages/core/src/server-runtime-client.ts

+22-8
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export interface ServerRuntimeClientOptions extends ClientOptions<BaseTransportO
4242
export class ServerRuntimeClient<
4343
O extends ClientOptions & ServerRuntimeClientOptions = ServerRuntimeClientOptions,
4444
> extends BaseClient<O> {
45+
// eslint-disable-next-line deprecation/deprecation
4546
protected _sessionFlusher: SessionFlusher | undefined;
4647

4748
/**
@@ -80,10 +81,12 @@ export class ServerRuntimeClient<
8081
*/
8182
// eslint-disable-next-line @typescript-eslint/no-explicit-any
8283
public captureException(exception: any, hint?: EventHint, scope?: Scope): string {
83-
// Check if the flag `autoSessionTracking` is enabled, and if `_sessionFlusher` exists because it is initialised only
84-
// when the `requestHandler` middleware is used, and hence the expectation is to have SessionAggregates payload
85-
// sent to the Server only when the `requestHandler` middleware is used
84+
// Check if `_sessionFlusher` exists because it is initialized (defined) only when the `autoSessionTracking` is enabled.
85+
// The expectation is that session aggregates are only sent when `autoSessionTracking` is enabled.
86+
// TODO(v9): Our goal in the future is to not have the `autoSessionTracking` option and instead rely on integrations doing the creation and sending of sessions. We will not have a central kill-switch for sessions.
87+
// TODO(v9): This should move into the httpIntegration.
8688
if (this._options.autoSessionTracking && this._sessionFlusher) {
89+
// eslint-disable-next-line deprecation/deprecation
8790
const requestSession = getIsolationScope().getRequestSession();
8891

8992
// Necessary checks to ensure this is code block is executed only within a request
@@ -100,16 +103,18 @@ export class ServerRuntimeClient<
100103
* @inheritDoc
101104
*/
102105
public captureEvent(event: Event, hint?: EventHint, scope?: Scope): string {
103-
// Check if the flag `autoSessionTracking` is enabled, and if `_sessionFlusher` exists because it is initialised only
104-
// when the `requestHandler` middleware is used, and hence the expectation is to have SessionAggregates payload
105-
// sent to the Server only when the `requestHandler` middleware is used
106+
// Check if `_sessionFlusher` exists because it is initialized only when the `autoSessionTracking` is enabled.
107+
// The expectation is that session aggregates are only sent when `autoSessionTracking` is enabled.
108+
// TODO(v9): Our goal in the future is to not have the `autoSessionTracking` option and instead rely on integrations doing the creation and sending of sessions. We will not have a central kill-switch for sessions.
109+
// TODO(v9): This should move into the httpIntegration.
106110
if (this._options.autoSessionTracking && this._sessionFlusher) {
107111
const eventType = event.type || 'exception';
108112
const isException =
109113
eventType === 'exception' && event.exception && event.exception.values && event.exception.values.length > 0;
110114

111115
// If the event is of type Exception, then a request session should be captured
112116
if (isException) {
117+
// eslint-disable-next-line deprecation/deprecation
113118
const requestSession = getIsolationScope().getRequestSession();
114119

115120
// Ensure that this is happening within the bounds of a request, and make sure not to override
@@ -134,12 +139,19 @@ export class ServerRuntimeClient<
134139
return super.close(timeout);
135140
}
136141

137-
/** Method that initialises an instance of SessionFlusher on Client */
142+
/**
143+
* Initializes an instance of SessionFlusher on the client which will aggregate and periodically flush session data.
144+
*
145+
* NOTICE: This method will implicitly create an interval that is periodically called.
146+
* To clean up this resources, call `.close()` when you no longer intend to use the client.
147+
* Not doing so will result in a memory leak.
148+
*/
138149
public initSessionFlusher(): void {
139150
const { release, environment } = this._options;
140151
if (!release) {
141-
DEBUG_BUILD && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!');
152+
DEBUG_BUILD && logger.warn('Cannot initialize an instance of SessionFlusher if no release is provided!');
142153
} else {
154+
// eslint-disable-next-line deprecation/deprecation
143155
this._sessionFlusher = new SessionFlusher(this, {
144156
release,
145157
environment,
@@ -214,6 +226,8 @@ export class ServerRuntimeClient<
214226
/**
215227
* Method responsible for capturing/ending a request session by calling `incrementSessionStatusCount` to increment
216228
* appropriate session aggregates bucket
229+
*
230+
* @deprecated This method should not be used or extended. It's functionality will move into the `httpIntegration` and not be part of any public API.
217231
*/
218232
protected _captureRequestSession(): void {
219233
if (!this._sessionFlusher) {

packages/core/src/sessionflusher.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ type ReleaseHealthAttributes = {
1414
};
1515

1616
/**
17-
* @inheritdoc
17+
* @deprecated `SessionFlusher` is deprecated and will be removed in the next major version of the SDK.
1818
*/
19+
// TODO(v9): The goal for the SessionFlusher is to become a stupidly simple mechanism to aggregate "Sessions" (actually "RequestSessions"). It should probably live directly inside the Http integration/instrumentation.
20+
// eslint-disable-next-line deprecation/deprecation
1921
export class SessionFlusher implements SessionFlusherLike {
2022
public readonly flushTimeout: number;
2123
private _pendingAggregates: Map<number, AggregationCounts>;
@@ -80,12 +82,14 @@ export class SessionFlusher implements SessionFlusherLike {
8082
return;
8183
}
8284
const isolationScope = getIsolationScope();
85+
// eslint-disable-next-line deprecation/deprecation
8386
const requestSession = isolationScope.getRequestSession();
8487

8588
if (requestSession && requestSession.status) {
8689
this._incrementSessionStatusCount(requestSession.status, new Date());
8790
// This is not entirely necessarily but is added as a safe guard to indicate the bounds of a request and so in
8891
// case captureRequestSession is called more than once to prevent double count
92+
// eslint-disable-next-line deprecation/deprecation
8993
isolationScope.setRequestSession(undefined);
9094
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
9195
}
@@ -95,6 +99,7 @@ export class SessionFlusher implements SessionFlusherLike {
9599
* Increments status bucket in pendingAggregates buffer (internal state) corresponding to status of
96100
* the session received
97101
*/
102+
// eslint-disable-next-line deprecation/deprecation
98103
private _incrementSessionStatusCount(status: RequestSessionStatus, date: Date): number {
99104
// Truncate minutes and seconds on Session Started attribute to have one minute bucket keys
100105
const sessionStartedTrunc = new Date(date).setSeconds(0, 0);

packages/core/src/types-hoist/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,11 @@ export type {
104104
Session,
105105
SessionContext,
106106
SessionStatus,
107+
// eslint-disable-next-line deprecation/deprecation
107108
RequestSession,
109+
// eslint-disable-next-line deprecation/deprecation
108110
RequestSessionStatus,
111+
// eslint-disable-next-line deprecation/deprecation
109112
SessionFlusherLike,
110113
SerializedSession,
111114
} from './session';

packages/core/src/types-hoist/scope.ts

+7
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface ScopeContext {
2323
contexts: Contexts;
2424
tags: { [key: string]: Primitive };
2525
fingerprint: string[];
26+
// eslint-disable-next-line deprecation/deprecation
2627
requestSession: RequestSession;
2728
propagationContext: PropagationContext;
2829
}
@@ -168,12 +169,18 @@ export interface Scope {
168169

169170
/**
170171
* Returns the `RequestSession` if there is one
172+
*
173+
* @deprecated Use `getSession()` and `setSession()` instead of `getRequestSession()` and `setRequestSession()`;
171174
*/
175+
// eslint-disable-next-line deprecation/deprecation
172176
getRequestSession(): RequestSession | undefined;
173177

174178
/**
175179
* Sets the `RequestSession` on the scope
180+
*
181+
* @deprecated Use `getSession()` and `setSession()` instead of `getRequestSession()` and `setRequestSession()`;
176182
*/
183+
// eslint-disable-next-line deprecation/deprecation
177184
setRequestSession(requestSession?: RequestSession): this;
178185

179186
/**

packages/core/src/types-hoist/session.ts

+11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import type { User } from './user';
22

3+
/**
4+
* @deprecated This type is deprecated and will be removed in the next major version of the SDK.
5+
*/
36
export interface RequestSession {
7+
// eslint-disable-next-line deprecation/deprecation
48
status?: RequestSessionStatus;
59
}
610

@@ -35,6 +39,10 @@ export interface Session {
3539
export type SessionContext = Partial<Session>;
3640

3741
export type SessionStatus = 'ok' | 'exited' | 'crashed' | 'abnormal';
42+
43+
/**
44+
* @deprecated This type is deprecated and will be removed in the next major version of the SDK.
45+
*/
3846
export type RequestSessionStatus = 'ok' | 'errored' | 'crashed';
3947

4048
/** JSDoc */
@@ -46,6 +54,9 @@ export interface SessionAggregates {
4654
aggregates: Array<AggregationCounts>;
4755
}
4856

57+
/**
58+
* @deprecated This type is deprecated and will be removed in the next major version of the SDK.
59+
*/
4960
export interface SessionFlusherLike {
5061
/**
5162
* Increments the Session Status bucket in SessionAggregates Object corresponding to the status of the session

packages/core/test/lib/scope.test.ts

+9
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,10 @@ describe('Scope', () => {
261261

262262
test('_requestSession clone', () => {
263263
const parentScope = new Scope();
264+
// eslint-disable-next-line deprecation/deprecation
264265
parentScope.setRequestSession({ status: 'errored' });
265266
const scope = parentScope.clone();
267+
// eslint-disable-next-line deprecation/deprecation
266268
expect(parentScope.getRequestSession()).toEqual(scope.getRequestSession());
267269
});
268270

@@ -288,15 +290,19 @@ describe('Scope', () => {
288290
// Test that ensures if the status value of `status` of `_requestSession` is changed in a child scope
289291
// that it should also change in parent scope because we are copying the reference to the object
290292
const parentScope = new Scope();
293+
// eslint-disable-next-line deprecation/deprecation
291294
parentScope.setRequestSession({ status: 'errored' });
292295

293296
const scope = parentScope.clone();
297+
// eslint-disable-next-line deprecation/deprecation
294298
const requestSession = scope.getRequestSession();
295299
if (requestSession) {
296300
requestSession.status = 'ok';
297301
}
298302

303+
// eslint-disable-next-line deprecation/deprecation
299304
expect(parentScope.getRequestSession()).toEqual({ status: 'ok' });
305+
// eslint-disable-next-line deprecation/deprecation
300306
expect(scope.getRequestSession()).toEqual({ status: 'ok' });
301307
});
302308

@@ -316,6 +322,7 @@ describe('Scope', () => {
316322
scope.setUser({ id: '1' });
317323
scope.setFingerprint(['abcd']);
318324
scope.addBreadcrumb({ message: 'test' });
325+
// eslint-disable-next-line deprecation/deprecation
319326
scope.setRequestSession({ status: 'ok' });
320327
expect(scope['_extra']).toEqual({ a: 2 });
321328
scope.clear();
@@ -349,6 +356,7 @@ describe('Scope', () => {
349356
scope.setUser({ id: '1337' });
350357
scope.setLevel('info');
351358
scope.setFingerprint(['foo']);
359+
// eslint-disable-next-line deprecation/deprecation
352360
scope.setRequestSession({ status: 'ok' });
353361
});
354362

@@ -453,6 +461,7 @@ describe('Scope', () => {
453461
level: 'warning' as const,
454462
tags: { bar: '3', baz: '4' },
455463
user: { id: '42' },
464+
// eslint-disable-next-line deprecation/deprecation
456465
requestSession: { status: 'errored' as RequestSessionStatus },
457466
propagationContext: {
458467
traceId: '8949daf83f4a4a70bee4c1eb9ab242ed',

packages/core/test/lib/sessionflusher.test.ts

+7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ describe('Session Flusher', () => {
1919
});
2020

2121
test('test incrementSessionStatusCount updates the internal SessionFlusher state', () => {
22+
// eslint-disable-next-line deprecation/deprecation
2223
const flusher = new SessionFlusher(mockClient, { release: '1.0.0', environment: 'dev' });
2324

2425
const date = new Date('2021-04-08T12:18:23.043Z');
@@ -42,6 +43,7 @@ describe('Session Flusher', () => {
4243
});
4344

4445
test('test undefined attributes are excluded, on incrementSessionStatusCount call', () => {
46+
// eslint-disable-next-line deprecation/deprecation
4547
const flusher = new SessionFlusher(mockClient, { release: '1.0.0' });
4648

4749
const date = new Date('2021-04-08T12:18:23.043Z');
@@ -55,6 +57,7 @@ describe('Session Flusher', () => {
5557
});
5658

5759
test('flush is called every 60 seconds after initialisation of an instance of SessionFlusher', () => {
60+
// eslint-disable-next-line deprecation/deprecation
5861
const flusher = new SessionFlusher(mockClient, { release: '1.0.0', environment: 'dev' });
5962
const flusherFlushFunc = jest.spyOn(flusher, 'flush');
6063
jest.advanceTimersByTime(59000);
@@ -68,6 +71,7 @@ describe('Session Flusher', () => {
6871
});
6972

7073
test('sendSessions is called on flush if sessions were captured', () => {
74+
// eslint-disable-next-line deprecation/deprecation
7175
const flusher = new SessionFlusher(mockClient, { release: '1.0.0', environment: 'dev' });
7276
const flusherFlushFunc = jest.spyOn(flusher, 'flush');
7377
const date = new Date('2021-04-08T12:18:23.043Z');
@@ -88,6 +92,7 @@ describe('Session Flusher', () => {
8892
});
8993

9094
test('sendSessions is not called on flush if no sessions were captured', () => {
95+
// eslint-disable-next-line deprecation/deprecation
9196
const flusher = new SessionFlusher(mockClient, { release: '1.0.0', environment: 'dev' });
9297
const flusherFlushFunc = jest.spyOn(flusher, 'flush');
9398

@@ -98,12 +103,14 @@ describe('Session Flusher', () => {
98103
});
99104

100105
test('calling close on SessionFlusher should disable SessionFlusher', () => {
106+
// eslint-disable-next-line deprecation/deprecation
101107
const flusher = new SessionFlusher(mockClient, { release: '1.0.x' });
102108
flusher.close();
103109
expect((flusher as any)._isEnabled).toEqual(false);
104110
});
105111

106112
test('calling close on SessionFlusher will force call flush', () => {
113+
// eslint-disable-next-line deprecation/deprecation
107114
const flusher = new SessionFlusher(mockClient, { release: '1.0.x' });
108115
const flusherFlushFunc = jest.spyOn(flusher, 'flush');
109116
const date = new Date('2021-04-08T12:18:23.043Z');

packages/node/src/integrations/http/SentryHttpInstrumentation.ts

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ export class SentryHttpInstrumentation extends InstrumentationBase<SentryHttpIns
148148

149149
const client = getClient<NodeClient>();
150150
if (client && client.getOptions().autoSessionTracking) {
151+
// eslint-disable-next-line deprecation/deprecation
151152
isolationScope.setRequestSession({ status: 'ok' });
152153
}
153154

packages/node/src/integrations/tracing/express.ts

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ export function expressErrorHandler(options?: ExpressHandlerOptions): ExpressMid
129129
// running in SessionAggregates mode
130130
const isSessionAggregatesMode = client['_sessionFlusher'] !== undefined;
131131
if (isSessionAggregatesMode) {
132+
// eslint-disable-next-line deprecation/deprecation
132133
const requestSession = getIsolationScope().getRequestSession();
133134
// If an error bubbles to the `errorHandler`, then this is an unhandled error, and should be reported as a
134135
// Crashed session. The `_requestSession.status` is checked to ensure that this error is happening within

packages/node/src/sdk/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ function _init(
156156

157157
logger.log(`Running in ${isCjs() ? 'CommonJS' : 'ESM'} mode.`);
158158

159+
// TODO(V9): Remove this code since all of the logic should be in an integration
159160
if (options.autoSessionTracking) {
160161
startSessionTracking();
161162
}

0 commit comments

Comments
 (0)