@@ -252,7 +252,7 @@ def __init__(self, meter, tracer):
252
252
self ._duration_histogram = self ._meter .create_histogram (
253
253
name = "rpc.server.duration" ,
254
254
unit = "ms" ,
255
- description = "measures the duration of the inbound rpc " ,
255
+ description = "measures duration of inbound RPC " ,
256
256
)
257
257
self ._request_size_histogram = self ._meter .create_histogram (
258
258
name = "rpc.server.request.size" ,
@@ -339,70 +339,16 @@ def _create_attributes(self, context, full_method):
339
339
def intercept_service (self , continuation , handler_call_details ):
340
340
def telemetry_wrapper (behavior , request_streaming , response_streaming ):
341
341
def telemetry_interceptor (request_or_iterator , context ):
342
- with self ._set_remote_context (context ):
343
- attributes = self ._create_attributes (context , handler_call_details .method )
344
-
345
- with self ._tracer .start_as_current_span (
346
- name = handler_call_details .method ,
347
- kind = trace .SpanKind .SERVER ,
348
- attributes = attributes ,
349
- end_on_exit = False ,
350
- record_exception = False ,
351
- set_status_on_exception = False
352
- ) as span :
353
-
354
- try :
355
- # wrap the context
356
- context = _OpenTelemetryServicerContext (context , span )
357
-
358
- # wrap / log the request (iterator)
359
- if request_streaming :
360
- request_or_iterator = self ._log_stream_requests (
361
- request_or_iterator , span , attributes
362
- )
363
- else :
364
- self ._log_unary_request (
365
- request_or_iterator , span , attributes
366
- )
367
-
368
- # call the actual RPC and track the duration
369
- with self ._record_duration (attributes , context ):
370
- response_or_iterator = behavior (request_or_iterator , context )
371
-
372
- # wrap / log the response (iterator)
373
- if response_streaming :
374
- response_or_iterator = self ._log_stream_responses (
375
- response_or_iterator , span , attributes , context
376
- )
377
- else :
378
- self ._log_unary_response (
379
- response_or_iterator , span , attributes , context
380
- )
381
-
382
- return response_or_iterator
383
-
384
- except Exception as exc :
385
- # Bare exceptions are likely to be gRPC aborts, which
386
- # we handle in our context wrapper.
387
- # Here, we're interested in uncaught exceptions.
388
- # pylint:disable=unidiomatic-typecheck
389
- if type (exc ) != Exception :
390
- span .set_attribute (
391
- SpanAttributes .RPC_GRPC_STATUS_CODE ,
392
- grpc .StatusCode .UNKNOWN .value [0 ]
393
- )
394
- span .set_status (
395
- Status (
396
- status_code = StatusCode .ERROR ,
397
- description = f"{ type (exc ).__name__ } : { exc } " ,
398
- )
399
- )
400
- span .record_exception (exc )
401
- raise exc
402
-
403
- finally :
404
- if not response_streaming :
405
- span .end ()
342
+ if response_streaming :
343
+ return self ._intercept_streaming_response (
344
+ behavior , request_or_iterator , context ,
345
+ request_streaming , handler_call_details .method
346
+ )
347
+
348
+ return self ._intercept_unary_response (
349
+ behavior , request_or_iterator , context ,
350
+ request_streaming , handler_call_details .method
351
+ )
406
352
407
353
return telemetry_interceptor
408
354
@@ -411,6 +357,118 @@ def telemetry_interceptor(request_or_iterator, context):
411
357
telemetry_wrapper
412
358
)
413
359
360
+ def _intercept_unary_response (self , behavior , request_or_iterator , context , request_streaming , full_method ):
361
+ with self ._set_remote_context (context ):
362
+ attributes = self ._create_attributes (context , full_method )
363
+
364
+ with self ._tracer .start_as_current_span (
365
+ name = full_method ,
366
+ kind = trace .SpanKind .SERVER ,
367
+ attributes = attributes ,
368
+ end_on_exit = True ,
369
+ record_exception = False ,
370
+ set_status_on_exception = False
371
+ ) as span :
372
+
373
+ try :
374
+ # wrap the context
375
+ context = _OpenTelemetryServicerContext (context , span )
376
+
377
+ # wrap / log the request (iterator)
378
+ if request_streaming :
379
+ request_or_iterator = self ._log_streaming_request (
380
+ request_or_iterator , span , attributes
381
+ )
382
+ else :
383
+ self ._log_unary_request (
384
+ request_or_iterator , span , attributes
385
+ )
386
+
387
+ # call the actual RPC and track the duration
388
+ with self ._record_duration (attributes , context ):
389
+ response_or_iterator = behavior (request_or_iterator , context )
390
+
391
+ # log the response (iterator)
392
+ self ._log_unary_response (
393
+ response_or_iterator , span , attributes , context
394
+ )
395
+
396
+ return response_or_iterator
397
+
398
+ except Exception as exc :
399
+ # Bare exceptions are likely to be gRPC aborts, which
400
+ # we handle in our context wrapper.
401
+ # Here, we're interested in uncaught exceptions.
402
+ # pylint:disable=unidiomatic-typecheck
403
+ if type (exc ) != Exception :
404
+ span .set_attribute (
405
+ SpanAttributes .RPC_GRPC_STATUS_CODE ,
406
+ grpc .StatusCode .UNKNOWN .value [0 ]
407
+ )
408
+ span .set_status (
409
+ Status (
410
+ status_code = StatusCode .ERROR ,
411
+ description = f"{ type (exc ).__name__ } : { exc } " ,
412
+ )
413
+ )
414
+ span .record_exception (exc )
415
+ raise exc
416
+
417
+ def _intercept_streaming_response (self , behavior , request_or_iterator , context , request_streaming , full_method ):
418
+ with self ._set_remote_context (context ):
419
+ attributes = self ._create_attributes (context , full_method )
420
+
421
+ with self ._tracer .start_as_current_span (
422
+ name = full_method ,
423
+ kind = trace .SpanKind .SERVER ,
424
+ attributes = attributes ,
425
+ end_on_exit = True ,
426
+ record_exception = False ,
427
+ set_status_on_exception = False
428
+ ) as span :
429
+
430
+ try :
431
+ # wrap the context
432
+ context = _OpenTelemetryServicerContext (context , span )
433
+
434
+ # wrap / log the request (iterator)
435
+ if request_streaming :
436
+ request_or_iterator = self ._log_streaming_request (
437
+ request_or_iterator , span , attributes
438
+ )
439
+ else :
440
+ self ._log_unary_request (
441
+ request_or_iterator , span , attributes
442
+ )
443
+
444
+ # call the actual RPC and track the duration
445
+ with self ._record_duration (attributes , context ):
446
+ response_or_iterator = behavior (request_or_iterator , context )
447
+
448
+ # log the response (iterator)
449
+ yield from self ._log_streaming_response (
450
+ response_or_iterator , span , attributes , context
451
+ )
452
+
453
+ except Exception as exc :
454
+ # Bare exceptions are likely to be gRPC aborts, which
455
+ # we handle in our context wrapper.
456
+ # Here, we're interested in uncaught exceptions.
457
+ # pylint:disable=unidiomatic-typecheck
458
+ if type (exc ) != Exception :
459
+ span .set_attribute (
460
+ SpanAttributes .RPC_GRPC_STATUS_CODE ,
461
+ grpc .StatusCode .UNKNOWN .value [0 ]
462
+ )
463
+ span .set_status (
464
+ Status (
465
+ status_code = StatusCode .ERROR ,
466
+ description = f"{ type (exc ).__name__ } : { exc } " ,
467
+ )
468
+ )
469
+ span .record_exception (exc )
470
+ raise exc
471
+
414
472
def _log_unary_request (self , request , active_span , attributes ):
415
473
message_size_by = request .ByteSize ()
416
474
_add_message_event (
@@ -429,7 +487,7 @@ def _log_unary_response(self, response, active_span, attributes, context):
429
487
self ._response_size_histogram .record (message_size_by , attributes )
430
488
self ._responses_per_rpc_histogram .record (1 , attributes )
431
489
432
- def _log_stream_requests (self , request_iterator , active_span , attributes ):
490
+ def _log_streaming_request (self , request_iterator , active_span , attributes ):
433
491
req_id = 1
434
492
for req_id , msg in enumerate (request_iterator , start = 1 ):
435
493
message_size_by = msg .ByteSize ()
@@ -441,52 +499,28 @@ def _log_stream_requests(self, request_iterator, active_span, attributes):
441
499
442
500
self ._requests_per_rpc_histogram .record (req_id , attributes )
443
501
444
- def _log_stream_responses (self , response_iterator , active_span , attributes , context ):
445
- with trace .use_span (
446
- active_span ,
447
- end_on_exit = True ,
448
- record_exception = False ,
449
- set_status_on_exception = False
450
- ):
451
- try :
452
- res_id = 1
453
- for res_id , msg in enumerate (response_iterator , start = 1 ):
454
- message_size_by = msg .ByteSize ()
455
- _add_message_event (
456
- active_span , MessageTypeValues .SENT .value , message_size_by , message_id = res_id
457
- )
458
- self ._response_size_histogram .record (message_size_by , attributes )
459
- yield msg
460
- except Exception as exc :
461
- # Bare exceptions are likely to be gRPC aborts, which
462
- # we handle in our context wrapper.
463
- # Here, we're interested in uncaught exceptions.
464
- # pylint:disable=unidiomatic-typecheck
465
- if type (exc ) != Exception :
466
- active_span .set_attribute (
467
- SpanAttributes .RPC_GRPC_STATUS_CODE ,
468
- grpc .StatusCode .UNKNOWN .value [0 ]
469
- )
470
- active_span .set_status (
471
- Status (
472
- status_code = StatusCode .ERROR ,
473
- description = f"{ type (exc ).__name__ } : { exc } " ,
474
- )
475
- )
476
- active_span .record_exception (exc )
477
- raise exc
478
- finally :
479
- if context ._code != grpc .StatusCode .OK :
480
- attributes [SpanAttributes .RPC_GRPC_STATUS_CODE ] = context ._code .value [0 ]
481
- self ._responses_per_rpc_histogram .record (res_id , attributes )
502
+ def _log_streaming_response (self , response_iterator , active_span , attributes , context ):
503
+ try :
504
+ res_id = 1
505
+ for res_id , msg in enumerate (response_iterator , start = 1 ):
506
+ message_size_by = msg .ByteSize ()
507
+ _add_message_event (
508
+ active_span , MessageTypeValues .SENT .value , message_size_by , message_id = res_id
509
+ )
510
+ self ._response_size_histogram .record (message_size_by , attributes )
511
+ yield msg
512
+ finally :
513
+ if context ._code != grpc .StatusCode .OK :
514
+ attributes [SpanAttributes .RPC_GRPC_STATUS_CODE ] = context ._code .value [0 ]
515
+ self ._responses_per_rpc_histogram .record (res_id , attributes )
482
516
483
517
@contextmanager
484
518
def _record_duration (self , attributes , context ):
485
519
start = _time_ns ()
486
520
try :
487
521
yield
488
522
finally :
489
- duration = max (round ((_time_ns () - start ) * 1000 ), 0 )
523
+ duration = max (round ((_time_ns () - start ) / 1000 ), 0 )
490
524
if context ._code != grpc .StatusCode .OK :
491
525
attributes [SpanAttributes .RPC_GRPC_STATUS_CODE ] = context ._code .value [0 ]
492
526
self ._duration_histogram .record (duration , attributes )
0 commit comments