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