Skip to content

Commit 7d88ebd

Browse files
committed
switch to log container envelope
1 parent eaaef93 commit 7d88ebd

File tree

9 files changed

+390
-251
lines changed

9 files changed

+390
-251
lines changed

packages/core/src/index.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,6 @@ export type {
323323
ProfileChunkItem,
324324
SpanEnvelope,
325325
SpanItem,
326-
OtelLogEnvelope,
327-
OtelLogItem,
328326
} from './types-hoist/envelope';
329327
export type { ExtendedError } from './types-hoist/error';
330328
export type { Event, EventHint, EventType, ErrorEvent, TransactionEvent } from './types-hoist/event';
@@ -385,13 +383,7 @@ export type {
385383
TraceFlag,
386384
} from './types-hoist/span';
387385
export type { SpanStatus } from './types-hoist/spanStatus';
388-
export type {
389-
Log,
390-
LogSeverityLevel,
391-
SerializedOtelLog,
392-
SerializedLogAttribute,
393-
SerializedLogAttributeValueType,
394-
} from './types-hoist/log';
386+
export type { Log, LogSeverityLevel } from './types-hoist/log';
395387
export type { TimedEvent } from './types-hoist/timedEvent';
396388
export type { StackFrame } from './types-hoist/stackframe';
397389
export type { Stacktrace, StackParser, StackLineParser, StackLineParserFn } from './types-hoist/stacktrace';

packages/core/src/logs/envelope.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,47 @@
11
import type { DsnComponents } from '../types-hoist/dsn';
22
import type { SdkMetadata } from '../types-hoist/sdkmetadata';
3-
import type { SerializedOtelLog } from '../types-hoist/log';
4-
import type { OtelLogEnvelope, OtelLogItem } from '../types-hoist/envelope';
3+
import type { SerializedLog } from '../types-hoist/log';
4+
import type { LogContainerItem, LogEnvelope } from '../types-hoist/envelope';
55
import { dsnToString } from '../utils-hoist/dsn';
66
import { createEnvelope } from '../utils-hoist/envelope';
77

