Skip to content

Commit

Permalink
Merge branch 'develop' into jb/profiling/local-require
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasBa authored Dec 4, 2024
2 parents 54d2383 + fcd2935 commit fd618e9
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ sentryTest('logs debug messages correctly', async ({ getLocalTestUrl, page }) =>
'Sentry Logger [log]: Integration installed: Dedupe',
'Sentry Logger [log]: Integration installed: HttpContext',
'Sentry Logger [warn]: Discarded session because of missing or non-string release',
'Sentry Logger [log]: Integration installed: BrowserSession',
'test log',
]
: ['[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.', 'test log'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ sentryTest('should capture replays (@sentry/browser export)', async ({ getLocalT
event_id: expect.stringMatching(/\w{32}/),
environment: 'production',
sdk: {
integrations: [
integrations: expect.arrayContaining([
'InboundFilters',
'FunctionToString',
'BrowserApiErrors',
Expand All @@ -43,8 +43,9 @@ sentryTest('should capture replays (@sentry/browser export)', async ({ getLocalT
'LinkedErrors',
'Dedupe',
'HttpContext',
'BrowserSession',
'Replay',
],
]),
version: SDK_VERSION,
name: 'sentry.javascript.browser',
},
Expand All @@ -71,7 +72,7 @@ sentryTest('should capture replays (@sentry/browser export)', async ({ getLocalT
event_id: expect.stringMatching(/\w{32}/),
environment: 'production',
sdk: {
integrations: [
integrations: expect.arrayContaining([
'InboundFilters',
'FunctionToString',
'BrowserApiErrors',
Expand All @@ -80,8 +81,9 @@ sentryTest('should capture replays (@sentry/browser export)', async ({ getLocalT
'LinkedErrors',
'Dedupe',
'HttpContext',
'BrowserSession',
'Replay',
],
]),
version: SDK_VERSION,
name: 'sentry.javascript.browser',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ sentryTest('should capture replays (@sentry-internal/replay export)', async ({ g
event_id: expect.stringMatching(/\w{32}/),
environment: 'production',
sdk: {
integrations: [
integrations: expect.arrayContaining([
'InboundFilters',
'FunctionToString',
'BrowserApiErrors',
Expand All @@ -43,8 +43,9 @@ sentryTest('should capture replays (@sentry-internal/replay export)', async ({ g
'LinkedErrors',
'Dedupe',
'HttpContext',
'BrowserSession',
'Replay',
],
]),
version: SDK_VERSION,
name: 'sentry.javascript.browser',
},
Expand All @@ -71,7 +72,7 @@ sentryTest('should capture replays (@sentry-internal/replay export)', async ({ g
event_id: expect.stringMatching(/\w{32}/),
environment: 'production',
sdk: {
integrations: [
integrations: expect.arrayContaining([
'InboundFilters',
'FunctionToString',
'BrowserApiErrors',
Expand All @@ -80,8 +81,9 @@ sentryTest('should capture replays (@sentry-internal/replay export)', async ({ g
'LinkedErrors',
'Dedupe',
'HttpContext',
'BrowserSession',
'Replay',
],
]),
version: SDK_VERSION,
name: 'sentry.javascript.browser',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const DEFAULT_REPLAY_EVENT = {
event_id: expect.stringMatching(/\w{32}/),
environment: 'production',
sdk: {
integrations: [
integrations: expect.arrayContaining([
'InboundFilters',
'FunctionToString',
'BrowserApiErrors',
Expand All @@ -25,8 +25,9 @@ const DEFAULT_REPLAY_EVENT = {
'LinkedErrors',
'Dedupe',
'HttpContext',
'BrowserSession',
'Replay',
],
]),
version: SDK_VERSION,
name: 'sentry.javascript.browser',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ test.describe('client-side errors', () => {
'LinkedErrors',
'Dedupe',
'HttpContext',
'BrowserSession',
'BrowserTracing',
]),
name: 'sentry.javascript.astro',
Expand Down
11 changes: 9 additions & 2 deletions packages/angular/src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { VERSION } from '@angular/core';
import type { BrowserOptions } from '@sentry/browser';
import {
breadcrumbsIntegration,
browserSessionIntegration,
globalHandlersIntegration,
httpContextIntegration,
init as browserInit,
Expand All @@ -22,7 +23,7 @@ import { IS_DEBUG_BUILD } from './flags';
/**
* Get the default integrations for the Angular SDK.
*/
export function getDefaultIntegrations(): Integration[] {
export function getDefaultIntegrations(options: BrowserOptions = {}): Integration[] {
// Don't include the BrowserApiErrors integration as it interferes with the Angular SDK's `ErrorHandler`:
// BrowserApiErrors would catch certain errors before they reach the `ErrorHandler` and
// thus provide a lower fidelity error than what `SentryErrorHandler`
Expand All @@ -31,7 +32,7 @@ export function getDefaultIntegrations(): Integration[] {
// see:
// - /~https://github.com/getsentry/sentry-javascript/issues/5417#issuecomment-1453407097
// - /~https://github.com/getsentry/sentry-javascript/issues/2744
return [
const integrations = [
inboundFiltersIntegration(),
functionToStringIntegration(),
breadcrumbsIntegration(),
Expand All @@ -40,6 +41,12 @@ export function getDefaultIntegrations(): Integration[] {
dedupeIntegration(),
httpContextIntegration(),
];

if (options.autoSessionTracking !== false) {
integrations.push(browserSessionIntegration());
}

return integrations;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/angular/test/sdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('init', () => {
});

it('does not include the BrowserApiErrors integration', () => {
const browserDefaultIntegrationsWithoutBrowserApiErrors = SentryBrowser.getDefaultIntegrations()
const browserDefaultIntegrationsWithoutBrowserApiErrors = SentryBrowser.getDefaultIntegrations({})
.filter(i => i.name !== 'BrowserApiErrors')
.map(i => i.name)
.sort();
Expand Down
1 change: 1 addition & 0 deletions packages/browser/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,4 @@ export type { Span } from '@sentry/core';
export { makeBrowserOfflineTransport } from './transports/offline';
export { browserProfilingIntegration } from './profiling/integration';
export { spotlightBrowserIntegration } from './integrations/spotlight';
export { browserSessionIntegration } from './integrations/browsersession';
39 changes: 39 additions & 0 deletions packages/browser/src/integrations/browsersession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { addHistoryInstrumentationHandler } from '@sentry-internal/browser-utils';
import { captureSession, defineIntegration, logger, startSession } from '@sentry/core';
import { DEBUG_BUILD } from '../debug-build';
import { WINDOW } from '../helpers';

/**
* When added, automatically creates sessions which allow you to track adoption and crashes (crash free rate) in your Releases in Sentry.
* More information: https://docs.sentry.io/product/releases/health/
*
* Note: In order for session tracking to work, you need to set up Releases: https://docs.sentry.io/product/releases/
*/
export const browserSessionIntegration = defineIntegration(() => {
return {
name: 'BrowserSession',
setupOnce() {
if (typeof WINDOW.document === 'undefined') {
DEBUG_BUILD &&
logger.warn('Using the `browserSessionIntegration` in non-browser environments is not supported.');
return;
}

// The session duration for browser sessions does not track a meaningful
// concept that can be used as a metric.
// Automatically captured sessions are akin to page views, and thus we
// discard their duration.
startSession({ ignoreDuration: true });
captureSession();

// We want to create a session for every navigation as well
addHistoryInstrumentationHandler(({ from, to }) => {
// Don't create an additional session for the initial route or if the location did not change
if (from !== undefined && from !== to) {
startSession({ ignoreDuration: true });
captureSession();
}
});
},
};
});
48 changes: 10 additions & 38 deletions packages/browser/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { addHistoryInstrumentationHandler } from '@sentry-internal/browser-utils';
import {
captureSession,
consoleSandbox,
dedupeIntegration,
functionToStringIntegration,
Expand All @@ -13,7 +11,6 @@ import {
lastEventId,
logger,
stackParserFromStackParserOptions,
startSession,
supportsFetch,
} from '@sentry/core';
import type { Client, DsnLike, Integration, Options, UserFeedback } from '@sentry/core';
Expand All @@ -23,19 +20,20 @@ import { DEBUG_BUILD } from './debug-build';
import { WINDOW } from './helpers';
import { breadcrumbsIntegration } from './integrations/breadcrumbs';
import { browserApiErrorsIntegration } from './integrations/browserapierrors';
import { browserSessionIntegration } from './integrations/browsersession';
import { globalHandlersIntegration } from './integrations/globalhandlers';
import { httpContextIntegration } from './integrations/httpcontext';
import { linkedErrorsIntegration } from './integrations/linkederrors';
import { defaultStackParser } from './stack-parsers';
import { makeFetchTransport } from './transports/fetch';

/** Get the default integrations for the browser SDK. */
export function getDefaultIntegrations(_options: Options): Integration[] {
export function getDefaultIntegrations(options: Options): Integration[] {
/**
* Note: Please make sure this stays in sync with Angular SDK, which re-exports
* `getDefaultIntegrations` but with an adjusted set of integrations.
*/
return [
const integrations = [
inboundFiltersIntegration(),
functionToStringIntegration(),
browserApiErrorsIntegration(),
Expand All @@ -45,6 +43,12 @@ export function getDefaultIntegrations(_options: Options): Integration[] {
dedupeIntegration(),
httpContextIntegration(),
];

if (options.autoSessionTracking !== false) {
integrations.push(browserSessionIntegration());
}

return integrations;
}

function applyDefaultOptions(optionsArg: BrowserOptions = {}): BrowserOptions {
Expand Down Expand Up @@ -187,13 +191,7 @@ export function init(browserOptions: BrowserOptions = {}): Client | undefined {
transport: options.transport || makeFetchTransport,
};

const client = initAndBind(BrowserClient, clientOptions);

if (options.autoSessionTracking) {
startSessionTracking();
}

return client;
return initAndBind(BrowserClient, clientOptions);
}

/**
Expand Down Expand Up @@ -308,32 +306,6 @@ export function onLoad(callback: () => void): void {
callback();
}

/**
* Enable automatic Session Tracking for the initial page load.
*/
function startSessionTracking(): void {
if (typeof WINDOW.document === 'undefined') {
DEBUG_BUILD && logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.');
return;
}

// The session duration for browser sessions does not track a meaningful
// concept that can be used as a metric.
// Automatically captured sessions are akin to page views, and thus we
// discard their duration.
startSession({ ignoreDuration: true });
captureSession();

// We want to create a session for every navigation as well
addHistoryInstrumentationHandler(({ from, to }) => {
// Don't create an additional session for the initial route or if the location did not change
if (from !== undefined && from !== to) {
startSession({ ignoreDuration: true });
captureSession();
}
});
}

/**
* Captures user feedback and sends it to Sentry.
*
Expand Down
33 changes: 23 additions & 10 deletions packages/node/src/integrations/http/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ClientRequest, IncomingMessage, RequestOptions, ServerResponse } f
import { diag } from '@opentelemetry/api';
import type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import type { IntegrationFn, Span } from '@sentry/core';
import type { Span } from '@sentry/core';
import { defineIntegration } from '@sentry/core';
import { getClient } from '@sentry/opentelemetry';
import { generateInstrumentOnce } from '../../otel/instrument';
Expand Down Expand Up @@ -30,6 +30,16 @@ interface HttpOptions {
*/
spans?: boolean;

/**
* Whether the integration should create [Sessions](https://docs.sentry.io/product/releases/health/#sessions) for incoming requests to track the health and crash-free rate of your releases in Sentry.
* Read more about Release Health: https://docs.sentry.io/product/releases/health/
*
* Defaults to `true`.
*
* Note: If `autoSessionTracking` is set to `false` in `Sentry.init()` or the Client owning this integration, this option will be ignored.
*/
trackIncomingRequestsAsSessions?: boolean;

/**
* Do not capture spans or breadcrumbs for outgoing HTTP requests to URLs where the given callback returns `true`.
* This controls both span & breadcrumb creation - spans will be non recording if tracing is disabled.
Expand Down Expand Up @@ -123,20 +133,18 @@ const instrumentHttp = (options: HttpOptions = {}): void => {
instrumentSentryHttp(options);
};

const _httpIntegration = ((options: HttpOptions = {}) => {
/**
* The http integration instruments Node's internal http and https modules.
* It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.
*/
export const httpIntegration = defineIntegration((options: HttpOptions = {}) => {
return {
name: INTEGRATION_NAME,
setupOnce() {
instrumentHttp(options);
},
};
}) satisfies IntegrationFn;

/**
* The http integration instruments Node's internal http and https modules.
* It creates breadcrumbs and spans for outgoing HTTP requests which will be attached to the currently active span.
*/
export const httpIntegration = defineIntegration(_httpIntegration);
});

/**
* Determines if @param req is a ClientRequest, meaning the request was created within the express app
Expand Down Expand Up @@ -207,7 +215,12 @@ function getConfigWithDefaults(options: Partial<HttpOptions> = {}): HttpInstrume
},
responseHook: (span, res) => {
const client = getClient<NodeClient>();
if (client && client.getOptions().autoSessionTracking) {

if (
client &&
client.getOptions().autoSessionTracking !== false &&
options.trackIncomingRequestsAsSessions !== false
) {
setImmediate(() => {
client['_captureRequestSession']();
});
Expand Down

0 comments on commit fd618e9

Please sign in to comment.