From a254d697890412ab26af60b9866d2ba5d4c12771 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 24 Jul 2026 15:50:55 +0200 Subject: [PATCH 1/6] feat(core)!: Enable logs by default Flip the `enableLogs` client option to default to `true`, mirroring `enableMetrics`. No logs are emitted unless the logger API is called or a logging integration is explicitly enabled, since no default integration captures logs. Fixes #20639 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../deno-streamed/src/app.ts | 1 - .../test-applications/deno/src/app.ts | 1 - .../effect-3-browser/src/index.js | 1 - .../effect-3-node/src/app.ts | 1 - .../effect-4-browser/src/index.js | 1 - .../effect-4-node/src/app.ts | 1 - .../node-express-streaming/src/app.ts | 1 - .../node-express-v5/src/app.ts | 1 - .../test-applications/node-express/src/app.ts | 1 - .../src/instrument.ts | 1 - .../tsx-express/instrument.mjs | 1 - .../suites/consola/instrument.mjs | 1 - .../suites/pino/instrument-auto-off.mjs | 1 - .../suites/pino/instrument.mjs | 1 - .../suites/public-api/logger/scenario.ts | 1 - .../public-api/logs-disabled/subject.ts | 28 +++++++ .../suites/public-api/logs-disabled/test.ts | 30 ++++++++ .../suites/public-api/logs/subject.ts | 1 - .../suites/winston/instrument.mjs | 1 - packages/core/src/client.ts | 2 +- packages/core/src/logs/internal.ts | 9 ++- packages/core/src/types/options.ts | 2 +- packages/core/test/lib/client.test.ts | 36 ++++----- .../test/lib/integrations/consola.test.ts | 2 - .../test/lib/logs/console-integration.test.ts | 2 - packages/core/test/lib/logs/internal.test.ts | 76 ++++++++----------- packages/deno/test/mod.test.ts | 3 - packages/node/test/sdk/client.test.ts | 7 +- 28 files changed, 115 insertions(+), 99 deletions(-) create mode 100644 dev-packages/node-integration-tests/suites/public-api/logs-disabled/subject.ts create mode 100644 dev-packages/node-integration-tests/suites/public-api/logs-disabled/test.ts diff --git a/dev-packages/e2e-tests/test-applications/deno-streamed/src/app.ts b/dev-packages/e2e-tests/test-applications/deno-streamed/src/app.ts index fccf12f5790c..5e8b7d123809 100644 --- a/dev-packages/e2e-tests/test-applications/deno-streamed/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/deno-streamed/src/app.ts @@ -22,7 +22,6 @@ Sentry.init({ traceLifecycle: 'stream', tracesSampleRate: 1, dataCollection: { userInfo: true }, - enableLogs: true, }); const port = 3030; diff --git a/dev-packages/e2e-tests/test-applications/deno/src/app.ts b/dev-packages/e2e-tests/test-applications/deno/src/app.ts index 89d242b03e2c..663b62914e51 100644 --- a/dev-packages/e2e-tests/test-applications/deno/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/deno/src/app.ts @@ -25,7 +25,6 @@ Sentry.init({ tunnel: 'http://localhost:3031/', tracesSampleRate: 1, dataCollection: { userInfo: true }, - enableLogs: true, }); const port = 3030; diff --git a/dev-packages/e2e-tests/test-applications/effect-3-browser/src/index.js b/dev-packages/e2e-tests/test-applications/effect-3-browser/src/index.js index 5c598efe2794..d48683c1e0f4 100644 --- a/dev-packages/e2e-tests/test-applications/effect-3-browser/src/index.js +++ b/dev-packages/e2e-tests/test-applications/effect-3-browser/src/index.js @@ -20,7 +20,6 @@ const AppLayer = Layer.mergeAll( release: 'e2e-test', environment: 'qa', tunnel: 'http://localhost:3031', - enableLogs: true, }), Layer.setTracer(Sentry.SentryEffectTracer), Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger), diff --git a/dev-packages/e2e-tests/test-applications/effect-3-node/src/app.ts b/dev-packages/e2e-tests/test-applications/effect-3-node/src/app.ts index 18bc0e2d4f12..6ddbc1fc5e28 100644 --- a/dev-packages/e2e-tests/test-applications/effect-3-node/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/effect-3-node/src/app.ts @@ -16,7 +16,6 @@ const SentryLive = Layer.mergeAll( debug: !!process.env.DEBUG, tunnel: 'http://localhost:3031/', tracesSampleRate: 1, - enableLogs: true, }), Layer.setTracer(Sentry.SentryEffectTracer), Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger), diff --git a/dev-packages/e2e-tests/test-applications/effect-4-browser/src/index.js b/dev-packages/e2e-tests/test-applications/effect-4-browser/src/index.js index 7cc0d78ba969..117e5636c692 100644 --- a/dev-packages/e2e-tests/test-applications/effect-4-browser/src/index.js +++ b/dev-packages/e2e-tests/test-applications/effect-4-browser/src/index.js @@ -20,7 +20,6 @@ const AppLayer = Layer.mergeAll( release: 'e2e-test', environment: 'qa', tunnel: 'http://localhost:3031', - enableLogs: true, }), Logger.layer([Sentry.SentryEffectLogger]), Layer.succeed(Tracer.Tracer, Sentry.SentryEffectTracer), diff --git a/dev-packages/e2e-tests/test-applications/effect-4-node/src/app.ts b/dev-packages/e2e-tests/test-applications/effect-4-node/src/app.ts index 25d5c21f41d3..7ccc484ea40f 100644 --- a/dev-packages/e2e-tests/test-applications/effect-4-node/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/effect-4-node/src/app.ts @@ -17,7 +17,6 @@ const SentryLive = Layer.mergeAll( debug: !!process.env.DEBUG, tunnel: 'http://localhost:3031/', tracesSampleRate: 1, - enableLogs: true, }), Logger.layer([Sentry.SentryEffectLogger]), Layer.succeed(Tracer.Tracer, Sentry.SentryEffectTracer), diff --git a/dev-packages/e2e-tests/test-applications/node-express-streaming/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express-streaming/src/app.ts index 5a0d1afa4141..f02a6afff084 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-streaming/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-streaming/src/app.ts @@ -7,7 +7,6 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, - enableLogs: true, traceLifecycle: 'stream', integrations: [ Sentry.spanStreamingIntegration(), diff --git a/dev-packages/e2e-tests/test-applications/node-express-v5/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express-v5/src/app.ts index 7b6db485e963..de62ad6a7eab 100644 --- a/dev-packages/e2e-tests/test-applications/node-express-v5/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-express-v5/src/app.ts @@ -14,7 +14,6 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, - enableLogs: true, integrations: [Sentry.nodeRuntimeMetricsIntegration({ collectionIntervalMs: 1_000 })], }); diff --git a/dev-packages/e2e-tests/test-applications/node-express/src/app.ts b/dev-packages/e2e-tests/test-applications/node-express/src/app.ts index fa352284e01d..c2b8076cdf2a 100644 --- a/dev-packages/e2e-tests/test-applications/node-express/src/app.ts +++ b/dev-packages/e2e-tests/test-applications/node-express/src/app.ts @@ -14,7 +14,6 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, - enableLogs: true, integrations: [ Sentry.nativeNodeFetchIntegration({ headersToSpanAttributes: { diff --git a/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/src/instrument.ts b/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/src/instrument.ts index 8a096bf201af..45db28c19a78 100644 --- a/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/src/instrument.ts +++ b/dev-packages/e2e-tests/test-applications/node-otel-without-tracing/src/instrument.ts @@ -18,7 +18,6 @@ Sentry.init({ // Tracing is completely disabled // Custom OTEL setup skipOpenTelemetrySetup: true, - enableLogs: true, }); // Create and configure NodeTracerProvider diff --git a/dev-packages/e2e-tests/test-applications/tsx-express/instrument.mjs b/dev-packages/e2e-tests/test-applications/tsx-express/instrument.mjs index a83e7afea09c..1d89289c1b49 100644 --- a/dev-packages/e2e-tests/test-applications/tsx-express/instrument.mjs +++ b/dev-packages/e2e-tests/test-applications/tsx-express/instrument.mjs @@ -7,5 +7,4 @@ Sentry.init({ debug: !!process.env.DEBUG, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1, - enableLogs: true, }); diff --git a/dev-packages/node-integration-tests/suites/consola/instrument.mjs b/dev-packages/node-integration-tests/suites/consola/instrument.mjs index 01b7cad88cc2..4ce4f3c0ffa9 100644 --- a/dev-packages/node-integration-tests/suites/consola/instrument.mjs +++ b/dev-packages/node-integration-tests/suites/consola/instrument.mjs @@ -6,6 +6,5 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0.0', environment: 'test', - enableLogs: true, transport: loggingTransport, }); diff --git a/dev-packages/node-integration-tests/suites/pino/instrument-auto-off.mjs b/dev-packages/node-integration-tests/suites/pino/instrument-auto-off.mjs index 6902acf03ccc..5ea7061a8ffb 100644 --- a/dev-packages/node-integration-tests/suites/pino/instrument-auto-off.mjs +++ b/dev-packages/node-integration-tests/suites/pino/instrument-auto-off.mjs @@ -5,6 +5,5 @@ Sentry.init({ dsn: process.env.SENTRY_DSN, release: '1.0', tracesSampleRate: 1.0, - enableLogs: true, integrations: [Sentry.pinoIntegration({ autoInstrument: false })], }); diff --git a/dev-packages/node-integration-tests/suites/pino/instrument.mjs b/dev-packages/node-integration-tests/suites/pino/instrument.mjs index 54bea36742dd..b3975e128c04 100644 --- a/dev-packages/node-integration-tests/suites/pino/instrument.mjs +++ b/dev-packages/node-integration-tests/suites/pino/instrument.mjs @@ -5,6 +5,5 @@ Sentry.init({ dsn: process.env.SENTRY_DSN, release: '1.0', tracesSampleRate: 1.0, - enableLogs: true, integrations: [Sentry.pinoIntegration({ error: { levels: ['error', 'fatal'] } })], }); diff --git a/dev-packages/node-integration-tests/suites/public-api/logger/scenario.ts b/dev-packages/node-integration-tests/suites/public-api/logger/scenario.ts index 5d769a14c03b..eac14291c9eb 100644 --- a/dev-packages/node-integration-tests/suites/public-api/logger/scenario.ts +++ b/dev-packages/node-integration-tests/suites/public-api/logger/scenario.ts @@ -6,7 +6,6 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0.0', environment: 'test', - enableLogs: true, transport: loggingTransport, }); diff --git a/dev-packages/node-integration-tests/suites/public-api/logs-disabled/subject.ts b/dev-packages/node-integration-tests/suites/public-api/logs-disabled/subject.ts new file mode 100644 index 000000000000..06eee985d7bf --- /dev/null +++ b/dev-packages/node-integration-tests/suites/public-api/logs-disabled/subject.ts @@ -0,0 +1,28 @@ +import * as Sentry from '@sentry/node'; +import { loggingTransport } from '@sentry-internal/node-integration-tests'; + +const client = new Sentry.NodeClient({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + enableLogs: false, + transport: loggingTransport, + stackParser: Sentry.defaultStackParser, + integrations: [], +}); + +const scope = new Sentry.Scope(); +scope.setClient(client); +client.init(); + +async function run(): Promise { + // Should be dropped because logs are disabled. + Sentry.logger.info('this log should not be captured', {}, { scope }); + + // Should be delivered — used as a sentinel so the test has a deterministic + // envelope to match instead of asserting on the absence of one. + scope.captureException(new Error('sentinel_error')); + + await client.flush(); +} + +// eslint-disable-next-line @typescript-eslint/no-floating-promises +void run(); diff --git a/dev-packages/node-integration-tests/suites/public-api/logs-disabled/test.ts b/dev-packages/node-integration-tests/suites/public-api/logs-disabled/test.ts new file mode 100644 index 000000000000..eab0632bb8e4 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/public-api/logs-disabled/test.ts @@ -0,0 +1,30 @@ +import { afterAll, describe, test } from 'vitest'; +import { cleanupChildProcesses, createRunner } from '../../../utils/runner'; + +describe('logs disabled', () => { + afterAll(() => { + cleanupChildProcesses(); + }); + + // With `enableLogs: false` the log is dropped at capture time, so it never reaches + // the transport. The sentinel error is the only envelope we expect — if a log + // envelope were emitted, it would arrive before the error and fail the assertion. + test('does not capture logs when enableLogs is disabled', async () => { + const runner = createRunner(__dirname, 'subject.ts') + .expect({ + event: { + exception: { + values: [ + { + type: 'Error', + value: 'sentinel_error', + }, + ], + }, + }, + }) + .start(); + + await runner.completed(); + }); +}); diff --git a/dev-packages/node-integration-tests/suites/public-api/logs/subject.ts b/dev-packages/node-integration-tests/suites/public-api/logs/subject.ts index 650a5112cfe1..bb64c10b2bc9 100644 --- a/dev-packages/node-integration-tests/suites/public-api/logs/subject.ts +++ b/dev-packages/node-integration-tests/suites/public-api/logs/subject.ts @@ -6,7 +6,6 @@ const client = new Sentry.NodeClient({ transport: loggingTransport, stackParser: Sentry.defaultStackParser, integrations: [], - enableLogs: true, dataCollection: { userInfo: true }, }); diff --git a/dev-packages/node-integration-tests/suites/winston/instrument.mjs b/dev-packages/node-integration-tests/suites/winston/instrument.mjs index e96cc26c71d8..7ac52e645e47 100644 --- a/dev-packages/node-integration-tests/suites/winston/instrument.mjs +++ b/dev-packages/node-integration-tests/suites/winston/instrument.mjs @@ -6,7 +6,6 @@ Sentry.init({ dsn: 'https://public@dsn.ingest.sentry.io/1337', release: '1.0.0', environment: 'test', - enableLogs: true, transport: loggingTransport, debug: true, }); diff --git a/packages/core/src/client.ts b/packages/core/src/client.ts index 836b4ca521c0..fdd867836ea1 100644 --- a/packages/core/src/client.ts +++ b/packages/core/src/client.ts @@ -267,7 +267,7 @@ export abstract class Client { // Backfill enableLogs option from _experiments.enableLogs // TODO(v11): Remove or change default value // eslint-disable-next-line typescript/no-deprecated - this._options.enableLogs = this._options.enableLogs ?? this._options._experiments?.enableLogs; + this._options.enableLogs = this._options.enableLogs ?? this._options._experiments?.enableLogs ?? true; // Setup log flushing with weight and timeout tracking if (this._options.enableLogs) { diff --git a/packages/core/src/logs/internal.ts b/packages/core/src/logs/internal.ts index 5987df008547..9453cadcf417 100644 --- a/packages/core/src/logs/internal.ts +++ b/packages/core/src/logs/internal.ts @@ -84,8 +84,13 @@ export function _INTERNAL_captureLog( return; } - const { release, environment, enableLogs = false, beforeSendLog } = client.getOptions(); - if (!enableLogs) { + const { release, environment, _experiments, enableLogs, beforeSendLog } = client.getOptions(); + + // todo(v11): Remove the experimental flag + // eslint-disable-next-line typescript/no-deprecated + const logsEnabled = enableLogs ?? _experiments?.enableLogs ?? true; + + if (!logsEnabled) { DEBUG_BUILD && debug.warn('logging option not enabled, log will not be captured.'); return; } diff --git a/packages/core/src/types/options.ts b/packages/core/src/types/options.ts index 4aa93e6ac12e..fc094b0aaa32 100644 --- a/packages/core/src/types/options.ts +++ b/packages/core/src/types/options.ts @@ -572,7 +572,7 @@ export interface ClientOptions { .spyOn(logsInternalModule, '_INTERNAL_flushLogsBuffer') .mockImplementation(() => undefined); - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); await client.close(); @@ -2938,32 +2938,32 @@ describe('Client', () => { }); describe('enableLogs', () => { - it('defaults to `undefined`', () => { + it('defaults to `true`', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); - expect(client.getOptions().enableLogs).toBeUndefined(); + expect(client.getOptions().enableLogs).toBe(true); }); - it('can be set as a top-level option', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + it('can be disabled via the top-level option', () => { + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: false }); const client = new TestClient(options); - expect(client.getOptions().enableLogs).toBe(true); + expect(client.getOptions().enableLogs).toBe(false); }); - it('can be set as an experimental option', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, _experiments: { enableLogs: true } }); + it('can be disabled via the experimental option', () => { + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, _experiments: { enableLogs: false } }); const client = new TestClient(options); - expect(client.getOptions().enableLogs).toBe(true); + expect(client.getOptions().enableLogs).toBe(false); }); test('top-level option takes precedence over experimental option', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, - _experiments: { enableLogs: false }, + enableLogs: false, + _experiments: { enableLogs: true }, }); const client = new TestClient(options); - expect(client.getOptions().enableLogs).toBe(true); + expect(client.getOptions().enableLogs).toBe(false); }); }); @@ -2979,7 +2979,6 @@ describe('Client', () => { it('flushes logs when weight exceeds 800KB', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, }); const client = new TestClient(options); const scope = new Scope(); @@ -2997,7 +2996,6 @@ describe('Client', () => { it('accumulates log weight without flushing when under threshold', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, }); const client = new TestClient(options); const scope = new Scope(); @@ -3015,7 +3013,6 @@ describe('Client', () => { it('flushes logs after idle timeout', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, }); const client = new TestClient(options); const scope = new Scope(); @@ -3037,7 +3034,6 @@ describe('Client', () => { it('does not reset idle timeout when new logs are captured', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, }); const client = new TestClient(options); const scope = new Scope(); @@ -3064,7 +3060,6 @@ describe('Client', () => { it('starts new timer after timeout completes and flushes', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, }); const client = new TestClient(options); const scope = new Scope(); @@ -3096,7 +3091,6 @@ describe('Client', () => { it('flushes logs on flush event', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, }); const client = new TestClient(options); const scope = new Scope(); @@ -3117,6 +3111,7 @@ describe('Client', () => { it('does not flush logs when logs are disabled', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, + enableLogs: false, }); const client = new TestClient(options); const scope = new Scope(); @@ -3136,7 +3131,6 @@ describe('Client', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, }); const client = new TestClient(options); const scope = new Scope(); @@ -3154,9 +3148,7 @@ describe('Client', () => { it('flush() drains the log buffer when client has no transport', async () => { // Client without DSN — _transport is undefined - const options = getDefaultTestClientOptions({ - enableLogs: true, - }); + const options = getDefaultTestClientOptions({}); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); diff --git a/packages/core/test/lib/integrations/consola.test.ts b/packages/core/test/lib/integrations/consola.test.ts index 0ab7a3cc1e98..6cdaedc64cba 100644 --- a/packages/core/test/lib/integrations/consola.test.ts +++ b/packages/core/test/lib/integrations/consola.test.ts @@ -32,10 +32,8 @@ describe('createConsolaReporter', () => { beforeEach(() => { vi.clearAllMocks(); - // Create a test client with enableLogs: true mockClient = new TestClient({ ...getDefaultTestClientOptions({ dsn: 'https://username@domain/123' }), - enableLogs: true, normalizeDepth: 3, normalizeMaxBreadth: 1000, }); diff --git a/packages/core/test/lib/logs/console-integration.test.ts b/packages/core/test/lib/logs/console-integration.test.ts index ef39b4ebdb15..a2a878365064 100644 --- a/packages/core/test/lib/logs/console-integration.test.ts +++ b/packages/core/test/lib/logs/console-integration.test.ts @@ -44,7 +44,6 @@ describe('consoleLoggingIntegration', () => { client = new TestClient({ ...getDefaultTestClientOptions({ dsn: 'https://username@domain/123' }), - enableLogs: true, normalizeDepth: 3, normalizeMaxBreadth: 1000, }); @@ -418,7 +417,6 @@ describe('consoleLoggingIntegration', () => { it('only captures configured levels', () => { const filteredClient = new TestClient({ ...getDefaultTestClientOptions({ dsn: 'https://username@domain/123' }), - enableLogs: true, }); vi.mocked(getClient).mockReturnValue(filteredClient); diff --git a/packages/core/test/lib/logs/internal.test.ts b/packages/core/test/lib/logs/internal.test.ts index 608193b4a838..c98cd8574692 100644 --- a/packages/core/test/lib/logs/internal.test.ts +++ b/packages/core/test/lib/logs/internal.test.ts @@ -22,7 +22,7 @@ describe('_INTERNAL_captureLog', () => { _INTERNAL_resetSequenceNumber(); }); it('captures and sends logs', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -43,9 +43,9 @@ describe('_INTERNAL_captureLog', () => { ); }); - it('does not capture logs when enableLogs is not enabled', () => { + it('does not capture logs when enableLogs is disabled', () => { const logWarnSpy = vi.spyOn(loggerModule.debug, 'warn').mockImplementation(() => undefined); - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: false }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -59,7 +59,7 @@ describe('_INTERNAL_captureLog', () => { }); it('includes trace context when available', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -81,7 +81,6 @@ describe('_INTERNAL_captureLog', () => { it('includes release and environment in log attributes when available', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, release: '1.0.0', environment: 'test', }); @@ -108,7 +107,6 @@ describe('_INTERNAL_captureLog', () => { it('includes SDK metadata in log attributes when available', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, }); const client = new TestClient(options); const scope = new Scope(); @@ -140,7 +138,6 @@ describe('_INTERNAL_captureLog', () => { it('does not include SDK metadata in log attributes when not available', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, }); const client = new TestClient(options); const scope = new Scope(); @@ -161,7 +158,7 @@ describe('_INTERNAL_captureLog', () => { describe('attributes', () => { it('includes custom attributes in log', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -190,7 +187,7 @@ describe('_INTERNAL_captureLog', () => { }); it('applies scope attributes attributes to log', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -251,7 +248,7 @@ describe('_INTERNAL_captureLog', () => { }); it('flushes logs buffer when it reaches max size', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -273,7 +270,7 @@ describe('_INTERNAL_captureLog', () => { }); it('does not flush logs buffer when it is empty', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const mockSendEnvelope = vi.spyOn(client as any, 'sendEnvelope').mockImplementation(() => {}); @@ -282,7 +279,7 @@ describe('_INTERNAL_captureLog', () => { }); it('handles parameterized strings correctly', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -310,7 +307,7 @@ describe('_INTERNAL_captureLog', () => { }); it('does not set the template attribute if there are no parameters', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -332,7 +329,6 @@ describe('_INTERNAL_captureLog', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, beforeSendLog, }); const client = new TestClient(options); @@ -396,7 +392,6 @@ describe('_INTERNAL_captureLog', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, beforeSendLog, }); const client = new TestClient(options); @@ -422,7 +417,7 @@ describe('_INTERNAL_captureLog', () => { it('emits beforeCaptureLog and afterCaptureLog events', () => { const beforeCaptureLogSpy = vi.spyOn(TestClient.prototype, 'emit'); - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -442,7 +437,7 @@ describe('_INTERNAL_captureLog', () => { describe('replay integration with onlyIfSampled', () => { it('includes replay ID for sampled sessions', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -474,7 +469,7 @@ describe('_INTERNAL_captureLog', () => { }); it('excludes replay ID for unsampled sessions when onlyIfSampled=true', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -501,7 +496,7 @@ describe('_INTERNAL_captureLog', () => { }); it('includes replay ID for buffer mode sessions', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -536,7 +531,7 @@ describe('_INTERNAL_captureLog', () => { }); it('handles missing replay integration gracefully', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -555,7 +550,6 @@ describe('_INTERNAL_captureLog', () => { it('combines replay ID with other log attributes', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, release: '1.0.0', environment: 'test', }); @@ -607,7 +601,7 @@ describe('_INTERNAL_captureLog', () => { }); it('does not set replay ID attribute when getReplayId returns null or undefined', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -635,7 +629,7 @@ describe('_INTERNAL_captureLog', () => { }); it('sets replay_is_buffering attribute when replay is in buffer mode', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -668,7 +662,7 @@ describe('_INTERNAL_captureLog', () => { }); it('does not set replay_is_buffering attribute when replay is in session mode', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -698,7 +692,7 @@ describe('_INTERNAL_captureLog', () => { }); it('does not set replay_is_buffering attribute when replay is undefined mode', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -728,7 +722,7 @@ describe('_INTERNAL_captureLog', () => { }); it('does not set replay_is_buffering attribute when no replay ID is available', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -756,7 +750,7 @@ describe('_INTERNAL_captureLog', () => { }); it('does not set replay_is_buffering attribute when replay integration is missing', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -777,7 +771,6 @@ describe('_INTERNAL_captureLog', () => { it('combines replay_is_buffering with other replay attributes', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, release: '1.0.0', environment: 'test', }); @@ -837,7 +830,6 @@ describe('_INTERNAL_captureLog', () => { it('includes user data in log attributes', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, }); const client = new TestClient(options); const scope = new Scope(); @@ -871,7 +863,6 @@ describe('_INTERNAL_captureLog', () => { it('includes partial user data when only some fields are available', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, sendDefaultPii: true, }); const client = new TestClient(options); @@ -897,7 +888,6 @@ describe('_INTERNAL_captureLog', () => { it('includes user email and username without id', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, sendDefaultPii: true, }); const client = new TestClient(options); @@ -928,7 +918,6 @@ describe('_INTERNAL_captureLog', () => { it('does not include user data when user object is empty', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, sendDefaultPii: true, }); const client = new TestClient(options); @@ -947,7 +936,6 @@ describe('_INTERNAL_captureLog', () => { it('combines user data with other log attributes', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, sendDefaultPii: true, release: '1.0.0', environment: 'test', @@ -1002,7 +990,6 @@ describe('_INTERNAL_captureLog', () => { it('handles user data with non-string values', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, sendDefaultPii: true, }); const client = new TestClient(options); @@ -1033,7 +1020,6 @@ describe('_INTERNAL_captureLog', () => { it('preserves existing user attributes in log and does not override them', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, sendDefaultPii: true, }); const client = new TestClient(options); @@ -1077,7 +1063,6 @@ describe('_INTERNAL_captureLog', () => { it('only adds scope user data for attributes that do not already exist', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, sendDefaultPii: true, }); const client = new TestClient(options); @@ -1127,7 +1112,6 @@ describe('_INTERNAL_captureLog', () => { it('overrides user-provided system attributes with SDK values', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, - enableLogs: true, release: 'sdk-release-1.0.0', environment: 'sdk-environment', }); @@ -1188,7 +1172,7 @@ describe('_INTERNAL_captureLog', () => { it('increments the sequence number across consecutive logs', () => { vi.spyOn(timeModule, 'timestampInSeconds').mockReturnValue(1000.001); - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -1215,7 +1199,7 @@ describe('_INTERNAL_captureLog', () => { return log; }); - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true, beforeSendLog }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, beforeSendLog }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -1235,7 +1219,7 @@ describe('_INTERNAL_captureLog', () => { it('produces monotonically increasing sequence numbers within the same millisecond', () => { vi.spyOn(timeModule, 'timestampInSeconds').mockReturnValue(1000.001); - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -1258,7 +1242,7 @@ describe('_INTERNAL_captureLog', () => { }); it('resets the sequence number via _INTERNAL_resetSequenceNumber', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -1280,7 +1264,7 @@ describe('_INTERNAL_captureLog', () => { describe.runIf(hasToWellFormed)('lone surrogate sanitization', () => { it('sanitizes lone surrogates in log message body', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -1292,7 +1276,7 @@ describe('_INTERNAL_captureLog', () => { }); it('sanitizes lone surrogates in parameterized (fmt) log message body', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -1305,7 +1289,7 @@ describe('_INTERNAL_captureLog', () => { }); it('sanitizes lone surrogates in log attribute values', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -1327,7 +1311,7 @@ describe('_INTERNAL_captureLog', () => { }); it('sanitizes lone surrogates in log attribute keys', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); @@ -1349,7 +1333,7 @@ describe('_INTERNAL_captureLog', () => { }); it('preserves valid emoji in log messages and attributes', () => { - const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: true }); + const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN }); const client = new TestClient(options); const scope = new Scope(); scope.setClient(client); diff --git a/packages/deno/test/mod.test.ts b/packages/deno/test/mod.test.ts index 2a7e208b2ff2..1f560f215460 100644 --- a/packages/deno/test/mod.test.ts +++ b/packages/deno/test/mod.test.ts @@ -117,7 +117,6 @@ Deno.test('logger.info captures a log envelope item', async () => { const envelopes: Array = []; const client = new DenoClient({ dsn: 'https://233a45e5efe34c47a3536797ce15dafa@nothing.here/5650507', - enableLogs: true, integrations: getDefaultIntegrations({}), stackParser: createStackParser(nodeStackLineParser()), transport: makeTestTransport(envelope => { @@ -153,7 +152,6 @@ Deno.test('logger.info captures a log envelope item', async () => { Deno.test('adds server.address to log attributes', () => { const client = new DenoClient({ dsn: 'https://233a45e5efe34c47a3536797ce15dafa@nothing.here/5650507', - enableLogs: true, serverName: 'test-server', integrations: getDefaultIntegrations({}), stackParser: createStackParser(nodeStackLineParser()), @@ -169,7 +167,6 @@ Deno.test('adds server.address to log attributes', () => { Deno.test('preserves existing log attributes when adding server.address', () => { const client = new DenoClient({ dsn: 'https://233a45e5efe34c47a3536797ce15dafa@nothing.here/5650507', - enableLogs: true, serverName: 'test-server', integrations: getDefaultIntegrations({}), stackParser: createStackParser(nodeStackLineParser()), diff --git a/packages/node/test/sdk/client.test.ts b/packages/node/test/sdk/client.test.ts index 8934982ca4a1..9e00b357bf3e 100644 --- a/packages/node/test/sdk/client.test.ts +++ b/packages/node/test/sdk/client.test.ts @@ -55,6 +55,7 @@ describe('NodeClient', () => { runtime: { name: 'node', version: expect.any(String) }, serverName: expect.any(String), tracesSampleRate: 1, + enableLogs: true, }); }); @@ -301,7 +302,7 @@ describe('NodeClient', () => { describe('log capture', () => { it('adds server name to log attributes', () => { - const options = getDefaultNodeClientOptions({ enableLogs: true }); + const options = getDefaultNodeClientOptions(); const client = new NodeClient(options); const log: Log = { level: 'info', message: 'test message', attributes: {} }; @@ -314,7 +315,7 @@ describe('NodeClient', () => { it('preserves existing log attributes', () => { const serverName = 'test-server'; - const options = getDefaultNodeClientOptions({ serverName, enableLogs: true }); + const options = getDefaultNodeClientOptions({ serverName }); const client = new NodeClient(options); const log: Log = { level: 'info', message: 'test message', attributes: { 'existing.attr': 'value' } }; @@ -375,7 +376,7 @@ describe('NodeClient', () => { it('stops log capture if it was started', async () => { const processOffSpy = vi.spyOn(process, 'off'); - const client = new NodeClient(getDefaultNodeClientOptions({ enableLogs: true })); + const client = new NodeClient(getDefaultNodeClientOptions()); const result = await client.close(); From a5bbc0368b5ea60faaf062933e9d03b06b741055 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 24 Jul 2026 16:01:35 +0200 Subject: [PATCH 2/6] test(core): Account for backfilled enableLogs in getOptions assertion The client constructor backfills `enableLogs` onto its options, so the strict `getOptions()` equality check now needs the resolved default. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/core/test/lib/client.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/test/lib/client.test.ts b/packages/core/test/lib/client.test.ts index 81b02d850e6a..46d9331ff47c 100644 --- a/packages/core/test/lib/client.test.ts +++ b/packages/core/test/lib/client.test.ts @@ -103,7 +103,7 @@ describe('Client', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, test: true }); const client = new TestClient(options); - expect(client.getOptions()).toEqual({ attachStacktrace: true, traceLifecycle: 'stream', ...options }); + expect(client.getOptions()).toEqual({ attachStacktrace: true, traceLifecycle: 'stream', ...options, enableLogs: true }); }); test('defaults traceLifecycle to stream', () => { From f073283ef7cd8183619a308951dc8cadaf0473ef Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 24 Jul 2026 16:04:01 +0200 Subject: [PATCH 3/6] test(node): Make logs-disabled test deterministically catch leaks Flush the log buffer before capturing the sentinel error so a leaked log envelope arrives first and fails the ordered `event` expectation. Previously the error was sent first and the runner could complete before a stray log arrived, letting a broken disable path pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../suites/public-api/logs-disabled/subject.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dev-packages/node-integration-tests/suites/public-api/logs-disabled/subject.ts b/dev-packages/node-integration-tests/suites/public-api/logs-disabled/subject.ts index 06eee985d7bf..6f6112423614 100644 --- a/dev-packages/node-integration-tests/suites/public-api/logs-disabled/subject.ts +++ b/dev-packages/node-integration-tests/suites/public-api/logs-disabled/subject.ts @@ -14,11 +14,14 @@ scope.setClient(client); client.init(); async function run(): Promise { - // Should be dropped because logs are disabled. Sentry.logger.info('this log should not be captured', {}, { scope }); - // Should be delivered — used as a sentinel so the test has a deterministic - // envelope to match instead of asserting on the absence of one. + // Flush the log buffer before the sentinel is captured. If the disable path is + // broken, the leaked log envelope is sent here and arrives before the error, + // failing the ordered `event` expectation. If logs are correctly disabled, + // the buffer is empty and only the sentinel error is delivered. + await client.flush(); + scope.captureException(new Error('sentinel_error')); await client.flush(); From efe6fef68e461fb0b3bad7956eef614c79b598ff Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 24 Jul 2026 16:11:47 +0200 Subject: [PATCH 4/6] refactor(core): Simplify enableLogs guard to a plain default The constructor already backfills `enableLogs` from `_experiments.enableLogs`, so re-reading `_experiments` in the capture guard was dead code. Reduce it to a plain destructure default, matching the original shape. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/core/src/logs/internal.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/core/src/logs/internal.ts b/packages/core/src/logs/internal.ts index 9453cadcf417..efbbed137cc2 100644 --- a/packages/core/src/logs/internal.ts +++ b/packages/core/src/logs/internal.ts @@ -84,13 +84,8 @@ export function _INTERNAL_captureLog( return; } - const { release, environment, _experiments, enableLogs, beforeSendLog } = client.getOptions(); - - // todo(v11): Remove the experimental flag - // eslint-disable-next-line typescript/no-deprecated - const logsEnabled = enableLogs ?? _experiments?.enableLogs ?? true; - - if (!logsEnabled) { + const { release, environment, enableLogs = true, beforeSendLog } = client.getOptions(); + if (!enableLogs) { DEBUG_BUILD && debug.warn('logging option not enabled, log will not be captured.'); return; } From de83bc925365d922a4133a5088643374c7a31684 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Fri, 24 Jul 2026 16:13:24 +0200 Subject: [PATCH 5/6] docs(core): Update stale enableLogs backfill TODO The default has now been flipped, so the "or change default value" branch of the TODO is done. Narrow it to removing the deprecated experimental flag, matching the adjacent enableMetrics TODO. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/core/src/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/client.ts b/packages/core/src/client.ts index fdd867836ea1..2b3338bfe7f2 100644 --- a/packages/core/src/client.ts +++ b/packages/core/src/client.ts @@ -265,7 +265,7 @@ export abstract class Client { } // Backfill enableLogs option from _experiments.enableLogs - // TODO(v11): Remove or change default value + // todo(v11): Remove the experimental flag // eslint-disable-next-line typescript/no-deprecated this._options.enableLogs = this._options.enableLogs ?? this._options._experiments?.enableLogs ?? true; From 8a28f394b10dd70749475384535b0d0c5aeadc13 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 29 Jul 2026 10:11:23 +0200 Subject: [PATCH 6/6] docs(logs): Remove stale "requires enableLogs" references Logs default to `true` now, so the JSDoc note that the logger API and logging integrations require `enableLogs` to be enabled is no longer accurate. Drop the clause, the redundant `enableLogs: true` from init examples/READMEs, and the `_experiments.enableLogs` flag from the shared browser logger test init. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../suites/public-api/logger/init.js | 4 ---- packages/core/src/integrations/consola.ts | 4 ++-- packages/core/src/logs/console-integration.ts | 3 +-- packages/core/src/logs/public-api.ts | 12 ++++++------ packages/core/test/lib/client.test.ts | 7 ++++++- packages/effect/README.md | 2 -- packages/node/src/integrations/pino.ts | 3 +-- packages/node/src/integrations/winston.ts | 2 +- packages/node/src/logs/exports.ts | 12 ++++++------ packages/vercel-edge/src/logs/exports.ts | 12 ++++++------ 10 files changed, 29 insertions(+), 32 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/init.js b/dev-packages/browser-integration-tests/suites/public-api/logger/init.js index 75a97155a8f1..d9c534b801cd 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/logger/init.js +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/init.js @@ -5,8 +5,4 @@ window.Sentry = Sentry; Sentry.init({ traceLifecycle: 'static', dsn: 'https://public@dsn.ingest.sentry.io/1337', - // purposefully testing against the experimental flag here - _experiments: { - enableLogs: true, - }, }); diff --git a/packages/core/src/integrations/consola.ts b/packages/core/src/integrations/consola.ts index a5b7d44a3b33..6385d330ec37 100644 --- a/packages/core/src/integrations/consola.ts +++ b/packages/core/src/integrations/consola.ts @@ -191,7 +191,7 @@ export interface ConsolaLogObject { const DEFAULT_CAPTURED_LEVELS: Array = ['trace', 'debug', 'info', 'warn', 'error', 'fatal']; /** - * Creates a new Sentry reporter for Consola that forwards logs to Sentry. Requires the `enableLogs` option to be enabled. + * Creates a new Sentry reporter for Consola that forwards logs to Sentry. * * **Note: This integration supports Consola v3.x only.** The reporter interface and log object structure * may differ in other versions of Consola. @@ -205,7 +205,7 @@ const DEFAULT_CAPTURED_LEVELS: Array = ['trace', 'debug', 'inf * import { consola } from 'consola'; * * Sentry.init({ - * enableLogs: true, + * dsn: '__DSN__', * }); * * const sentryReporter = Sentry.createConsolaReporter({ diff --git a/packages/core/src/logs/console-integration.ts b/packages/core/src/logs/console-integration.ts index f04f9e540ea9..b31baacaa65e 100644 --- a/packages/core/src/logs/console-integration.ts +++ b/packages/core/src/logs/console-integration.ts @@ -95,7 +95,7 @@ const _consoleLoggingIntegration = ((options: Partial = { }) satisfies IntegrationFn; /** - * Captures calls to the `console` API as logs in Sentry. Requires the `enableLogs` option to be enabled. + * Captures calls to the `console` API as logs in Sentry. * * @experimental This feature is experimental and may be changed or removed in future versions. * @@ -109,7 +109,6 @@ const _consoleLoggingIntegration = ((options: Partial = { * import * as Sentry from '@sentry/browser'; * * Sentry.init({ - * enableLogs: true, * integrations: [Sentry.consoleLoggingIntegration({ levels: ['error', 'warn'] })], * }); * ``` diff --git a/packages/core/src/logs/public-api.ts b/packages/core/src/logs/public-api.ts index 540ede61da79..1261edc9da75 100644 --- a/packages/core/src/logs/public-api.ts +++ b/packages/core/src/logs/public-api.ts @@ -30,7 +30,7 @@ interface CaptureLogMetadata { } /** - * @summary Capture a log with the `trace` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `trace` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { userId: 100, route: '/dashboard' }. @@ -64,7 +64,7 @@ export function trace( } /** - * @summary Capture a log with the `debug` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `debug` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { component: 'Header', state: 'loading' }. @@ -99,7 +99,7 @@ export function debug( } /** - * @summary Capture a log with the `info` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `info` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { feature: 'checkout', status: 'completed' }. @@ -134,7 +134,7 @@ export function info( } /** - * @summary Capture a log with the `warn` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `warn` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { browser: 'Chrome', version: '91.0' }. @@ -170,7 +170,7 @@ export function warn( } /** - * @summary Capture a log with the `error` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `error` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { error: 'NetworkError', url: '/api/data' }. @@ -207,7 +207,7 @@ export function error( } /** - * @summary Capture a log with the `fatal` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `fatal` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { appState: 'corrupted', sessionId: 'abc-123' }. diff --git a/packages/core/test/lib/client.test.ts b/packages/core/test/lib/client.test.ts index 46d9331ff47c..ddc992476533 100644 --- a/packages/core/test/lib/client.test.ts +++ b/packages/core/test/lib/client.test.ts @@ -103,7 +103,12 @@ describe('Client', () => { const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, test: true }); const client = new TestClient(options); - expect(client.getOptions()).toEqual({ attachStacktrace: true, traceLifecycle: 'stream', ...options, enableLogs: true }); + expect(client.getOptions()).toEqual({ + attachStacktrace: true, + traceLifecycle: 'stream', + ...options, + enableLogs: true, + }); }); test('defaults traceLifecycle to stream', () => { diff --git a/packages/effect/README.md b/packages/effect/README.md index bfe3c51ce8dc..aa733a4e528e 100644 --- a/packages/effect/README.md +++ b/packages/effect/README.md @@ -27,7 +27,6 @@ const SentryLive = Layer.mergeAll( Sentry.effectLayer({ dsn: '__DSN__', tracesSampleRate: 1.0, - enableLogs: true, }), Layer.setTracer(Sentry.SentryEffectTracer), Logger.replace(Logger.defaultLogger, Sentry.SentryEffectLogger), @@ -59,7 +58,6 @@ const SentryLive = Layer.mergeAll( Sentry.effectLayer({ dsn: '__DSN__', tracesSampleRate: 1.0, - enableLogs: true, }), Layer.succeed(Tracer.Tracer, Sentry.SentryEffectTracer), Logger.layer([Sentry.SentryEffectLogger]), diff --git a/packages/node/src/integrations/pino.ts b/packages/node/src/integrations/pino.ts index 842ea9838f10..27c421b35b95 100644 --- a/packages/node/src/integrations/pino.ts +++ b/packages/node/src/integrations/pino.ts @@ -79,8 +79,7 @@ type PinoOptions = { */ log: { /** - * Levels that trigger capturing of logs. Logs are only captured if - * `enableLogs` is enabled. + * Levels that trigger capturing of logs. * * @default ["trace", "debug", "info", "warn", "error", "fatal"] */ diff --git a/packages/node/src/integrations/winston.ts b/packages/node/src/integrations/winston.ts index 1d60c66d1f37..fd0d510599d4 100644 --- a/packages/node/src/integrations/winston.ts +++ b/packages/node/src/integrations/winston.ts @@ -45,7 +45,7 @@ interface WinstonTransportOptions { } /** - * Creates a new Sentry Winston transport that fowards logs to Sentry. Requires the `enableLogs` option to be enabled. + * Creates a new Sentry Winston transport that fowards logs to Sentry. * * Supports Winston 3.x.x. * diff --git a/packages/node/src/logs/exports.ts b/packages/node/src/logs/exports.ts index a4a6ee2fef69..166d8a8c6d01 100644 --- a/packages/node/src/logs/exports.ts +++ b/packages/node/src/logs/exports.ts @@ -1,7 +1,7 @@ import { captureLog, type CaptureLogArgs } from './capture'; /** - * @summary Capture a log with the `trace` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `trace` level. * * You can either pass a message and attributes or a message template, params and attributes. * @@ -28,7 +28,7 @@ export function trace(...args: CaptureLogArgs): void { } /** - * @summary Capture a log with the `debug` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `debug` level. * * You can either pass a message and attributes or a message template, params and attributes. * @@ -55,7 +55,7 @@ export function debug(...args: CaptureLogArgs): void { } /** - * @summary Capture a log with the `info` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `info` level. * * You can either pass a message and attributes or a message template, params and attributes. * @@ -82,7 +82,7 @@ export function info(...args: CaptureLogArgs): void { } /** - * @summary Capture a log with the `warn` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `warn` level. * * You can either pass a message and attributes or a message template, params and attributes. * @@ -110,7 +110,7 @@ export function warn(...args: CaptureLogArgs): void { } /** - * @summary Capture a log with the `error` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `error` level. * * You can either pass a message and attributes or a message template, params and attributes. * @@ -138,7 +138,7 @@ export function error(...args: CaptureLogArgs): void { } /** - * @summary Capture a log with the `fatal` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `fatal` level. * * You can either pass a message and attributes or a message template, params and attributes. * diff --git a/packages/vercel-edge/src/logs/exports.ts b/packages/vercel-edge/src/logs/exports.ts index c21477e378b3..5a7e065eb3ee 100644 --- a/packages/vercel-edge/src/logs/exports.ts +++ b/packages/vercel-edge/src/logs/exports.ts @@ -19,7 +19,7 @@ function captureLog( } /** - * @summary Capture a log with the `trace` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `trace` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { userId: 100, route: '/dashboard' }. @@ -48,7 +48,7 @@ export function trace(message: ParameterizedString, attributes?: Log['attributes } /** - * @summary Capture a log with the `debug` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `debug` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { component: 'Header', state: 'loading' }. @@ -78,7 +78,7 @@ export function debug(message: ParameterizedString, attributes?: Log['attributes } /** - * @summary Capture a log with the `info` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `info` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { feature: 'checkout', status: 'completed' }. @@ -108,7 +108,7 @@ export function info(message: ParameterizedString, attributes?: Log['attributes' } /** - * @summary Capture a log with the `warn` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `warn` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { browser: 'Chrome', version: '91.0' }. @@ -139,7 +139,7 @@ export function warn(message: ParameterizedString, attributes?: Log['attributes' } /** - * @summary Capture a log with the `error` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `error` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { error: 'NetworkError', url: '/api/data' }. @@ -171,7 +171,7 @@ export function error(message: ParameterizedString, attributes?: Log['attributes } /** - * @summary Capture a log with the `fatal` level. Requires the `enableLogs` option to be enabled. + * @summary Capture a log with the `fatal` level. * * @param message - The message to log. * @param attributes - Arbitrary structured data that stores information about the log - e.g., { appState: 'corrupted', sessionId: 'abc-123' }.