88
/**
9-
* Creates OTEL log envelope item for a serialized OTEL log.
9+
* Creates a log container envelope item for a list of logs.
1010
*
11-
* @param log - The serialized OTEL log to include in the envelope.
12-
* @returns The created OTEL log envelope item.
11+
* @param items - The logs to include in the envelope.
12+
* @returns The created log container envelope item.
1313
*/
14-
export function createOtelLogEnvelopeItem(log: SerializedOtelLog): OtelLogItem {
14+
export function createLogContainerEnvelopeItem(items: Array<SerializedLog>): LogContainerItem {
1515
return [
1616
{
17-
type: 'otel_log',
17+
type: 'log',
18+
item_count: items.length,
19+
content_type: 'application/vnd.sentry.items.log+json',
20+
},
21+
{
22+
items,
1823
},
19-
log,
2024
];
2125
}
2226

2327
/**
2428
* Creates an envelope for a list of logs.
2529
*
30+
* Logs from multiple traces can be included in the same envelope.
31+
*
2632
* @param logs - The logs to include in the envelope.
2733
* @param metadata - The metadata to include in the envelope.
2834
* @param tunnel - The tunnel to include in the envelope.
2935
* @param dsn - The DSN to include in the envelope.
3036
* @returns The created envelope.
3137
*/
32-
export function createOtelLogEnvelope(
33-
logs: Array<SerializedOtelLog>,
38+
export function createLogEnvelope(
39+
logs: Array<SerializedLog>,
3440
metadata?: SdkMetadata,
3541
tunnel?: string,
3642
dsn?: DsnComponents,
37-
): OtelLogEnvelope {
38-
const headers: OtelLogEnvelope[0] = {};
43+
): LogEnvelope {
44+
const headers: LogEnvelope[0] = {};
3945

4046
if (metadata?.sdk) {
4147
headers.sdk = {
@@ -48,5 +54,5 @@ export function createOtelLogEnvelope(
4854
headers.dsn = dsnToString(dsn);
4955
}
5056

51-
return createEnvelope<OtelLogEnvelope>(headers, logs.map(createOtelLogEnvelopeItem));
57+
return createEnvelope<LogEnvelope>(headers, [createLogContainerEnvelopeItem(logs)]);
5258
}

packages/core/src/logs/exports.ts

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import type { Client } from '../client';
2+
import type { SerializedLog, SerializedLogAttributeValue } from '../types-hoist/log';
3+
import type { Log } from '../types-hoist/log';
4+
25
import { _getTraceInfoFromScope } from '../client';
36
import { getClient, getCurrentScope } from '../currentScopes';
47
import { DEBUG_BUILD } from '../debug-build';
58
import { SEVERITY_TEXT_TO_SEVERITY_NUMBER } from './constants';
6-
import type { SerializedLogAttribute, SerializedOtelLog } from '../types-hoist/log';
7-
import type { Log } from '../types-hoist/log';
89
import { _getSpanForScope } from '../utils/spanOnScope';
9-
import { createOtelLogEnvelope } from './envelope';
10+
import { createLogEnvelope } from './envelope';
1011
import { logger } from '../utils-hoist/logger';
1112
import { isParameterizedString } from '../utils-hoist/is';
13+
import { timestampInSeconds } from '../utils-hoist/time';
1214

1315
const MAX_LOG_BUFFER_SIZE = 100;
1416

15-
const CLIENT_TO_LOG_BUFFER_MAP = new WeakMap<Client, Array<SerializedOtelLog>>();
17+
const CLIENT_TO_LOG_BUFFER_MAP = new WeakMap<Client, Array<SerializedLog>>();
1618

1719
/**
1820
* Converts a log attribute to a serialized log attribute.
@@ -21,22 +23,28 @@ const CLIENT_TO_LOG_BUFFER_MAP = new WeakMap<Client, Array<SerializedOtelLog>>()
2123
* @param value - The value of the log attribute.
2224
* @returns The serialized log attribute.
2325
*/
24-
export function logAttributeToSerializedLogAttribute(key: string, value: unknown): SerializedLogAttribute {
26+
export function logAttributeToSerializedLogAttribute(value: unknown): SerializedLogAttributeValue {
2527
switch (typeof value) {
2628
case 'number':
29+
if (Number.isInteger(value)) {
30+
return {
31+
value,
32+
type: 'integer',
33+
};
34+
}
2735
return {
28-
key,
29-
value: { doubleValue: value },
36+
value,
37+
type: 'double',
3038
};
3139
case 'boolean':
3240
return {
33-
key,
34-
value: { boolValue: value },
41+
value,
42+
type: 'boolean',
3543
};
3644
case 'string':
3745
return {
38-
key,
39-
value: { stringValue: value },
46+
value,
47+
type: 'string',
4048
};
4149
default: {
4250
let stringValue = '';
@@ -46,8 +54,8 @@ export function logAttributeToSerializedLogAttribute(key: string, value: unknown
4654
// Do nothing
4755
}
4856
return {
49-
key,
50-
value: { stringValue },
57+
value: stringValue,
58+
type: 'string',
5159
};
5260
}
5361
}
@@ -128,15 +136,19 @@ export function _INTERNAL_captureLog(
128136

129137
const { level, message, attributes = {}, severityNumber } = log;
130138

131-
const serializedLog: SerializedOtelLog = {
132-
severityText: level,
133-
body: {
134-
stringValue: message,
135-
},
136-
attributes: Object.entries(attributes).map(([key, value]) => logAttributeToSerializedLogAttribute(key, value)),
137-
timeUnixNano: `${new Date().getTime().toString()}000000`,
138-
traceId: traceContext?.trace_id,
139-
severityNumber: severityNumber ?? SEVERITY_TEXT_TO_SEVERITY_NUMBER[level],
139+
const serializedLog: SerializedLog = {
140+
timestamp: timestampInSeconds(),
141+
level,
142+
body: message,
143+
trace_id: traceContext?.trace_id,
144+
severity_number: severityNumber ?? SEVERITY_TEXT_TO_SEVERITY_NUMBER[level],
145+
attributes: Object.keys(attributes).reduce(
146+
(acc, key) => {
147+
acc[key] = logAttributeToSerializedLogAttribute(attributes[key]);
148+
return acc;
149+
},
150+
{} as Record<string, SerializedLogAttributeValue>,
151+
),
140152
};
141153

142154
const logBuffer = CLIENT_TO_LOG_BUFFER_MAP.get(client);
@@ -161,14 +173,14 @@ export function _INTERNAL_captureLog(
161173
* @experimental This method will experience breaking changes. This is not yet part of
162174
* the stable Sentry SDK API and can be changed or removed without warning.
163175
*/
164-
export function _INTERNAL_flushLogsBuffer(client: Client, maybeLogBuffer?: Array<SerializedOtelLog>): void {
176+
export function _INTERNAL_flushLogsBuffer(client: Client, maybeLogBuffer?: Array<SerializedLog>): void {
165177
const logBuffer = maybeLogBuffer ?? CLIENT_TO_LOG_BUFFER_MAP.get(client) ?? [];
166178
if (logBuffer.length === 0) {
167179
return;
168180
}
169181

170182
const clientOptions = client.getOptions();
171-
const envelope = createOtelLogEnvelope(logBuffer, clientOptions._metadata, clientOptions.tunnel, client.getDsn());
183+
const envelope = createLogEnvelope(logBuffer, clientOptions._metadata, clientOptions.tunnel, client.getDsn());
172184

173185
// Clear the log buffer after envelopes have been constructed.
174186
logBuffer.length = 0;
@@ -188,6 +200,6 @@ export function _INTERNAL_flushLogsBuffer(client: Client, maybeLogBuffer?: Array
188200
* @param client - The client to get the log buffer for.
189201
* @returns The log buffer for the given client.
190202
*/
191-
export function _INTERNAL_getLogBuffer(client: Client): Array<SerializedOtelLog> | undefined {
203+
export function _INTERNAL_getLogBuffer(client: Client): Array<SerializedLog> | undefined {
192204
return CLIENT_TO_LOG_BUFFER_MAP.get(client);
193205
}

packages/core/src/types-hoist/envelope.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { LegacyCSPReport } from './csp';
55
import type { DsnComponents } from './dsn';
66
import type { Event } from './event';
77
import type { FeedbackEvent, UserFeedback } from './feedback';
8-
import type { SerializedOtelLog } from './log';
8+
import type { SerializedLogContainer } from './log';
99
import type { Profile, ProfileChunk } from './profiling';
1010
import type { ReplayEvent, ReplayRecordingData } from './replay';
1111
import type { SdkInfo } from './sdkinfo';
@@ -44,7 +44,7 @@ export type EnvelopeItemType =
4444
| 'replay_recording'
4545
| 'check_in'
4646
| 'span'
47-
| 'otel_log'
47+
| 'log'
4848
| 'raw_security';
4949

5050
export type BaseEnvelopeHeaders = {
@@ -87,7 +87,17 @@ type CheckInItemHeaders = { type: 'check_in' };
8787
type ProfileItemHeaders = { type: 'profile' };
8888
type ProfileChunkItemHeaders = { type: 'profile_chunk' };
8989
type SpanItemHeaders = { type: 'span' };
90-
type OtelLogItemHeaders = { type: 'otel_log' };
90+
type LogContainerItemHeaders = {
91+
type: 'log';
92+
/**
93+
* The number of log items in the container. This must be the same as the number of log items in the payload.
94+
*/
95+
item_count: number;
96+
/**
97+
* The content type of the log items. This must be `application/vnd.sentry.items.log+json`.
98+
*/
99+
content_type: 'application/vnd.sentry.items.log+json';
100+
};
91101
type RawSecurityHeaders = { type: 'raw_security'; sentry_release?: string; sentry_environment?: string };
92102

93103
export type EventItem = BaseEnvelopeItem<EventItemHeaders, Event>;
@@ -104,7 +114,7 @@ export type FeedbackItem = BaseEnvelopeItem<FeedbackItemHeaders, FeedbackEvent>;
104114
export type ProfileItem = BaseEnvelopeItem<ProfileItemHeaders, Profile>;
105115
export type ProfileChunkItem = BaseEnvelopeItem<ProfileChunkItemHeaders, ProfileChunk>;
106116
export type SpanItem = BaseEnvelopeItem<SpanItemHeaders, Partial<SpanJSON>>;
107-
export type OtelLogItem = BaseEnvelopeItem<OtelLogItemHeaders, SerializedOtelLog>;
117+
export type LogContainerItem = BaseEnvelopeItem<LogContainerItemHeaders, SerializedLogContainer>;
108118
export type RawSecurityItem = BaseEnvelopeItem<RawSecurityHeaders, LegacyCSPReport>;
109119

110120
export type EventEnvelopeHeaders = { event_id: string; sent_at: string; trace?: Partial<DynamicSamplingContext> };
@@ -113,8 +123,7 @@ type CheckInEnvelopeHeaders = { trace?: DynamicSamplingContext };
113123
type ClientReportEnvelopeHeaders = BaseEnvelopeHeaders;
114124
type ReplayEnvelopeHeaders = BaseEnvelopeHeaders;
115125
type SpanEnvelopeHeaders = BaseEnvelopeHeaders & { trace?: DynamicSamplingContext };
116-
type OtelLogEnvelopeHeaders = BaseEnvelopeHeaders & { trace?: DynamicSamplingContext };
117-
126+
type LogEnvelopeHeaders = BaseEnvelopeHeaders;
118127
export type EventEnvelope = BaseEnvelope<
119128
EventEnvelopeHeaders,
120129
EventItem | AttachmentItem | UserFeedbackItem | FeedbackItem | ProfileItem
@@ -126,7 +135,7 @@ export type CheckInEnvelope = BaseEnvelope<CheckInEnvelopeHeaders, CheckInItem>;
126135
export type SpanEnvelope = BaseEnvelope<SpanEnvelopeHeaders, SpanItem>;
127136
export type ProfileChunkEnvelope = BaseEnvelope<BaseEnvelopeHeaders, ProfileChunkItem>;
128137
export type RawSecurityEnvelope = BaseEnvelope<BaseEnvelopeHeaders, RawSecurityItem>;
129-
export type OtelLogEnvelope = BaseEnvelope<OtelLogEnvelopeHeaders, OtelLogItem>;
138+
export type LogEnvelope = BaseEnvelope<LogEnvelopeHeaders, LogContainerItem>;
130139

131140
export type Envelope =
132141
| EventEnvelope
@@ -137,6 +146,5 @@ export type Envelope =
137146
| CheckInEnvelope
138147
| SpanEnvelope
139148
| RawSecurityEnvelope
140-
| OtelLogEnvelope;
141-
149+
| LogEnvelope;
142150
export type EnvelopeItem = Envelope[1][number];

0 commit comments

Comments
 (0)