From 25115c55bd005de2c83b5c4b67fcfe106ae69bc4 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 22 Apr 2026 15:44:43 +0200 Subject: [PATCH 1/6] add ingest settings to log envelope payload --- .../suites/public-api/logger/simple/test.ts | 2 + packages/core/src/logs/envelope.ts | 13 +++- packages/core/src/logs/internal.ts | 8 ++- packages/core/src/types-hoist/log.ts | 5 ++ packages/core/test/lib/logs/envelope.test.ts | 63 ++++++++++++++++++- 5 files changed, 86 insertions(+), 5 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts b/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts index db6d174820d7..50a1cb608df7 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts @@ -23,6 +23,8 @@ sentryTest('should capture all logging methods', async ({ getLocalTestUrl, page content_type: 'application/vnd.sentry.items.log+json', }, { + version: 2, + ingest_settings: { infer_ip: 'never', infer_useragent: 'never' }, items: [ { timestamp: expect.any(Number), diff --git a/packages/core/src/logs/envelope.ts b/packages/core/src/logs/envelope.ts index c1d5b23e1575..5cd0a577e6b9 100644 --- a/packages/core/src/logs/envelope.ts +++ b/packages/core/src/logs/envelope.ts @@ -4,14 +4,17 @@ import type { SerializedLog } from '../types-hoist/log'; import type { SdkMetadata } from '../types-hoist/sdkmetadata'; import { dsnToString } from '../utils/dsn'; import { createEnvelope } from '../utils/envelope'; +import { isBrowser } from '../utils/isBrowser'; /** * Creates a log container envelope item for a list of logs. * * @param items - The logs to include in the envelope. + * @param inferUserData - If true, tells Relay to infer the end-user IP and User-Agent from the incoming request. * @returns The created log container envelope item. */ -export function createLogContainerEnvelopeItem(items: Array): LogContainerItem { +export function createLogContainerEnvelopeItem(items: Array, inferUserData?: boolean): LogContainerItem { + const inferSetting = inferUserData ? 'auto' : 'never'; return [ { type: 'log', @@ -19,6 +22,10 @@ export function createLogContainerEnvelopeItem(items: Array): Log content_type: 'application/vnd.sentry.items.log+json', }, { + version: 2, + ...(isBrowser() && { + ingest_settings: { infer_ip: inferSetting, infer_useragent: inferSetting }, + }), items, }, ]; @@ -33,6 +40,7 @@ export function createLogContainerEnvelopeItem(items: Array): Log * @param metadata - The metadata to include in the envelope. * @param tunnel - The tunnel to include in the envelope. * @param dsn - The DSN to include in the envelope. + * @param inferUserData - If true, tells Relay to infer the end-user IP and User-Agent from the incoming request. * @returns The created envelope. */ export function createLogEnvelope( @@ -40,6 +48,7 @@ export function createLogEnvelope( metadata?: SdkMetadata, tunnel?: string, dsn?: DsnComponents, + inferUserData?: boolean, ): LogEnvelope { const headers: LogEnvelope[0] = {}; @@ -54,5 +63,5 @@ export function createLogEnvelope( headers.dsn = dsnToString(dsn); } - return createEnvelope(headers, [createLogContainerEnvelopeItem(logs)]); + return createEnvelope(headers, [createLogContainerEnvelopeItem(logs, inferUserData)]); } diff --git a/packages/core/src/logs/internal.ts b/packages/core/src/logs/internal.ts index 097ffbb6906e..c1eff9f50fcf 100644 --- a/packages/core/src/logs/internal.ts +++ b/packages/core/src/logs/internal.ts @@ -192,7 +192,13 @@ export function _INTERNAL_flushLogsBuffer(client: Client, maybeLogBuffer?: Array } const clientOptions = client.getOptions(); - const envelope = createLogEnvelope(logBuffer, clientOptions._metadata, clientOptions.tunnel, client.getDsn()); + const envelope = createLogEnvelope( + logBuffer, + clientOptions._metadata, + clientOptions.tunnel, + client.getDsn(), + clientOptions.sendDefaultPii, + ); // Clear the log buffer after envelopes have been constructed. _getBufferMap().set(client, []); diff --git a/packages/core/src/types-hoist/log.ts b/packages/core/src/types-hoist/log.ts index 7c704d3caf77..5d1cd72b32d3 100644 --- a/packages/core/src/types-hoist/log.ts +++ b/packages/core/src/types-hoist/log.ts @@ -64,5 +64,10 @@ export interface SerializedLog { } export type SerializedLogContainer = { + version?: number; + ingest_settings?: { + infer_ip?: 'auto' | 'never'; + infer_useragent?: 'auto' | 'never'; + }; items: Array; }; diff --git a/packages/core/test/lib/logs/envelope.test.ts b/packages/core/test/lib/logs/envelope.test.ts index 7fbe1a439910..a26b042c7e8d 100644 --- a/packages/core/test/lib/logs/envelope.test.ts +++ b/packages/core/test/lib/logs/envelope.test.ts @@ -5,6 +5,7 @@ import type { SerializedLog } from '../../../src/types-hoist/log'; import type { SdkMetadata } from '../../../src/types-hoist/sdkmetadata'; import * as utilsDsn from '../../../src/utils/dsn'; import * as utilsEnvelope from '../../../src/utils/envelope'; +import { isBrowser } from '../../../src/utils/isBrowser'; // Mock utils functions vi.mock('../../../src/utils/dsn', () => ({ @@ -13,6 +14,13 @@ vi.mock('../../../src/utils/dsn', () => ({ vi.mock('../../../src/utils/envelope', () => ({ createEnvelope: vi.fn((_headers, items) => [_headers, items]), })); +vi.mock('../../../src/utils/isBrowser', () => ({ + isBrowser: vi.fn(() => false), +})); + +afterEach(() => { + vi.mocked(isBrowser).mockReturnValue(false); +}); describe('createLogContainerEnvelopeItem', () => { it('creates an envelope item with correct structure', () => { @@ -26,7 +34,58 @@ describe('createLogContainerEnvelopeItem', () => { expect(result).toHaveLength(2); expect(result[0]).toEqual({ type: 'log', item_count: 2, content_type: 'application/vnd.sentry.items.log+json' }); - expect(result[1]).toEqual({ items: [mockLog, mockLog] }); + expect(result[1]).toEqual({ version: 2, items: [mockLog, mockLog] }); + }); + + it("includes ingest_settings with 'auto' values when in browser and sendDefaultPii is true", () => { + vi.mocked(isBrowser).mockReturnValue(true); + + const mockLog: SerializedLog = { + timestamp: 1713859200, + level: 'info', + body: 'Test log message', + }; + + const result = createLogContainerEnvelopeItem([mockLog], true); + + expect(result[1]).toEqual({ + version: 2, + ingest_settings: { infer_ip: 'auto', infer_useragent: 'auto' }, + items: [mockLog], + }); + }); + + it("includes ingest_settings with 'never' values when in browser and sendDefaultPii is false", () => { + vi.mocked(isBrowser).mockReturnValue(true); + + const mockLog: SerializedLog = { + timestamp: 1713859200, + level: 'info', + body: 'Test log message', + }; + + const result = createLogContainerEnvelopeItem([mockLog], false); + + expect(result[1]).toEqual({ + version: 2, + ingest_settings: { infer_ip: 'never', infer_useragent: 'never' }, + items: [mockLog], + }); + }); + + it('omits ingest_settings when not in browser', () => { + const mockLog: SerializedLog = { + timestamp: 1713859200, + level: 'info', + body: 'Test log message', + }; + + const result = createLogContainerEnvelopeItem([mockLog], true); + + expect(result[1]).toEqual({ + version: 2, + items: [mockLog], + }); }); }); @@ -133,7 +192,7 @@ describe('createLogEnvelope', () => { expect.arrayContaining([ expect.arrayContaining([ { type: 'log', item_count: 2, content_type: 'application/vnd.sentry.items.log+json' }, - { items: mockLogs }, + { version: 2, items: mockLogs }, ]), ]), ); From 5e0af0f9ffe1b1f9a4fbb53188e31727e58d6845 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 22 Apr 2026 15:57:16 +0200 Subject: [PATCH 2/6] only send version:2 if span streaming is used --- .../suites/public-api/logger/simple/test.ts | 2 -- packages/core/src/logs/envelope.ts | 27 +++++++++++--- packages/core/src/logs/internal.ts | 2 ++ packages/core/test/lib/logs/envelope.test.ts | 36 +++++++++++++------ 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts b/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts index 50a1cb608df7..db6d174820d7 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts @@ -23,8 +23,6 @@ sentryTest('should capture all logging methods', async ({ getLocalTestUrl, page content_type: 'application/vnd.sentry.items.log+json', }, { - version: 2, - ingest_settings: { infer_ip: 'never', infer_useragent: 'never' }, items: [ { timestamp: expect.any(Number), diff --git a/packages/core/src/logs/envelope.ts b/packages/core/src/logs/envelope.ts index 5cd0a577e6b9..375ae35498ac 100644 --- a/packages/core/src/logs/envelope.ts +++ b/packages/core/src/logs/envelope.ts @@ -9,11 +9,22 @@ import { isBrowser } from '../utils/isBrowser'; /** * Creates a log container envelope item for a list of logs. * + * When `spanStreamingEnabled` is false, the payload is emitted in the legacy (v1) shape for + * backwards compatibility: Relay's historical behavior for log envelopes was to always infer + * end-user IP and User-Agent. Sending `version: 2` opts the payload into the explicit + * `ingest_settings` protocol, which would silently turn that inference off for SDKs that + * haven't adopted the new behavior. + * * @param items - The logs to include in the envelope. + * @param spanStreamingEnabled - If true, emit the v2 payload shape with explicit `ingest_settings`. * @param inferUserData - If true, tells Relay to infer the end-user IP and User-Agent from the incoming request. * @returns The created log container envelope item. */ -export function createLogContainerEnvelopeItem(items: Array, inferUserData?: boolean): LogContainerItem { +export function createLogContainerEnvelopeItem( + items: Array, + spanStreamingEnabled?: boolean, + inferUserData?: boolean, +): LogContainerItem { const inferSetting = inferUserData ? 'auto' : 'never'; return [ { @@ -22,9 +33,11 @@ export function createLogContainerEnvelopeItem(items: Array, infe content_type: 'application/vnd.sentry.items.log+json', }, { - version: 2, - ...(isBrowser() && { - ingest_settings: { infer_ip: inferSetting, infer_useragent: inferSetting }, + ...(spanStreamingEnabled && { + version: 2, + ...(isBrowser() && { + ingest_settings: { infer_ip: inferSetting, infer_useragent: inferSetting }, + }), }), items, }, @@ -40,6 +53,7 @@ export function createLogContainerEnvelopeItem(items: Array, infe * @param metadata - The metadata to include in the envelope. * @param tunnel - The tunnel to include in the envelope. * @param dsn - The DSN to include in the envelope. + * @param spanStreamingEnabled - If true, emit the v2 payload shape with explicit `ingest_settings`. * @param inferUserData - If true, tells Relay to infer the end-user IP and User-Agent from the incoming request. * @returns The created envelope. */ @@ -48,6 +62,7 @@ export function createLogEnvelope( metadata?: SdkMetadata, tunnel?: string, dsn?: DsnComponents, + spanStreamingEnabled?: boolean, inferUserData?: boolean, ): LogEnvelope { const headers: LogEnvelope[0] = {}; @@ -63,5 +78,7 @@ export function createLogEnvelope( headers.dsn = dsnToString(dsn); } - return createEnvelope(headers, [createLogContainerEnvelopeItem(logs, inferUserData)]); + return createEnvelope(headers, [ + createLogContainerEnvelopeItem(logs, spanStreamingEnabled, inferUserData), + ]); } diff --git a/packages/core/src/logs/internal.ts b/packages/core/src/logs/internal.ts index c1eff9f50fcf..37d19a886f2f 100644 --- a/packages/core/src/logs/internal.ts +++ b/packages/core/src/logs/internal.ts @@ -3,6 +3,7 @@ import { getGlobalSingleton } from '../carrier'; import type { Client } from '../client'; import { getClient, getCurrentScope, getIsolationScope } from '../currentScopes'; import { DEBUG_BUILD } from '../debug-build'; +import { hasSpanStreamingEnabled } from '../tracing/spans/hasSpanStreamingEnabled'; import type { Integration } from '../types-hoist/integration'; import type { Log, SerializedLog } from '../types-hoist/log'; import { consoleSandbox, debug } from '../utils/debug-logger'; @@ -197,6 +198,7 @@ export function _INTERNAL_flushLogsBuffer(client: Client, maybeLogBuffer?: Array clientOptions._metadata, clientOptions.tunnel, client.getDsn(), + hasSpanStreamingEnabled(client), clientOptions.sendDefaultPii, ); diff --git a/packages/core/test/lib/logs/envelope.test.ts b/packages/core/test/lib/logs/envelope.test.ts index a26b042c7e8d..cff802b1ca73 100644 --- a/packages/core/test/lib/logs/envelope.test.ts +++ b/packages/core/test/lib/logs/envelope.test.ts @@ -23,7 +23,7 @@ afterEach(() => { }); describe('createLogContainerEnvelopeItem', () => { - it('creates an envelope item with correct structure', () => { + it('creates an envelope item with legacy shape when span streaming is disabled', () => { const mockLog: SerializedLog = { timestamp: 1713859200, level: 'error', @@ -34,10 +34,25 @@ describe('createLogContainerEnvelopeItem', () => { expect(result).toHaveLength(2); expect(result[0]).toEqual({ type: 'log', item_count: 2, content_type: 'application/vnd.sentry.items.log+json' }); - expect(result[1]).toEqual({ version: 2, items: [mockLog, mockLog] }); + expect(result[1]).toEqual({ items: [mockLog, mockLog] }); }); - it("includes ingest_settings with 'auto' values when in browser and sendDefaultPii is true", () => { + it('emits version: 2 without ingest_settings when span streaming is enabled but not in browser', () => { + const mockLog: SerializedLog = { + timestamp: 1713859200, + level: 'info', + body: 'Test log message', + }; + + const result = createLogContainerEnvelopeItem([mockLog], true, true); + + expect(result[1]).toEqual({ + version: 2, + items: [mockLog], + }); + }); + + it("includes ingest_settings with 'auto' values when span streaming is enabled, in browser, and inferUserData is true", () => { vi.mocked(isBrowser).mockReturnValue(true); const mockLog: SerializedLog = { @@ -46,7 +61,7 @@ describe('createLogContainerEnvelopeItem', () => { body: 'Test log message', }; - const result = createLogContainerEnvelopeItem([mockLog], true); + const result = createLogContainerEnvelopeItem([mockLog], true, true); expect(result[1]).toEqual({ version: 2, @@ -55,7 +70,7 @@ describe('createLogContainerEnvelopeItem', () => { }); }); - it("includes ingest_settings with 'never' values when in browser and sendDefaultPii is false", () => { + it("includes ingest_settings with 'never' values when span streaming is enabled, in browser, and inferUserData is false", () => { vi.mocked(isBrowser).mockReturnValue(true); const mockLog: SerializedLog = { @@ -64,7 +79,7 @@ describe('createLogContainerEnvelopeItem', () => { body: 'Test log message', }; - const result = createLogContainerEnvelopeItem([mockLog], false); + const result = createLogContainerEnvelopeItem([mockLog], true, false); expect(result[1]).toEqual({ version: 2, @@ -73,17 +88,18 @@ describe('createLogContainerEnvelopeItem', () => { }); }); - it('omits ingest_settings when not in browser', () => { + it('omits version and ingest_settings when span streaming is disabled even if in browser', () => { + vi.mocked(isBrowser).mockReturnValue(true); + const mockLog: SerializedLog = { timestamp: 1713859200, level: 'info', body: 'Test log message', }; - const result = createLogContainerEnvelopeItem([mockLog], true); + const result = createLogContainerEnvelopeItem([mockLog], false, true); expect(result[1]).toEqual({ - version: 2, items: [mockLog], }); }); @@ -192,7 +208,7 @@ describe('createLogEnvelope', () => { expect.arrayContaining([ expect.arrayContaining([ { type: 'log', item_count: 2, content_type: 'application/vnd.sentry.items.log+json' }, - { version: 2, items: mockLogs }, + { items: mockLogs }, ]), ]), ); From c7885f8b29e324e554c073b6c24316ad6e6362fb Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 22 Apr 2026 16:38:23 +0200 Subject: [PATCH 3/6] infer_useragent -> infer_user_agent --- packages/core/src/logs/envelope.ts | 2 +- packages/core/src/types-hoist/log.ts | 2 +- packages/core/test/lib/logs/envelope.test.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/logs/envelope.ts b/packages/core/src/logs/envelope.ts index 375ae35498ac..4cfc0fbfe6cc 100644 --- a/packages/core/src/logs/envelope.ts +++ b/packages/core/src/logs/envelope.ts @@ -36,7 +36,7 @@ export function createLogContainerEnvelopeItem( ...(spanStreamingEnabled && { version: 2, ...(isBrowser() && { - ingest_settings: { infer_ip: inferSetting, infer_useragent: inferSetting }, + ingest_settings: { infer_ip: inferSetting, infer_user_agent: inferSetting }, }), }), items, diff --git a/packages/core/src/types-hoist/log.ts b/packages/core/src/types-hoist/log.ts index 5d1cd72b32d3..0f84ebbcbdda 100644 --- a/packages/core/src/types-hoist/log.ts +++ b/packages/core/src/types-hoist/log.ts @@ -67,7 +67,7 @@ export type SerializedLogContainer = { version?: number; ingest_settings?: { infer_ip?: 'auto' | 'never'; - infer_useragent?: 'auto' | 'never'; + infer_user_agent?: 'auto' | 'never'; }; items: Array; }; diff --git a/packages/core/test/lib/logs/envelope.test.ts b/packages/core/test/lib/logs/envelope.test.ts index cff802b1ca73..c8c6eef361a7 100644 --- a/packages/core/test/lib/logs/envelope.test.ts +++ b/packages/core/test/lib/logs/envelope.test.ts @@ -65,7 +65,7 @@ describe('createLogContainerEnvelopeItem', () => { expect(result[1]).toEqual({ version: 2, - ingest_settings: { infer_ip: 'auto', infer_useragent: 'auto' }, + ingest_settings: { infer_ip: 'auto', infer_user_agent: 'auto' }, items: [mockLog], }); }); @@ -83,7 +83,7 @@ describe('createLogContainerEnvelopeItem', () => { expect(result[1]).toEqual({ version: 2, - ingest_settings: { infer_ip: 'never', infer_useragent: 'never' }, + ingest_settings: { infer_ip: 'never', infer_user_agent: 'never' }, items: [mockLog], }); }); From c31b0db47d51340cf9dfee23505361e79b23aa33 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 22 Apr 2026 17:36:02 +0200 Subject: [PATCH 4/6] always send v2 envelopes --- packages/core/src/logs/envelope.ts | 23 +++------- packages/core/src/logs/internal.ts | 2 - packages/core/test/lib/logs/envelope.test.ts | 45 ++++---------------- 3 files changed, 13 insertions(+), 57 deletions(-) diff --git a/packages/core/src/logs/envelope.ts b/packages/core/src/logs/envelope.ts index 4cfc0fbfe6cc..dce968e295b6 100644 --- a/packages/core/src/logs/envelope.ts +++ b/packages/core/src/logs/envelope.ts @@ -9,20 +9,13 @@ import { isBrowser } from '../utils/isBrowser'; /** * Creates a log container envelope item for a list of logs. * - * When `spanStreamingEnabled` is false, the payload is emitted in the legacy (v1) shape for - * backwards compatibility: Relay's historical behavior for log envelopes was to always infer - * end-user IP and User-Agent. Sending `version: 2` opts the payload into the explicit - * `ingest_settings` protocol, which would silently turn that inference off for SDKs that - * haven't adopted the new behavior. - * * @param items - The logs to include in the envelope. - * @param spanStreamingEnabled - If true, emit the v2 payload shape with explicit `ingest_settings`. * @param inferUserData - If true, tells Relay to infer the end-user IP and User-Agent from the incoming request. + * Only emitted as `ingest_settings` in browser environments. * @returns The created log container envelope item. */ export function createLogContainerEnvelopeItem( items: Array, - spanStreamingEnabled?: boolean, inferUserData?: boolean, ): LogContainerItem { const inferSetting = inferUserData ? 'auto' : 'never'; @@ -33,11 +26,9 @@ export function createLogContainerEnvelopeItem( content_type: 'application/vnd.sentry.items.log+json', }, { - ...(spanStreamingEnabled && { - version: 2, - ...(isBrowser() && { - ingest_settings: { infer_ip: inferSetting, infer_user_agent: inferSetting }, - }), + version: 2, + ...(isBrowser() && { + ingest_settings: { infer_ip: inferSetting, infer_user_agent: inferSetting }, }), items, }, @@ -53,7 +44,6 @@ export function createLogContainerEnvelopeItem( * @param metadata - The metadata to include in the envelope. * @param tunnel - The tunnel to include in the envelope. * @param dsn - The DSN to include in the envelope. - * @param spanStreamingEnabled - If true, emit the v2 payload shape with explicit `ingest_settings`. * @param inferUserData - If true, tells Relay to infer the end-user IP and User-Agent from the incoming request. * @returns The created envelope. */ @@ -62,7 +52,6 @@ export function createLogEnvelope( metadata?: SdkMetadata, tunnel?: string, dsn?: DsnComponents, - spanStreamingEnabled?: boolean, inferUserData?: boolean, ): LogEnvelope { const headers: LogEnvelope[0] = {}; @@ -78,7 +67,5 @@ export function createLogEnvelope( headers.dsn = dsnToString(dsn); } - return createEnvelope(headers, [ - createLogContainerEnvelopeItem(logs, spanStreamingEnabled, inferUserData), - ]); + return createEnvelope(headers, [createLogContainerEnvelopeItem(logs, inferUserData)]); } diff --git a/packages/core/src/logs/internal.ts b/packages/core/src/logs/internal.ts index 37d19a886f2f..c1eff9f50fcf 100644 --- a/packages/core/src/logs/internal.ts +++ b/packages/core/src/logs/internal.ts @@ -3,7 +3,6 @@ import { getGlobalSingleton } from '../carrier'; import type { Client } from '../client'; import { getClient, getCurrentScope, getIsolationScope } from '../currentScopes'; import { DEBUG_BUILD } from '../debug-build'; -import { hasSpanStreamingEnabled } from '../tracing/spans/hasSpanStreamingEnabled'; import type { Integration } from '../types-hoist/integration'; import type { Log, SerializedLog } from '../types-hoist/log'; import { consoleSandbox, debug } from '../utils/debug-logger'; @@ -198,7 +197,6 @@ export function _INTERNAL_flushLogsBuffer(client: Client, maybeLogBuffer?: Array clientOptions._metadata, clientOptions.tunnel, client.getDsn(), - hasSpanStreamingEnabled(client), clientOptions.sendDefaultPii, ); diff --git a/packages/core/test/lib/logs/envelope.test.ts b/packages/core/test/lib/logs/envelope.test.ts index c8c6eef361a7..86626364f506 100644 --- a/packages/core/test/lib/logs/envelope.test.ts +++ b/packages/core/test/lib/logs/envelope.test.ts @@ -23,36 +23,23 @@ afterEach(() => { }); describe('createLogContainerEnvelopeItem', () => { - it('creates an envelope item with legacy shape when span streaming is disabled', () => { - const mockLog: SerializedLog = { - timestamp: 1713859200, - level: 'error', - body: 'Test error message', - }; - - const result = createLogContainerEnvelopeItem([mockLog, mockLog]); - - expect(result).toHaveLength(2); - expect(result[0]).toEqual({ type: 'log', item_count: 2, content_type: 'application/vnd.sentry.items.log+json' }); - expect(result[1]).toEqual({ items: [mockLog, mockLog] }); - }); - - it('emits version: 2 without ingest_settings when span streaming is enabled but not in browser', () => { + it('emits version: 2 without ingest_settings when not in browser', () => { const mockLog: SerializedLog = { timestamp: 1713859200, level: 'info', body: 'Test log message', }; - const result = createLogContainerEnvelopeItem([mockLog], true, true); + const result = createLogContainerEnvelopeItem([mockLog], true); + expect(result[0]).toEqual({ type: 'log', item_count: 1, content_type: 'application/vnd.sentry.items.log+json' }); expect(result[1]).toEqual({ version: 2, items: [mockLog], }); }); - it("includes ingest_settings with 'auto' values when span streaming is enabled, in browser, and inferUserData is true", () => { + it("includes ingest_settings with 'auto' values when in browser and inferUserData is true", () => { vi.mocked(isBrowser).mockReturnValue(true); const mockLog: SerializedLog = { @@ -61,7 +48,7 @@ describe('createLogContainerEnvelopeItem', () => { body: 'Test log message', }; - const result = createLogContainerEnvelopeItem([mockLog], true, true); + const result = createLogContainerEnvelopeItem([mockLog], true); expect(result[1]).toEqual({ version: 2, @@ -70,7 +57,7 @@ describe('createLogContainerEnvelopeItem', () => { }); }); - it("includes ingest_settings with 'never' values when span streaming is enabled, in browser, and inferUserData is false", () => { + it("includes ingest_settings with 'never' values when in browser and inferUserData is false", () => { vi.mocked(isBrowser).mockReturnValue(true); const mockLog: SerializedLog = { @@ -79,7 +66,7 @@ describe('createLogContainerEnvelopeItem', () => { body: 'Test log message', }; - const result = createLogContainerEnvelopeItem([mockLog], true, false); + const result = createLogContainerEnvelopeItem([mockLog], false); expect(result[1]).toEqual({ version: 2, @@ -87,22 +74,6 @@ describe('createLogContainerEnvelopeItem', () => { items: [mockLog], }); }); - - it('omits version and ingest_settings when span streaming is disabled even if in browser', () => { - vi.mocked(isBrowser).mockReturnValue(true); - - const mockLog: SerializedLog = { - timestamp: 1713859200, - level: 'info', - body: 'Test log message', - }; - - const result = createLogContainerEnvelopeItem([mockLog], false, true); - - expect(result[1]).toEqual({ - items: [mockLog], - }); - }); }); describe('createLogEnvelope', () => { @@ -208,7 +179,7 @@ describe('createLogEnvelope', () => { expect.arrayContaining([ expect.arrayContaining([ { type: 'log', item_count: 2, content_type: 'application/vnd.sentry.items.log+json' }, - { items: mockLogs }, + { version: 2, items: mockLogs }, ]), ]), ); From b95976948a5391d744782232a1c403188c803e1b Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Wed, 22 Apr 2026 18:07:56 +0200 Subject: [PATCH 5/6] fix tests --- .../suites/public-api/logger/integration/test.ts | 2 ++ .../suites/public-api/logger/scopeAttributes/test.ts | 2 ++ .../suites/public-api/logger/simple/test.ts | 2 ++ .../suites/light-mode/logs/test.ts | 1 + .../suites/public-api/logs/test.ts | 1 + .../node-integration-tests/suites/public-api/logger/test.ts | 1 + packages/core/src/logs/envelope.ts | 5 +---- 7 files changed, 10 insertions(+), 4 deletions(-) diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/integration/test.ts b/dev-packages/browser-integration-tests/suites/public-api/logger/integration/test.ts index 7315e8cf4f36..8312c2a13e4d 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/logger/integration/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/integration/test.ts @@ -23,6 +23,8 @@ sentryTest('should capture console object calls', async ({ getLocalTestUrl, page content_type: 'application/vnd.sentry.items.log+json', }, { + version: 2, + ingest_settings: { infer_ip: 'never', infer_user_agent: 'never' }, items: [ { timestamp: expect.any(Number), diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/test.ts b/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/test.ts index 4d7970945436..07af615712ff 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/scopeAttributes/test.ts @@ -22,6 +22,8 @@ sentryTest('captures logs with scope attributes', async ({ getLocalTestUrl, page content_type: 'application/vnd.sentry.items.log+json', }, { + version: 2, + ingest_settings: { infer_ip: 'never', infer_user_agent: 'never' }, items: [ { timestamp: expect.any(Number), diff --git a/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts b/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts index db6d174820d7..0a464d896c5d 100644 --- a/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts +++ b/dev-packages/browser-integration-tests/suites/public-api/logger/simple/test.ts @@ -23,6 +23,8 @@ sentryTest('should capture all logging methods', async ({ getLocalTestUrl, page content_type: 'application/vnd.sentry.items.log+json', }, { + version: 2, + ingest_settings: { infer_ip: 'never', infer_user_agent: 'never' }, items: [ { timestamp: expect.any(Number), diff --git a/dev-packages/node-core-integration-tests/suites/light-mode/logs/test.ts b/dev-packages/node-core-integration-tests/suites/light-mode/logs/test.ts index 25096f1be7e5..858e80e0718d 100644 --- a/dev-packages/node-core-integration-tests/suites/light-mode/logs/test.ts +++ b/dev-packages/node-core-integration-tests/suites/light-mode/logs/test.ts @@ -11,6 +11,7 @@ describe('light mode logs', () => { .expect({ log: logsContainer => { expect(logsContainer).toEqual({ + version: 2, items: [ { attributes: { diff --git a/dev-packages/node-core-integration-tests/suites/public-api/logs/test.ts b/dev-packages/node-core-integration-tests/suites/public-api/logs/test.ts index 53c80a6194c5..8afc4402475d 100644 --- a/dev-packages/node-core-integration-tests/suites/public-api/logs/test.ts +++ b/dev-packages/node-core-integration-tests/suites/public-api/logs/test.ts @@ -11,6 +11,7 @@ describe('logger public API', () => { .expect({ log: logsContainer => { expect(logsContainer).toEqual({ + version: 2, items: [ { attributes: { diff --git a/dev-packages/node-integration-tests/suites/public-api/logger/test.ts b/dev-packages/node-integration-tests/suites/public-api/logger/test.ts index 6b9f43e738d2..e992d70c4de3 100644 --- a/dev-packages/node-integration-tests/suites/public-api/logger/test.ts +++ b/dev-packages/node-integration-tests/suites/public-api/logger/test.ts @@ -39,6 +39,7 @@ describe('logs', () => { .expect({ log: logsContainer => { expect(logsContainer).toEqual({ + version: 2, items: [ { timestamp: expect.any(Number), diff --git a/packages/core/src/logs/envelope.ts b/packages/core/src/logs/envelope.ts index dce968e295b6..3e30a5680316 100644 --- a/packages/core/src/logs/envelope.ts +++ b/packages/core/src/logs/envelope.ts @@ -14,10 +14,7 @@ import { isBrowser } from '../utils/isBrowser'; * Only emitted as `ingest_settings` in browser environments. * @returns The created log container envelope item. */ -export function createLogContainerEnvelopeItem( - items: Array, - inferUserData?: boolean, -): LogContainerItem { +export function createLogContainerEnvelopeItem(items: Array, inferUserData?: boolean): LogContainerItem { const inferSetting = inferUserData ? 'auto' : 'never'; return [ { From 28290e219064d4ed7bb8370d80b61b0711572784 Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Thu, 23 Apr 2026 09:27:39 +0200 Subject: [PATCH 6/6] update size limits --- .size-limit.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.size-limit.js b/.size-limit.js index cad516a0a49a..043b1d8555bf 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -8,7 +8,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/prod/index.js', import: createImport('init'), gzip: true, - limit: '26 KB', + limit: '27 KB', }, { name: '@sentry/browser - with treeshaking flags', @@ -59,7 +59,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/prod/index.js', import: createImport('init', 'browserTracingIntegration', 'replayIntegration'), gzip: true, - limit: '83 KB', + limit: '84 KB', }, { name: '@sentry/browser (incl. Tracing, Replay) - with treeshaking flags', @@ -96,7 +96,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/prod/index.js', import: createImport('init', 'browserTracingIntegration', 'replayIntegration', 'feedbackIntegration'), gzip: true, - limit: '100 KB', + limit: '101 KB', }, { name: '@sentry/browser (incl. Feedback)', @@ -138,7 +138,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/prod/index.js', import: createImport('init', 'metrics', 'logger'), gzip: true, - limit: '28 KB', + limit: '29 KB', }, // React SDK (ESM) { @@ -178,7 +178,7 @@ module.exports = [ path: 'packages/svelte/build/esm/index.js', import: createImport('init'), gzip: true, - limit: '26 KB', + limit: '27 KB', }, // Browser CDN bundles { @@ -197,7 +197,7 @@ module.exports = [ name: 'CDN Bundle (incl. Logs, Metrics)', path: createCDNPath('bundle.logs.metrics.min.js'), gzip: true, - limit: '30 KB', + limit: '31 KB', }, { name: 'CDN Bundle (incl. Tracing, Logs, Metrics)', @@ -283,14 +283,14 @@ module.exports = [ path: createCDNPath('bundle.tracing.replay.logs.metrics.min.js'), gzip: false, brotli: false, - limit: '258.5 KB', + limit: '259 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed', path: createCDNPath('bundle.tracing.replay.feedback.min.js'), gzip: false, brotli: false, - limit: '268 KB', + limit: '269 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed',