Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(node)!: Collect request sessions via HTTP instrumentation #14658

Merged
merged 48 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
7846b24
ci(v9): Ensure CI runs on v8 & v9 branches (#14604)
mydea Dec 6, 2024
d1ee444
feat(vue/nuxt)!: No longer create `"update"` spans for component trac…
lforst Dec 10, 2024
26119bf
feat(nextjs)!: Remove `experimental_captureRequestError` (#14607)
lforst Dec 10, 2024
d7e3626
feat(node)!: Collect request sessions via HTTP instrumentation
lforst Dec 11, 2024
30e2329
Merge branch 'v9' into lforst-server-sessions
lforst Dec 11, 2024
5430723
depr notice
lforst Dec 11, 2024
6610144
ci(v9): Ensure CI runs on v8 & v9 branches (#14604)
mydea Dec 6, 2024
1648698
feat(vue/nuxt)!: No longer create `"update"` spans for component trac…
lforst Dec 10, 2024
d9ee102
feat(nextjs)!: Remove `experimental_captureRequestError` (#14607)
lforst Dec 10, 2024
32a1cff
meta(v9): Add v9 migration guide (#14296)
lforst Dec 11, 2024
3add6cd
feat(node)!: Remove `processThreadBreadcrumbIntegration` (#14666)
lforst Dec 12, 2024
8b81476
feat(node)!: Avoid http spans by default for custom OTEL setups (#14678)
mydea Dec 13, 2024
c0f9aaa
Merge remote-tracking branch 'origin/v9' into lforst-server-sessions
lforst Dec 13, 2024
1c9544b
ref!: Don't polyfill optional chaining and nullish coalescing (#14603)
lforst Dec 13, 2024
b2aed90
Merge branch 'v9' into lforst-server-sessions
lforst Dec 13, 2024
ac0d55a
revert
lforst Dec 13, 2024
74ac9c3
Hmm
lforst Dec 13, 2024
5e65c87
ci(v9): Ensure CI runs on v8 & v9 branches (#14604)
mydea Dec 6, 2024
fac8d97
feat(vue/nuxt)!: No longer create `"update"` spans for component trac…
lforst Dec 10, 2024
6772615
feat(nextjs)!: Remove `experimental_captureRequestError` (#14607)
lforst Dec 10, 2024
6e88c55
meta(v9): Add v9 migration guide (#14296)
lforst Dec 11, 2024
bfd865c
feat(node)!: Remove `processThreadBreadcrumbIntegration` (#14666)
lforst Dec 12, 2024
550ceef
feat(node)!: Avoid http spans by default for custom OTEL setups (#14678)
mydea Dec 13, 2024
f792e64
ref!: Don't polyfill optional chaining and nullish coalescing (#14603)
lforst Dec 13, 2024
5c7d64e
Merge branch 'v9' into lforst-server-sessions
lforst Dec 13, 2024
a2ca9b0
crashed and errored
lforst Dec 13, 2024
64ab7f6
rm unneeded tests
lforst Dec 13, 2024
0d38856
More cleanup
lforst Dec 13, 2024
974b37b
stuff
lforst Dec 13, 2024
c3b7e24
formatting
lforst Dec 13, 2024
7800715
Merge remote-tracking branch 'origin/develop' into lforst-server-sess…
lforst Dec 16, 2024
cde5a08
Fix some tests
lforst Dec 16, 2024
eb795ec
hm
lforst Dec 16, 2024
31686ac
desperately try to improve bundle size
lforst Dec 16, 2024
2d084e8
bundle?
lforst Dec 16, 2024
a0fe31d
Merge branch 'develop' into lforst-server-sessions
lforst Dec 16, 2024
084781a
fun
lforst Dec 16, 2024
cae7fc8
Add the most beautiful tests I have ever produced
lforst Dec 16, 2024
3cfd11b
Merge branch 'develop' into lforst-server-sessions
lforst Dec 16, 2024
ad59b24
fix
lforst Dec 16, 2024
d06262c
Merge branch 'develop' into lforst-server-sessions
lforst Dec 16, 2024
0c7f97c
lint
lforst Dec 16, 2024
5940711
Merge remote-tracking branch 'origin/develop' into lforst-server-sess…
lforst Dec 16, 2024
845e454
fix
lforst Dec 16, 2024
d93c352
facepalm
lforst Dec 16, 2024
aabd1a9
Merge remote-tracking branch 'origin/develop' into lforst-server-sess…
lforst Dec 19, 2024
9ab3627
Feedback
lforst Dec 19, 2024
120c34e
messed up merge
lforst Dec 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module.exports = [
path: 'packages/browser/build/npm/esm/index.js',
import: createImport('init'),
gzip: true,
limit: '24 KB',
limit: '24.1 KB',
modifyWebpackConfig: function (config) {
const webpack = require('webpack');
const TerserPlugin = require('terser-webpack-plugin');
Expand Down
15 changes: 6 additions & 9 deletions dev-packages/node-integration-tests/suites/sessions/server.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import { loggingTransport } from '@sentry-internal/node-integration-tests';
import type { SessionFlusher } from '@sentry/core';
import * as Sentry from '@sentry/node';

Sentry.init({
dsn: 'https://[email protected]/1337',
release: '1.0',
transport: loggingTransport,
integrations: [
Sentry.httpIntegration({
// Flush after 2 seconds (to avoid waiting for the default 60s)
sessionFlushingDelayMS: 2_000,
}),
],
});

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

const app = express();

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

// Flush after 2 seconds (to avoid waiting for the default 60s)
setTimeout(() => {
flusher?.flush();
}, 2000);

app.get('/test/success', (_req, res) => {
res.send('Success!');
});
Expand Down
1 change: 1 addition & 0 deletions docs/migration/v8-to-v9.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ The Sentry metrics beta has ended and the metrics API has been removed from the
- Deprecated `RequestSessionStatus` type. No replacements.
- Deprecated `SessionFlusherLike` type. No replacements.
- Deprecated `SessionFlusher`. No replacements.
- Deprecated `initSessionFlusher` on `ServerRuntimeClient`. No replacements. The `httpIntegration` will flush sessions by itself.

## `@sentry/nestjs`

Expand Down
31 changes: 24 additions & 7 deletions packages/core/src/baseclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type {
} from './types-hoist';

import { getEnvelopeEndpointWithUrlEncodedAuth } from './api';
import { DEFAULT_ENVIRONMENT } from './constants';
import { getCurrentScope, getIsolationScope, getTraceContextFromScope } from './currentScopes';
import { DEBUG_BUILD } from './debug-build';
import { createEventEnvelope, createSessionEnvelope } from './envelope';
Expand All @@ -55,6 +56,7 @@ import { prepareEvent } from './utils/prepareEvent';
import { showSpanDropWarning } from './utils/spanUtils';

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

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

/**
Expand Down Expand Up @@ -371,6 +369,25 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
* @inheritDoc
*/
public sendSession(session: Session | SessionAggregates): void {
// Backfill release and environment on session
const { release: clientReleaseOption, environment: clientEnvironmentOption = DEFAULT_ENVIRONMENT } = this._options;
if ('aggregates' in session) {
const sessionAttrs = session.attrs || {};
if (!sessionAttrs.release && !clientReleaseOption) {
DEBUG_BUILD && logger.warn(MISSING_RELEASE_FOR_SESSION_ERROR);
return;
}
sessionAttrs.release = sessionAttrs.release || clientReleaseOption;
sessionAttrs.environment = sessionAttrs.environment || clientEnvironmentOption;
} else {
if (!session.release && !clientReleaseOption) {
DEBUG_BUILD && logger.warn(MISSING_RELEASE_FOR_SESSION_ERROR);
return;
}
session.release = session.release || clientReleaseOption;
session.environment = session.environment || clientEnvironmentOption;
}

const env = createSessionEnvelope(session, this._dsn, this._options._metadata, this._options.tunnel);

// sendEnvelope should not throw
Expand Down
6 changes: 0 additions & 6 deletions packages/core/src/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import type {
User,
} from './types-hoist';

import { DEFAULT_ENVIRONMENT } from './constants';
import { getClient, getCurrentScope, getIsolationScope, withIsolationScope } from './currentScopes';
import { DEBUG_BUILD } from './debug-build';
import type { CaptureContext } from './scope';
Expand Down Expand Up @@ -265,18 +264,13 @@ export function addEventProcessor(callback: EventProcessor): void {
* @returns the new active session
*/
export function startSession(context?: SessionContext): Session {
const client = getClient();
const isolationScope = getIsolationScope();
const currentScope = getCurrentScope();

const { release, environment = DEFAULT_ENVIRONMENT } = (client && client.getOptions()) || {};

// Will fetch userAgent if called from browser sdk
const { userAgent } = GLOBAL_OBJ.navigator || {};

const session = makeSession({
release,
environment,
user: currentScope.getUser() || isolationScope.getUser(),
...(userAgent && { userAgent }),
...context,
Expand Down
2 changes: 0 additions & 2 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ export {
export { setAsyncContextStrategy } from './asyncContext';
export { getGlobalSingleton, getMainCarrier } from './carrier';
export { makeSession, closeSession, updateSession } from './session';
// eslint-disable-next-line deprecation/deprecation
export { SessionFlusher } from './sessionflusher';
export { Scope } from './scope';
export type { CaptureContext, ScopeContext, ScopeData } from './scope';
export { notifyEventProcessors } from './eventProcessors';
Expand Down
55 changes: 14 additions & 41 deletions packages/core/src/scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import type {
Extras,
Primitive,
PropagationContext,
RequestSession,
Session,
SeverityLevel,
Span,
Expand Down Expand Up @@ -50,11 +49,17 @@ export interface ScopeContext {
contexts: Contexts;
tags: { [key: string]: Primitive };
fingerprint: string[];
// eslint-disable-next-line deprecation/deprecation
requestSession: RequestSession;
propagationContext: PropagationContext;
}

// TODO(v9): Add `normalizedRequest`
export interface SdkProcessingMetadata {
[key: string]: unknown;
requestSession?: {
status: 'ok' | 'errored' | 'crashed';
};
}

/**
* Normalized data of the Scope, ready to be used.
*/
Expand All @@ -67,7 +72,7 @@ export interface ScopeData {
contexts: Contexts;
attachments: Attachment[];
propagationContext: PropagationContext;
sdkProcessingMetadata: { [key: string]: unknown };
sdkProcessingMetadata: SdkProcessingMetadata;
fingerprint: string[];
level?: SeverityLevel;
transactionName?: string;
Expand Down Expand Up @@ -112,7 +117,7 @@ export class Scope {
* A place to stash data which is needed at some point in the SDK's event processing pipeline but which shouldn't get
* sent to Sentry
*/
protected _sdkProcessingMetadata: { [key: string]: unknown };
protected _sdkProcessingMetadata: SdkProcessingMetadata;

/** Fingerprint */
protected _fingerprint?: string[];
Expand All @@ -131,10 +136,6 @@ export class Scope {
/** Session */
protected _session?: Session;

/** Request Mode Session Status */
// eslint-disable-next-line deprecation/deprecation
protected _requestSession?: RequestSession;

/** The client on this scope */
protected _client?: Client;

Expand Down Expand Up @@ -183,7 +184,6 @@ export class Scope {
newScope._transactionName = this._transactionName;
newScope._fingerprint = this._fingerprint;
newScope._eventProcessors = [...this._eventProcessors];
newScope._requestSession = this._requestSession;
newScope._attachments = [...this._attachments];
newScope._sdkProcessingMetadata = { ...this._sdkProcessingMetadata };
newScope._propagationContext = { ...this._propagationContext };
Expand Down Expand Up @@ -271,27 +271,6 @@ export class Scope {
return this._user;
}

/**
* Get the request session from this scope.
*
* @deprecated Use `getSession()` and `setSession()` instead of `getRequestSession()` and `setRequestSession()`;
*/
// eslint-disable-next-line deprecation/deprecation
public getRequestSession(): RequestSession | undefined {
return this._requestSession;
}

/**
* Set the request session for this scope.
*
* @deprecated Use `getSession()` and `setSession()` instead of `getRequestSession()` and `setRequestSession()`;
*/
// eslint-disable-next-line deprecation/deprecation
public setRequestSession(requestSession?: RequestSession): this {
this._requestSession = requestSession;
return this;
}

/**
* Set an object that will be merged into existing tags on the scope,
* and will be sent as tags data with the event.
Expand Down Expand Up @@ -422,13 +401,12 @@ export class Scope {

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

const [scopeInstance, requestSession] =
const scopeInstance =
scopeToMerge instanceof Scope
? // eslint-disable-next-line deprecation/deprecation
[scopeToMerge.getScopeData(), scopeToMerge.getRequestSession()]
? scopeToMerge.getScopeData()
: isPlainObject(scopeToMerge)
? [captureContext as ScopeContext, (captureContext as ScopeContext).requestSession]
: [];
? (captureContext as ScopeContext)
: undefined;

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

Expand All @@ -452,10 +430,6 @@ export class Scope {
this._propagationContext = propagationContext;
}

if (requestSession) {
this._requestSession = requestSession;
}

return this;
}

Expand All @@ -473,7 +447,6 @@ export class Scope {
this._level = undefined;
this._transactionName = undefined;
this._fingerprint = undefined;
this._requestSession = undefined;
this._session = undefined;
_setSpanForScope(this, undefined);
this._attachments = [];
Expand Down
Loading
Loading