1- import type { TypedAttributeValue } from '../attributes' ;
2- import { attributeValueToTypedAttributeValue } from '../attributes' ;
1+ import { attributeValueToTypedAttributeValue , TypedAttributeValue } from '../attributes' ;
32import { getGlobalSingleton } from '../carrier' ;
43import type { Client } from '../client' ;
54import { getClient , getCurrentScope , getGlobalScope , getIsolationScope } from '../currentScopes' ;
@@ -18,6 +17,31 @@ import { createLogEnvelope } from './envelope';
1817
1918const MAX_LOG_BUFFER_SIZE = 100 ;
2019
20+ /**
21+ * Converts a log attribute to a serialized log attribute.
22+ *
23+ * @param key - The key of the log attribute.
24+ * @param value - The value of the log attribute.
25+ * @returns The serialized log attribute.
26+ */
27+ export function attributeValueToTypedAttributeValueWithFallback ( value : unknown ) : TypedAttributeValue {
28+ const typedAttributeValue = attributeValueToTypedAttributeValue ( value ) ;
29+ if ( typedAttributeValue ) {
30+ return typedAttributeValue ;
31+ }
32+
33+ let stringValue = '' ;
34+ try {
35+ stringValue = JSON . stringify ( value ) ?? '' ;
36+ } catch {
37+ // Do nothing
38+ }
39+ return {
40+ value : stringValue ,
41+ type : 'string' ,
42+ } ;
43+ }
44+
2145/**
2246 * Sets a log attribute if the value exists and the attribute key is not already present.
2347 *
@@ -98,7 +122,7 @@ export function _INTERNAL_captureLog(
98122
99123 const {
100124 user : { id, email, username } ,
101- attributes : scopeAttributes ,
125+ attributes : scopeAttributes = { } ,
102126 } = getMergedScopeData ( currentScope ) ;
103127 setLogAttribute ( processedLogAttributes , 'user.id' , id , false ) ;
104128 setLogAttribute ( processedLogAttributes , 'user.email' , email , false ) ;
@@ -141,7 +165,7 @@ export function _INTERNAL_captureLog(
141165 // Add the parent span ID to the log attributes for trace context
142166 setLogAttribute ( processedLogAttributes , 'sentry.trace.parent_span_id' , span ?. spanContext ( ) . spanId ) ;
143167
144- const processedLog = { ...beforeLog , attributes : { ... scopeAttributes , ... processedLogAttributes } } ;
168+ const processedLog = { ...beforeLog , attributes : processedLogAttributes } ;
145169
146170 client . emit ( 'beforeCaptureLog' , processedLog ) ;
147171
@@ -153,24 +177,33 @@ export function _INTERNAL_captureLog(
153177 return ;
154178 }
155179
156- const { level, message, attributes = { } , severityNumber } = log ;
180+ const { level, message, attributes : logAttributes = { } , severityNumber } = log ;
157181
158182 const serializedLog : SerializedLog = {
159183 timestamp : timestampInSeconds ( ) ,
160184 level,
161185 body : message ,
162186 trace_id : traceContext ?. trace_id ,
163187 severity_number : severityNumber ?? SEVERITY_TEXT_TO_SEVERITY_NUMBER [ level ] ,
164- attributes : Object . keys ( attributes ) . reduce (
165- ( acc , key ) => {
166- const typedAttributeValue = attributeValueToTypedAttributeValue ( attributes [ key ] ) ;
167- if ( typedAttributeValue ) {
168- acc [ key ] = typedAttributeValue ;
169- }
170- return acc ;
171- } ,
172- { } as Record < string , TypedAttributeValue > ,
173- ) ,
188+ attributes : {
189+ ...Object . keys ( scopeAttributes ) . reduce (
190+ ( acc , key ) => {
191+ const attributeValue = attributeValueToTypedAttributeValue ( scopeAttributes [ key ] ) ;
192+ if ( attributeValue ) {
193+ acc [ key ] = attributeValue ;
194+ }
195+ return acc ;
196+ } ,
197+ { } as Record < string , TypedAttributeValue > ,
198+ ) ,
199+ ...Object . keys ( logAttributes ) . reduce (
200+ ( acc , key ) => {
201+ acc [ key ] = attributeValueToTypedAttributeValueWithFallback ( logAttributes [ key ] ) ;
202+ return acc ;
203+ } ,
204+ { } as Record < string , TypedAttributeValue > ,
205+ ) ,
206+ } ,
174207 } ;
175208
176209 captureSerializedLog ( client , serializedLog ) ;
0 commit comments