@@ -271,6 +271,12 @@ private void fillEndpoint(OpenTelemetryEndpoint endpoint) {
271271 @ CanIgnoreReturnValue
272272 @ SuppressWarnings ({"UnusedMethod" , "EffectivelyPrivate" })
273273 public synchronized Tracer .Span start (RedisCommand <?, ?, ?> command ) {
274+ // Extract args BEFORE calling start() so db.statement can include them
275+ // when it's set on SpanBuilder (making it available to samplers)
276+ if (command .getArgs () != null ) {
277+ argsList = OtelCommandArgsUtil .getCommandArgs (command .getArgs ());
278+ }
279+
274280 start ();
275281 long startNanos = System .nanoTime ();
276282
@@ -280,10 +286,6 @@ public synchronized Tracer.Span start(RedisCommand<?, ?, ?> command) {
280286 }
281287 span .updateName (command .getType ().toString ());
282288
283- if (command .getArgs () != null ) {
284- argsList = OtelCommandArgsUtil .getCommandArgs (command .getArgs ());
285- }
286-
287289 if (command instanceof CompleteableCommand ) {
288290 CompleteableCommand <?> completeableCommand = (CompleteableCommand <?>) command ;
289291 completeableCommand .onComplete (
@@ -311,8 +313,26 @@ public synchronized Tracer.Span start(RedisCommand<?, ?, ?> command) {
311313 @ Override
312314 @ CanIgnoreReturnValue
313315 public synchronized Tracer .Span start () {
316+ // Set db.statement on SpanBuilder before starting span so it's available to samplers
317+ if (name != null ) {
318+ String statement = sanitizer .sanitize (name , argsList != null ? argsList : splitArgs (argsString ));
319+ if (statement != null ) {
320+ if (SemconvStability .emitStableDatabaseSemconv ()) {
321+ spanBuilder .setAttribute (DB_QUERY_TEXT , statement );
322+ attributesBuilder .put (DB_QUERY_TEXT , statement );
323+ }
324+ if (SemconvStability .emitOldDatabaseSemconv ()) {
325+ spanBuilder .setAttribute (DB_STATEMENT , statement );
326+ attributesBuilder .put (DB_STATEMENT , statement );
327+ }
328+ }
329+ }
330+
314331 span = spanBuilder .startSpan ();
315332 spanStartNanos = System .nanoTime ();
333+ // Note: Span name cannot be set on SpanBuilder because it's set during tracer.spanBuilder(name)
334+ // call in nextSpan(), and we don't know the actual command name at that point. We have to update
335+ // the name after the span starts.
316336 if (name != null ) {
317337 span .updateName (name );
318338 }
@@ -401,19 +421,11 @@ public synchronized void finish() {
401421 }
402422
403423 private void finish (Span span , long startTime ) {
404- if (name != null ) {
405- String statement =
406- sanitizer .sanitize (name , argsList != null ? argsList : splitArgs (argsString ));
407- if (SemconvStability .emitStableDatabaseSemconv ()) {
408- span .setAttribute (DB_QUERY_TEXT , statement );
409- metrics .onEnd (
410- metrics .onStart (Context .current (), Attributes .empty (), startTime ),
411- attributesBuilder .build (),
412- System .nanoTime ());
413- }
414- if (SemconvStability .emitOldDatabaseSemconv ()) {
415- span .setAttribute (DB_STATEMENT , statement );
416- }
424+ if (SemconvStability .emitStableDatabaseSemconv ()) {
425+ metrics .onEnd (
426+ metrics .onStart (Context .current (), Attributes .empty (), startTime ),
427+ attributesBuilder .build (),
428+ System .nanoTime ());
417429 }
418430 span .end ();
419431 }
0 commit comments