13
13
# limitations under the License.
14
14
15
15
import asyncio
16
+ from time import time_ns
16
17
17
18
import redis
18
19
import redis .asyncio
@@ -326,6 +327,30 @@ def test_basics(self):
326
327
)
327
328
self .assertEqual (span .attributes .get ("db.redis.args_length" ), 2 )
328
329
330
+ def test_execute_command_traced_full_time (self ):
331
+ """Command should be traced for coroutine execution time, not creation time."""
332
+ coro_created_time = None
333
+ finish_time = None
334
+
335
+ async def pipeline_simple ():
336
+ nonlocal coro_created_time
337
+ nonlocal finish_time
338
+
339
+ # delay coroutine creation from coroutine execution
340
+ coro = self .redis_client .get ("foo" )
341
+ coro_created_time = time_ns ()
342
+ await coro
343
+ finish_time = time_ns ()
344
+
345
+ # create coroutine
346
+ async_call (pipeline_simple ())
347
+
348
+ spans = self .memory_exporter .get_finished_spans ()
349
+ self .assertEqual (len (spans ), 1 )
350
+ span = spans [0 ]
351
+ self .assertTrue (span .start_time > coro_created_time )
352
+ self .assertTrue (span .end_time < finish_time )
353
+
329
354
def test_pipeline_traced (self ):
330
355
async def pipeline_simple ():
331
356
async with self .redis_client .pipeline (
@@ -348,6 +373,36 @@ async def pipeline_simple():
348
373
)
349
374
self .assertEqual (span .attributes .get ("db.redis.pipeline_length" ), 3 )
350
375
376
+ def test_pipeline_traced_full_time (self ):
377
+ """Command should be traced for coroutine execution time, not creation time."""
378
+ coro_created_time = None
379
+ finish_time = None
380
+
381
+ async def pipeline_simple ():
382
+ async with self .redis_client .pipeline (
383
+ transaction = False
384
+ ) as pipeline :
385
+ nonlocal coro_created_time
386
+ nonlocal finish_time
387
+ pipeline .set ("blah" , 32 )
388
+ pipeline .rpush ("foo" , "éé" )
389
+ pipeline .hgetall ("xxx" )
390
+
391
+ # delay coroutine creation from coroutine execution
392
+ coro = pipeline .execute ()
393
+ coro_created_time = time_ns ()
394
+ await coro
395
+ finish_time = time_ns ()
396
+
397
+ # create coroutine
398
+ async_call (pipeline_simple ())
399
+
400
+ spans = self .memory_exporter .get_finished_spans ()
401
+ self .assertEqual (len (spans ), 1 )
402
+ span = spans [0 ]
403
+ self .assertTrue (span .start_time > coro_created_time )
404
+ self .assertTrue (span .end_time < finish_time )
405
+
351
406
def test_pipeline_immediate (self ):
352
407
async def pipeline_immediate ():
353
408
async with self .redis_client .pipeline () as pipeline :
@@ -367,6 +422,34 @@ async def pipeline_immediate():
367
422
span .attributes .get (SpanAttributes .DB_STATEMENT ), "SET b 2"
368
423
)
369
424
425
+ def test_pipeline_immediate_traced_full_time (self ):
426
+ """Command should be traced for coroutine execution time, not creation time."""
427
+ coro_created_time = None
428
+ finish_time = None
429
+
430
+ async def pipeline_simple ():
431
+ async with self .redis_client .pipeline (
432
+ transaction = False
433
+ ) as pipeline :
434
+ nonlocal coro_created_time
435
+ nonlocal finish_time
436
+ pipeline .set ("a" , 1 )
437
+
438
+ # delay coroutine creation from coroutine execution
439
+ coro = pipeline .immediate_execute_command ("SET" , "b" , 2 )
440
+ coro_created_time = time_ns ()
441
+ await coro
442
+ finish_time = time_ns ()
443
+
444
+ # create coroutine
445
+ async_call (pipeline_simple ())
446
+
447
+ spans = self .memory_exporter .get_finished_spans ()
448
+ self .assertEqual (len (spans ), 1 )
449
+ span = spans [0 ]
450
+ self .assertTrue (span .start_time > coro_created_time )
451
+ self .assertTrue (span .end_time < finish_time )
452
+
370
453
def test_parent (self ):
371
454
"""Ensure OpenTelemetry works with redis."""
372
455
ot_tracer = trace .get_tracer ("redis_svc" )
@@ -416,6 +499,30 @@ def test_basics(self):
416
499
)
417
500
self .assertEqual (span .attributes .get ("db.redis.args_length" ), 2 )
418
501
502
+ def test_execute_command_traced_full_time (self ):
503
+ """Command should be traced for coroutine execution time, not creation time."""
504
+ coro_created_time = None
505
+ finish_time = None
506
+
507
+ async def pipeline_simple ():
508
+ nonlocal coro_created_time
509
+ nonlocal finish_time
510
+
511
+ # delay coroutine creation from coroutine execution
512
+ coro = self .redis_client .get ("foo" )
513
+ coro_created_time = time_ns ()
514
+ await coro
515
+ finish_time = time_ns ()
516
+
517
+ # create coroutine
518
+ async_call (pipeline_simple ())
519
+
520
+ spans = self .memory_exporter .get_finished_spans ()
521
+ self .assertEqual (len (spans ), 1 )
522
+ span = spans [0 ]
523
+ self .assertTrue (span .start_time > coro_created_time )
524
+ self .assertTrue (span .end_time < finish_time )
525
+
419
526
def test_pipeline_traced (self ):
420
527
async def pipeline_simple ():
421
528
async with self .redis_client .pipeline (
@@ -438,6 +545,36 @@ async def pipeline_simple():
438
545
)
439
546
self .assertEqual (span .attributes .get ("db.redis.pipeline_length" ), 3 )
440
547
548
+ def test_pipeline_traced_full_time (self ):
549
+ """Command should be traced for coroutine execution time, not creation time."""
550
+ coro_created_time = None
551
+ finish_time = None
552
+
553
+ async def pipeline_simple ():
554
+ async with self .redis_client .pipeline (
555
+ transaction = False
556
+ ) as pipeline :
557
+ nonlocal coro_created_time
558
+ nonlocal finish_time
559
+ pipeline .set ("blah" , 32 )
560
+ pipeline .rpush ("foo" , "éé" )
561
+ pipeline .hgetall ("xxx" )
562
+
563
+ # delay coroutine creation from coroutine execution
564
+ coro = pipeline .execute ()
565
+ coro_created_time = time_ns ()
566
+ await coro
567
+ finish_time = time_ns ()
568
+
569
+ # create coroutine
570
+ async_call (pipeline_simple ())
571
+
572
+ spans = self .memory_exporter .get_finished_spans ()
573
+ self .assertEqual (len (spans ), 1 )
574
+ span = spans [0 ]
575
+ self .assertTrue (span .start_time > coro_created_time )
576
+ self .assertTrue (span .end_time < finish_time )
577
+
441
578
def test_parent (self ):
442
579
"""Ensure OpenTelemetry works with redis."""
443
580
ot_tracer = trace .get_tracer ("redis_svc" )
0 commit comments