24
24
import copy
25
25
import logging
26
26
from contextlib import contextmanager
27
- from typing import Callable , Dict , Iterable , Iterator , Generator , NoReturn , Optional
27
+ from typing import Callable , Iterator , Generator , Optional
28
28
29
29
import grpc
30
30
31
31
from opentelemetry import metrics , trace
32
32
from opentelemetry .context import attach , detach
33
- from opentelemetry .instrumentation .grpc ._types import Metadata , ProtoMessage , ProtoMessageOrIterator
34
- from opentelemetry .instrumentation .grpc ._utilities import _EventMetricRecorder , _MetricKind
33
+ from opentelemetry .instrumentation .grpc ._types import ProtoMessage , ProtoMessageOrIterator
34
+ from opentelemetry .instrumentation .grpc ._utilities import _EventMetricRecorder , _MetricKind , _OpenTelemetryServicerContext
35
35
from opentelemetry .propagate import extract
36
36
from opentelemetry .semconv .trace import MessageTypeValues , RpcSystemValues , SpanAttributes
37
37
from opentelemetry .trace .status import Status , StatusCode
@@ -79,150 +79,6 @@ def _wrap_rpc_behavior(
79
79
)
80
80
81
81
82
- # pylint:disable=abstract-method
83
- class _OpenTelemetryServicerContext (grpc .ServicerContext ):
84
-
85
- def __init__ (
86
- self ,
87
- servicer_context : grpc .ServicerContext ,
88
- active_span : trace .Span
89
- ) -> None :
90
- self ._servicer_context = servicer_context
91
- self ._active_span = active_span
92
- self ._code = grpc .StatusCode .OK
93
- self ._details = None
94
- super ().__init__ ()
95
-
96
- def __getattr__ (self , attr ):
97
- return getattr (self ._servicer_context , attr )
98
-
99
- # Interface of grpc.RpcContext
100
-
101
- # pylint: disable=invalid-name
102
- def add_callback (self , fn : Callable [[], None ]) -> None :
103
- return self ._servicer_context .add_callback (fn )
104
-
105
- def cancel (self ) -> None :
106
- self ._code = grpc .StatusCode .CANCELLED
107
- self ._details = grpc .StatusCode .CANCELLED .value [1 ]
108
- self ._active_span .set_attribute (
109
- SpanAttributes .RPC_GRPC_STATUS_CODE , self ._code .value [0 ]
110
- )
111
- self ._active_span .set_status (
112
- Status (
113
- status_code = StatusCode .ERROR ,
114
- description = f"{ self ._code } : { self ._details } " ,
115
- )
116
- )
117
- return self ._servicer_context .cancel ()
118
-
119
- def is_active (self ) -> bool :
120
- return self ._servicer_context .is_active ()
121
-
122
- def time_remaining (self ) -> Optional [float ]:
123
- return self ._servicer_context .time_remaining ()
124
-
125
- # Interface of grpc.ServicerContext
126
-
127
- def abort (self , code : grpc .StatusCode , details : str ) -> NoReturn :
128
- if not hasattr (self ._servicer_context , "abort" ):
129
- raise RuntimeError (
130
- "abort() is not supported with the installed version of grpcio"
131
- )
132
- self ._code = code
133
- self ._details = details
134
- self ._active_span .set_attribute (
135
- SpanAttributes .RPC_GRPC_STATUS_CODE , code .value [0 ]
136
- )
137
- self ._active_span .set_status (
138
- Status (
139
- status_code = StatusCode .ERROR ,
140
- description = f"{ code } : { details } " ,
141
- )
142
- )
143
- return self ._servicer_context .abort (code , details )
144
-
145
- def abort_with_status (self , status : grpc .Status ) -> NoReturn :
146
- if not hasattr (self ._servicer_context , "abort_with_status" ):
147
- raise RuntimeError (
148
- "abort_with_status() is not supported with the installed "
149
- "version of grpcio"
150
- )
151
- return self ._servicer_context .abort_with_status (status )
152
-
153
- def auth_context (self ) -> Dict [str , Iterable [bytes ]]:
154
- return self ._servicer_context .auth_context ()
155
-
156
- def code (self ) -> grpc .StatusCode :
157
- if not hasattr (self ._servicer_context , "code" ):
158
- raise RuntimeError (
159
- "code() is not supported with the installed version of grpcio"
160
- )
161
- return self ._servicer_context .code ()
162
-
163
- def details (self ) -> str :
164
- if not hasattr (self ._servicer_context , "details" ):
165
- raise RuntimeError (
166
- "details() is not supported with the installed version of "
167
- "grpcio"
168
- )
169
- return self ._servicer_context .details ()
170
-
171
- def disable_next_message_compression (self ) -> None :
172
- return self ._service_context .disable_next_message_compression ()
173
-
174
- def invocation_metadata (self ) -> Metadata :
175
- return self ._servicer_context .invocation_metadata ()
176
-
177
- def peer (self ) -> str :
178
- return self ._servicer_context .peer ()
179
-
180
- def peer_identities (self ) -> Optional [Iterable [bytes ]]:
181
- return self ._servicer_context .peer_identities ()
182
-
183
- def peer_identity_key (self ) -> Optional [str ]:
184
- return self ._servicer_context .peer_identity_key ()
185
-
186
- def send_initial_metadata (self , initial_metadata : Metadata ) -> None :
187
- return self ._servicer_context .send_initial_metadata (initial_metadata )
188
-
189
- def set_code (self , code : grpc .StatusCode ) -> None :
190
- self ._code = code
191
- # use details if we already have it, otherwise the status description
192
- details = self ._details or code .value [1 ]
193
- self ._active_span .set_attribute (
194
- SpanAttributes .RPC_GRPC_STATUS_CODE , code .value [0 ]
195
- )
196
- if code != grpc .StatusCode .OK :
197
- self ._active_span .set_status (
198
- Status (
199
- status_code = StatusCode .ERROR ,
200
- description = f"{ code } : { details } " ,
201
- )
202
- )
203
- return self ._servicer_context .set_code (code )
204
-
205
- def set_compression (self , compression : grpc .Compression ) -> None :
206
- return self ._servicer_context .set_compression (compression )
207
-
208
- def set_details (self , details : str ) -> None :
209
- self ._details = details
210
- if self ._code != grpc .StatusCode .OK :
211
- self ._active_span .set_status (
212
- Status (
213
- status_code = StatusCode .ERROR ,
214
- description = f"{ self ._code } : { details } " ,
215
- )
216
- )
217
- return self ._servicer_context .set_details (details )
218
-
219
- def set_trailing_metadata (self , trailing_metadata : Metadata ) -> None :
220
- return self ._servicer_context .set_trailing_metadata (trailing_metadata )
221
-
222
- def trailing_metadata (self ) -> Metadata :
223
- return self ._servicer_context .trailing_metadata ()
224
-
225
-
226
82
# pylint:disable=abstract-method
227
83
# pylint:disable=no-self-use
228
84
# pylint:disable=unused-argument
@@ -378,6 +234,7 @@ def intercept_unary_unary(
378
234
context : grpc .ServicerContext ,
379
235
full_method : str
380
236
) -> ProtoMessage :
237
+
381
238
with self ._set_remote_context (context ):
382
239
metric_attributes = self ._create_attributes (context , full_method )
383
240
span_attributes = copy .deepcopy (metric_attributes )
@@ -393,12 +250,11 @@ def intercept_unary_unary(
393
250
record_exception = False ,
394
251
set_status_on_exception = False
395
252
) as span :
396
- with self ._record_duration_manager (metric_attributes , context ):
253
+ # wrap the context
254
+ context = _OpenTelemetryServicerContext (context , span )
397
255
256
+ with self ._record_duration_manager (metric_attributes , context ):
398
257
try :
399
- # wrap the context
400
- context = _OpenTelemetryServicerContext (context , span )
401
-
402
258
# record the request
403
259
self ._record_unary_request (
404
260
span ,
@@ -448,6 +304,7 @@ def intercept_unary_stream(
448
304
context : grpc .ServicerContext ,
449
305
full_method : str
450
306
) -> Iterator [ProtoMessage ]:
307
+
451
308
with self ._set_remote_context (context ):
452
309
metric_attributes = self ._create_attributes (context , full_method )
453
310
span_attributes = copy .deepcopy (metric_attributes )
@@ -463,12 +320,11 @@ def intercept_unary_stream(
463
320
record_exception = False ,
464
321
set_status_on_exception = False
465
322
) as span :
323
+ # wrap the context
324
+ context = _OpenTelemetryServicerContext (context , span )
466
325
467
326
with self ._record_duration_manager (metric_attributes , context ):
468
327
try :
469
- # wrap the context
470
- context = _OpenTelemetryServicerContext (context , span )
471
-
472
328
# record the request
473
329
self ._record_unary_request (
474
330
span ,
@@ -516,6 +372,7 @@ def intercept_stream_unary(
516
372
context : grpc .ServicerContext ,
517
373
full_method : str
518
374
) -> ProtoMessage :
375
+
519
376
with self ._set_remote_context (context ):
520
377
metric_attributes = self ._create_attributes (context , full_method )
521
378
span_attributes = copy .deepcopy (metric_attributes )
@@ -531,12 +388,11 @@ def intercept_stream_unary(
531
388
record_exception = False ,
532
389
set_status_on_exception = False
533
390
) as span :
534
- with self ._record_duration_manager (metric_attributes , context ):
391
+ # wrap the context
392
+ context = _OpenTelemetryServicerContext (context , span )
535
393
394
+ with self ._record_duration_manager (metric_attributes , context ):
536
395
try :
537
- # wrap the context
538
- context = _OpenTelemetryServicerContext (context , span )
539
-
540
396
# wrap the request iterator with a recorder
541
397
request_iterator = self ._record_streaming_request (
542
398
span ,
@@ -587,6 +443,7 @@ def intercept_stream_stream(
587
443
context : grpc .ServicerContext ,
588
444
full_method : str
589
445
) -> Iterator [ProtoMessage ]:
446
+
590
447
with self ._set_remote_context (context ):
591
448
metric_attributes = self ._create_attributes (context , full_method )
592
449
span_attributes = copy .deepcopy (metric_attributes )
@@ -602,12 +459,11 @@ def intercept_stream_stream(
602
459
record_exception = False ,
603
460
set_status_on_exception = False
604
461
) as span :
462
+ # wrap the context
463
+ context = _OpenTelemetryServicerContext (context , span )
605
464
606
465
with self ._record_duration_manager (metric_attributes , context ):
607
466
try :
608
- # wrap the context
609
- context = _OpenTelemetryServicerContext (context , span )
610
-
611
467
# wrap the request iterator with a recorder
612
468
request_iterator = self ._record_streaming_request (
613
469
span ,
0 commit comments