Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ window.Sentry = Sentry;
Sentry.init({
traceLifecycle: 'static',
dsn: 'https://public@dsn.ingest.sentry.io/1337',
enableLogs: true,
integrations: [Sentry.consoleLoggingIntegration()],
});

This file was deleted.

This file was deleted.

21 changes: 9 additions & 12 deletions docs/migration/v11-end-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,18 +471,20 @@ Sentry.init({

In Node, Bun, Vercel Edge and Cloudflare you can also set the `SENTRY_TRACE_LIFECYCLE=static` environment variable instead. The static lifecycle only exists for backwards compatibility and is planned for removal in a future major version, so treat this as a temporary measure.

### Logs are enabled by default
### The `enableLogs` option was removed

Affected SDKs: All SDKs.

Logging follows an opt-in-by-usage model similar to metrics: you are opted in when you call `Sentry.logger.*` or explicitly enable a logging integration. The default value of `enableLogs` is now `true`, and logging integrations do not emit logs unless explicitly enabled.

To opt out of logging entirely, set `enableLogs` to `false`:
The `enableLogs` option was removed. Logging now follows an opt-in-by-usage model similar to metrics: logs are captured whenever you call `Sentry.logger.*` or add a logging integration (such as `consoleLoggingIntegration()` or the Pino integration). There is no longer an option to disable logging once you use a logging API or integration.

```js
// before
Sentry.init({
enableLogs: false,
enableLogs: true,
});

// after: no option needed, logs are captured when you use a logging API or integration
Sentry.init({});
```

### Browser sessions use `unhandled` instead of `crashed`
Expand Down Expand Up @@ -691,7 +693,7 @@ Sentry.init({
});
```

- The `_experiments.enableLogs` option was removed. Logs are now enabled by default, so if you were opting in via `_experiments.enableLogs: true` you can simply omit the option. Use the top-level `enableLogs: false` to opt out.
- The `_experiments.enableLogs` and top-level `enableLogs` options were removed. Logs are now captured whenever you use a logging API (`Sentry.logger.*`) or add a logging integration, so you can simply omit the option.

```js
// before
Expand All @@ -701,13 +703,8 @@ Sentry.init({
},
});

// after: logs are enabled by default, no option needed
// after: no option needed
Sentry.init({});

// or, to opt out
Sentry.init({
enableLogs: false,
});
```

- The deprecated `trackFetchStreamPerformance` option of `browserTracingIntegration` was removed. To track the duration of streamed fetch response bodies, add `fetchStreamPerformanceIntegration()` to your `integrations` array instead.
Expand Down
6 changes: 1 addition & 5 deletions packages/core/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,8 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
});
}

this._options.enableLogs ??= true;

// Setup log flushing with weight and timeout tracking
if (this._options.enableLogs) {
setupWeightBasedFlushing(this, 'afterCaptureLog', 'flushLogs', estimateLogSizeInBytes, _INTERNAL_flushLogsBuffer);
}
setupWeightBasedFlushing(this, 'afterCaptureLog', 'flushLogs', estimateLogSizeInBytes, _INTERNAL_flushLogsBuffer);

const enableMetrics = this._options.enableMetrics ?? true;

Expand Down
9 changes: 2 additions & 7 deletions packages/core/src/logs/console-integration.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { getClient } from '../currentScopes';
import { DEBUG_BUILD } from '../debug-build';
import { addConsoleInstrumentationHandler } from '../instrument/console';
import { defineIntegration } from '../integration';
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../semanticAttributes';
import type { ConsoleLevel } from '../types/instrument';
import type { IntegrationFn } from '../types/integration';
import { CONSOLE_LEVELS, debug } from '../utils/debug-logger';
import { CONSOLE_LEVELS } from '../utils/debug-logger';
import { isPlainObject } from '../utils/is';
import { normalize } from '../utils/normalize';
import { _INTERNAL_captureLog } from './internal';
Expand All @@ -27,11 +26,7 @@ const _consoleLoggingIntegration = ((options: Partial<CaptureConsoleOptions> = {
return {
name: INTEGRATION_NAME,
setup(client) {
const { enableLogs, normalizeDepth = 3, normalizeMaxBreadth = 1_000 } = client.getOptions();
if (!enableLogs) {
DEBUG_BUILD && debug.warn('`enableLogs` is not enabled, ConsoleLogs integration disabled');
return;
}
const { normalizeDepth = 3, normalizeMaxBreadth = 1_000 } = client.getOptions();

const unsubscribe = addConsoleInstrumentationHandler(({ args, level }) => {
if (getClient() !== client || !levels.includes(level)) {
Expand Down
6 changes: 1 addition & 5 deletions packages/core/src/logs/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,7 @@ export function _INTERNAL_captureLog(
return;
}

const { release, environment, enableLogs = true, beforeSendLog } = client.getOptions();
if (!enableLogs) {
DEBUG_BUILD && debug.warn('logging option not enabled, log will not be captured.');
return;
}
const { release, environment, beforeSendLog } = client.getOptions();

const [, traceContext] = _getTraceInfoFromScope(client, currentScope);

Expand Down
7 changes: 0 additions & 7 deletions packages/core/src/types/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -509,13 +509,6 @@ export interface ClientOptions<TO extends BaseTransportOptions = BaseTransportOp
*/
orgId?: `${number}` | number;

/**
* If logs support should be enabled.
*
* @default true
*/
enableLogs?: boolean;

/**
* An event-processing callback for logs, guaranteed to be invoked after all other log
* processors. This allows a log to be modified or dropped before it's sent.
Expand Down
33 changes: 0 additions & 33 deletions packages/core/test/lib/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,6 @@ describe('Client', () => {
attachStacktrace: true,
traceLifecycle: 'stream',
...options,
enableLogs: true,
});
});

Expand Down Expand Up @@ -3372,20 +3371,6 @@ describe('Client', () => {
});
});

describe('enableLogs', () => {
it('defaults to `true`', () => {
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN });
const client = new TestClient(options);
expect(client.getOptions().enableLogs).toBe(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(false);
});
});

describe('log weight-based flushing', () => {
beforeEach(() => {
vi.useFakeTimers();
Expand Down Expand Up @@ -3527,24 +3512,6 @@ describe('Client', () => {
expect(sendEnvelopeSpy).toHaveBeenCalledTimes(1);
});

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();
scope.setClient(client);

const sendEnvelopeSpy = vi.spyOn(client, 'sendEnvelope');

// Create a large log message
const largeMessage = 'x'.repeat(400_000);
_INTERNAL_captureLog({ message: largeMessage, level: 'info' }, scope);

expect(sendEnvelopeSpy).not.toHaveBeenCalled();
});

it('uses safeUnref on flush timer to not block process exit', () => {
const safeUnrefSpy = vi.spyOn(timerModule, 'safeUnref');

Expand Down
15 changes: 0 additions & 15 deletions packages/core/test/lib/logs/internal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,6 @@ describe('_INTERNAL_captureLog', () => {
);
});

it('does not capture logs when enableLogs is disabled', () => {
const logWarnSpy = vi.spyOn(loggerModule.debug, 'warn').mockImplementation(() => undefined);
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN, enableLogs: false });
const client = new TestClient(options);
const scope = new Scope();
scope.setClient(client);

_INTERNAL_captureLog({ level: 'info', message: 'test log message' }, scope);

expect(logWarnSpy).toHaveBeenCalledWith('logging option not enabled, log will not be captured.');
expect(_INTERNAL_getLogBuffer(client)).toBeUndefined();

logWarnSpy.mockRestore();
});

it('includes trace context when available', () => {
const options = getDefaultTestClientOptions({ dsn: PUBLIC_DSN });
const client = new TestClient(options);
Expand Down
26 changes: 12 additions & 14 deletions packages/deno/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,20 @@ export class DenoClient extends ServerRuntimeClient<DenoClientOptions> {

super(clientOptions);

if (this.getOptions().enableLogs) {
this._logOnExitFlushListener = () => {
_INTERNAL_flushLogsBuffer(this);
};

if (serverName) {
this.on('beforeCaptureLog', log => {
log.attributes = {
...log.attributes,
'server.address': serverName,
};
});
}
this._logOnExitFlushListener = () => {
_INTERNAL_flushLogsBuffer(this);
};

globalThis.addEventListener('unload', this._logOnExitFlushListener);
if (serverName) {
this.on('beforeCaptureLog', log => {
log.attributes = {
...log.attributes,
'server.address': serverName,
};
});
}

globalThis.addEventListener('unload', this._logOnExitFlushListener);
}

/** @inheritDoc */
Expand Down
3 changes: 1 addition & 2 deletions packages/deno/test/mod.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ Deno.test('preserves existing log attributes when adding server.address', () =>
assertEquals(log.attributes?.['server.address'], 'test-server');
});

Deno.test('close() removes unload listener when enableLogs is true', async () => {
Deno.test('close() removes unload listener', async () => {
const removeEventListenerCalls: Array<string> = [];
const originalRemoveEventListener = globalThis.removeEventListener;
globalThis.removeEventListener = ((event: string, ...args: unknown[]) => {
Expand All @@ -227,7 +227,6 @@ Deno.test('close() removes unload listener when enableLogs is true', async () =>
try {
const client = new DenoClient({
dsn: 'https://233a45e5efe34c47a3536797ce15dafa@nothing.here/5650507',
enableLogs: true,
integrations: getDefaultIntegrations({}),
stackParser: createStackParser(nodeStackLineParser()),
transport: makeTestTransport(() => {}),
Expand Down
6 changes: 2 additions & 4 deletions packages/node/src/integrations/pino.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,7 @@ const _pinoIntegration = defineIntegration((userOptions: DeepPartial<PinoOptions

return {
name: 'Pino',
setup: client => {
const enableLogs = !!client.getOptions().enableLogs;

setup: () => {
const integratedChannel = diagnosticsChannel.tracingChannel('pino_asJson');

function onPinoStart(self: Pino, args: PinoHookArgs, result: PinoResult): void {
Expand All @@ -141,7 +139,7 @@ const _pinoIntegration = defineIntegration((userOptions: DeepPartial<PinoOptions
const messageKey = getPinoKey(self, 'pino.messageKey', 'msg');
const logMessage = message || (resultObj?.[messageKey] as string | undefined) || '';

if (enableLogs && options.log.levels.includes(level)) {
if (options.log.levels.includes(level)) {
const attributes: Record<string, unknown> = {
...resultObj,
'sentry.origin': 'auto.log.pino',
Expand Down
26 changes: 12 additions & 14 deletions packages/node/src/sdk/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,21 @@ export class NodeClient extends ServerRuntimeClient<NodeClientOptions> {

super(clientOptions);

if (this.getOptions().enableLogs) {
this._logOnExitFlushListener = () => {
_INTERNAL_flushLogsBuffer(this);
};

if (serverName) {
this.on('beforeCaptureLog', log => {
log.attributes = {
...log.attributes,
'server.address': serverName,
};
});
}
this._logOnExitFlushListener = () => {
_INTERNAL_flushLogsBuffer(this);
};

process.on('beforeExit', this._logOnExitFlushListener);
if (serverName) {
this.on('beforeCaptureLog', log => {
log.attributes = {
...log.attributes,
'server.address': serverName,
};
});
}

process.on('beforeExit', this._logOnExitFlushListener);

// Enable deferred segment-span transaction capture here, in the constructor, rather than in
// `initOtel`. Every client runs its constructor exactly once, whereas `initOtel` only runs on
// `Sentry.init()` and only fully wires up the first client (a second `init` loses the
Expand Down
1 change: 0 additions & 1 deletion packages/node/test/sdk/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ describe('NodeClient', () => {
runtime: { name: 'node', version: expect.any(String) },
serverName: expect.any(String),
tracesSampleRate: 1,
enableLogs: true,
});
});

Expand Down
Loading