@@ -42,7 +42,7 @@ export function inferSpanData(spanName: string, attributes: SpanAttributes, kind
42
42
// eslint-disable-next-line deprecation/deprecation
43
43
const httpMethod = attributes [ ATTR_HTTP_REQUEST_METHOD ] || attributes [ SEMATTRS_HTTP_METHOD ] ;
44
44
if ( httpMethod ) {
45
- return descriptionForHttpMethod ( { attributes, name : getOriginalName ( spanName , attributes ) , kind } , httpMethod ) ;
45
+ return descriptionForHttpMethod ( { attributes, name : spanName , kind } , httpMethod ) ;
46
46
}
47
47
48
48
// eslint-disable-next-line deprecation/deprecation
@@ -64,9 +64,8 @@ export function inferSpanData(spanName: string, attributes: SpanAttributes, kind
64
64
const rpcService = attributes [ SEMATTRS_RPC_SERVICE ] ;
65
65
if ( rpcService ) {
66
66
return {
67
+ ...getUserUpdatedNameAndSource ( spanName , attributes , 'route' ) ,
67
68
op : 'rpc' ,
68
- description : getOriginalName ( spanName , attributes ) ,
69
- source : customSourceOrRoute ,
70
69
} ;
71
70
}
72
71
@@ -75,9 +74,8 @@ export function inferSpanData(spanName: string, attributes: SpanAttributes, kind
75
74
const messagingSystem = attributes [ SEMATTRS_MESSAGING_SYSTEM ] ;
76
75
if ( messagingSystem ) {
77
76
return {
77
+ ...getUserUpdatedNameAndSource ( spanName , attributes , customSourceOrRoute ) ,
78
78
op : 'message' ,
79
- description : getOriginalName ( spanName , attributes ) ,
80
- source : customSourceOrRoute ,
81
79
} ;
82
80
}
83
81
@@ -86,9 +84,8 @@ export function inferSpanData(spanName: string, attributes: SpanAttributes, kind
86
84
const faasTrigger = attributes [ SEMATTRS_FAAS_TRIGGER ] ;
87
85
if ( faasTrigger ) {
88
86
return {
87
+ ...getUserUpdatedNameAndSource ( spanName , attributes , customSourceOrRoute ) ,
89
88
op : faasTrigger . toString ( ) ,
90
- description : getOriginalName ( spanName , attributes ) ,
91
- source : customSourceOrRoute ,
92
89
} ;
93
90
}
94
91
@@ -108,14 +105,27 @@ export function parseSpanDescription(span: AbstractSpan): SpanDescription {
108
105
const attributes = spanHasAttributes ( span ) ? span . attributes : { } ;
109
106
const name = spanHasName ( span ) ? span . name : '<unknown>' ;
110
107
const kind = getSpanKind ( span ) ;
108
+ // console.log('x parseSpanDesc', { attributes, name, kind });
111
109
112
- return inferSpanData ( name , attributes , kind ) ;
110
+ const res = inferSpanData ( name , attributes , kind ) ;
111
+
112
+ // console.log('x parseSpanDesc res', res);
113
+ return res ;
113
114
}
114
115
115
116
function descriptionForDbSystem ( { attributes, name } : { attributes : Attributes ; name : string } ) : SpanDescription {
116
- // if we already set the source to custom, we don't overwrite the span description but just adjust the op
117
+ // if we already have a custom name, we don't overwrite it but only set the op
118
+ if ( typeof attributes [ '_sentry_span_name_set_by_user' ] === 'string' ) {
119
+ return {
120
+ op : 'db' ,
121
+ description : attributes [ '_sentry_span_name_set_by_user' ] ,
122
+ source : ( attributes [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] as TransactionSource ) || 'custom' ,
123
+ } ;
124
+ }
125
+
126
+ // if we already have the source set to custom, we don't overwrite the span description but only set the op
117
127
if ( attributes [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] === 'custom' ) {
118
- return { op : 'db' , description : getOriginalName ( name , attributes ) , source : 'custom' } ;
128
+ return { op : 'db' , description : name , source : 'custom' } ;
119
129
}
120
130
121
131
// Use DB statement (Ex "SELECT * FROM table") if possible as description.
@@ -151,7 +161,7 @@ export function descriptionForHttpMethod(
151
161
const { urlPath, url, query, fragment, hasRoute } = getSanitizedUrl ( attributes , kind ) ;
152
162
153
163
if ( ! urlPath ) {
154
- return { op : opParts . join ( '.' ) , description : getOriginalName ( name , attributes ) , source : 'custom' } ;
164
+ return { ... getUserUpdatedNameAndSource ( name , attributes ) , op : opParts . join ( '.' ) } ;
155
165
}
156
166
157
167
const graphqlOperationsAttribute = attributes [ SEMANTIC_ATTRIBUTE_SENTRY_GRAPHQL_OPERATION ] ;
@@ -161,12 +171,12 @@ export function descriptionForHttpMethod(
161
171
162
172
// When the http span has a graphql operation, append it to the description
163
173
// We add these in the graphqlIntegration
164
- const description = graphqlOperationsAttribute
174
+ const inferredDescription = graphqlOperationsAttribute
165
175
? `${ baseDescription } (${ getGraphqlOperationNamesFromAttribute ( graphqlOperationsAttribute ) } )`
166
176
: baseDescription ;
167
177
168
178
// If `httpPath` is a root path, then we can categorize the transaction source as route.
169
- const source : TransactionSource = hasRoute || urlPath === '/' ? 'route' : 'url' ;
179
+ const inferredSource : TransactionSource = hasRoute || urlPath === '/' ? 'route' : 'url' ;
170
180
171
181
const data : Record < string , string > = { } ;
172
182
@@ -190,15 +200,22 @@ export function descriptionForHttpMethod(
190
200
const origin = attributes [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] || 'manual' ;
191
201
const isManualSpan = ! `${ origin } ` . startsWith ( 'auto' ) ;
192
202
193
- // If users (or in very rare occasions we) set the source to custom, we don't overwrite it
203
+ // If users (or in very rare occasions we) set the source to custom, we don't overwrite the name
194
204
const alreadyHasCustomSource = attributes [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] === 'custom' ;
195
205
196
- const useInferredDescription = ! alreadyHasCustomSource && ( isClientOrServerKind || ! isManualSpan ) ;
206
+ const useInferredDescription =
207
+ ! alreadyHasCustomSource &&
208
+ attributes [ '_sentry_span_name_set_by_user' ] == null &&
209
+ ( isClientOrServerKind || ! isManualSpan ) ;
210
+
211
+ const { description, source } = useInferredDescription
212
+ ? { description : inferredDescription , source : inferredSource }
213
+ : getUserUpdatedNameAndSource ( name , attributes ) ;
197
214
198
215
return {
199
216
op : opParts . join ( '.' ) ,
200
- description : useInferredDescription ? description : getOriginalName ( name , attributes ) ,
201
- source : useInferredDescription ? source : 'custom' ,
217
+ description,
218
+ source,
202
219
data,
203
220
} ;
204
221
}
@@ -265,15 +282,32 @@ export function getSanitizedUrl(
265
282
}
266
283
267
284
/**
268
- * Because Otel decided to mutate span names via `span.updateName`, the only way to ensure
269
- * that a user-set span name is preserved is to store it as a tmp attribute on the span.
285
+ * Because Otel instrumentation sometimes mutates span names via `span.updateName`, the only way
286
+ * to ensure that a user-set span name is preserved is to store it as a tmp attribute on the span.
270
287
* We delete this attribute once we're done with it when preparing the event envelope.
288
+ *
289
+ * This temp attribute always takes precedence over the original name.
290
+ *
291
+ * We also need to take care of setting the correct source. Users can always update the source
292
+ * after updating the name, so we need to respect that.
293
+ *
271
294
* @internal exported only for testing
272
295
*/
273
- export function getOriginalName ( name : string , attributes : Attributes ) : string {
274
- return attributes [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] === 'custom' &&
275
- attributes [ '_sentry_span_name_set_by_user' ] &&
276
- typeof attributes [ '_sentry_span_name_set_by_user' ] === 'string'
277
- ? attributes [ '_sentry_span_name_set_by_user' ]
278
- : name ;
296
+ export function getUserUpdatedNameAndSource (
297
+ originalName : string ,
298
+ attributes : Attributes ,
299
+ fallbackSource : TransactionSource = 'custom' ,
300
+ ) : {
301
+ description : string ;
302
+ source : TransactionSource ;
303
+ } {
304
+ const source = ( attributes [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] as TransactionSource ) || fallbackSource ;
305
+
306
+ if ( attributes [ '_sentry_span_name_set_by_user' ] && typeof attributes [ '_sentry_span_name_set_by_user' ] === 'string' )
307
+ return {
308
+ description : attributes [ '_sentry_span_name_set_by_user' ] ,
309
+ source,
310
+ } ;
311
+
312
+ return { description : originalName , source } ;
279
313
}
0 commit comments