33
33
from opentelemetry .trace .status import Status , StatusCode
34
34
35
35
36
- class _GuardedSpan :
37
- def __init__ (self , span ):
38
- self .span = span
39
- self .generated_span = None
40
- self ._engaged = True
41
-
42
- def __enter__ (self ):
43
- self .generated_span = self .span .__enter__ ()
44
- return self
45
-
46
- def __exit__ (self , * args , ** kwargs ):
47
- if self ._engaged :
48
- self .generated_span = None
49
- return self .span .__exit__ (* args , ** kwargs )
50
- return False
51
-
52
- def release (self ):
53
- self ._engaged = False
54
- return self .span
55
-
56
-
57
36
class _CarrierSetter (Setter ):
58
37
"""We use a custom setter in order to be able to lower case
59
38
keys as is required by grpc.
@@ -68,7 +47,7 @@ def set(self, carrier: MutableMapping[str, str], key: str, value: str):
68
47
69
48
def _make_future_done_callback (span , rpc_info ):
70
49
def callback (response_future ):
71
- with span :
50
+ with trace . use_span ( span , end_on_exit = True ) :
72
51
code = response_future .code ()
73
52
if code != grpc .StatusCode .OK :
74
53
rpc_info .error = code
@@ -94,17 +73,17 @@ def _start_span(self, method):
94
73
SpanAttributes .RPC_SERVICE : service ,
95
74
}
96
75
97
- return self ._tracer .start_as_current_span (
98
- name = method , kind = trace .SpanKind .CLIENT , attributes = attributes
76
+ return self ._tracer .start_span (
77
+ name = method , kind = trace .SpanKind .CLIENT , attributes = attributes ,
99
78
)
100
79
101
80
# pylint:disable=no-self-use
102
- def _trace_result (self , guarded_span , rpc_info , result ):
81
+ def _trace_result (self , span , rpc_info , result ):
103
82
# If the RPC is called asynchronously, release the guard and add a
104
83
# callback so that the span can be finished once the future is done.
105
84
if isinstance (result , grpc .Future ):
106
85
result .add_done_callback (
107
- _make_future_done_callback (guarded_span . release () , rpc_info )
86
+ _make_future_done_callback (span , rpc_info )
108
87
)
109
88
return result
110
89
response = result
@@ -115,41 +94,43 @@ def _trace_result(self, guarded_span, rpc_info, result):
115
94
if isinstance (result , tuple ):
116
95
response = result [0 ]
117
96
rpc_info .response = response
118
-
97
+ span . end ()
119
98
return result
120
99
121
- def _start_guarded_span (self , * args , ** kwargs ):
122
- return _GuardedSpan (self ._start_span (* args , ** kwargs ))
123
-
124
100
def intercept_unary (self , request , metadata , client_info , invoker ):
125
101
if not metadata :
126
102
mutable_metadata = OrderedDict ()
127
103
else :
128
104
mutable_metadata = OrderedDict (metadata )
129
-
130
- with self ._start_guarded_span (client_info .full_method ) as guarded_span :
131
- inject (mutable_metadata , setter = _carrier_setter )
132
- metadata = tuple (mutable_metadata .items ())
133
-
134
- rpc_info = RpcInfo (
135
- full_method = client_info .full_method ,
136
- metadata = metadata ,
137
- timeout = client_info .timeout ,
138
- request = request ,
139
- )
140
-
105
+ span = self ._start_span (client_info .full_method )
106
+ with trace .use_span (span , record_exception = False , set_status_on_exception = False ):
141
107
try :
142
- result = invoker (request , metadata )
143
- except grpc .RpcError as err :
144
- guarded_span .generated_span .set_status (
145
- Status (StatusCode .ERROR )
108
+ inject (mutable_metadata , setter = _carrier_setter )
109
+ metadata = tuple (mutable_metadata .items ())
110
+
111
+ rpc_info = RpcInfo (
112
+ full_method = client_info .full_method ,
113
+ metadata = metadata ,
114
+ timeout = client_info .timeout ,
115
+ request = request ,
146
116
)
147
- guarded_span .generated_span .set_attribute (
148
- SpanAttributes .RPC_GRPC_STATUS_CODE , err .code ().value [0 ]
149
- )
150
- raise err
151
117
152
- return self ._trace_result (guarded_span , rpc_info , result )
118
+ result = invoker (request , metadata )
119
+ except Exception as exc :
120
+ if isinstance (exc , grpc .RpcError ):
121
+ span .set_attribute (
122
+ SpanAttributes .RPC_GRPC_STATUS_CODE , exc .code ().value [0 ]
123
+ )
124
+ span .set_status (
125
+ Status (
126
+ status_code = StatusCode .ERROR ,
127
+ description = "{}: {}" .format (type (exc ).__name__ , exc ),
128
+ )
129
+ )
130
+ span .record_exception (exc )
131
+ span .end ()
132
+ raise exc
133
+ return self ._trace_result (span , rpc_info , result )
153
134
154
135
# For RPCs that stream responses, the result can be a generator. To record
155
136
# the span across the generated responses and detect any errors, we wrap
@@ -162,7 +143,8 @@ def _intercept_server_stream(
162
143
else :
163
144
mutable_metadata = OrderedDict (metadata )
164
145
165
- with self ._start_span (client_info .full_method ) as span :
146
+ span = self ._start_span (client_info .full_method )
147
+ with trace .use_span (span , end_on_exit = True ):
166
148
inject (mutable_metadata , setter = _carrier_setter )
167
149
metadata = tuple (mutable_metadata .items ())
168
150
rpc_info = RpcInfo (
@@ -199,27 +181,34 @@ def intercept_stream(
199
181
else :
200
182
mutable_metadata = OrderedDict (metadata )
201
183
202
- with self ._start_guarded_span (client_info .full_method ) as guarded_span :
203
- inject (mutable_metadata , setter = _carrier_setter )
204
- metadata = tuple (mutable_metadata .items ())
205
- rpc_info = RpcInfo (
206
- full_method = client_info .full_method ,
207
- metadata = metadata ,
208
- timeout = client_info .timeout ,
209
- request = request_or_iterator ,
210
- )
184
+ span = self ._start_span (client_info .full_method )
185
+ with trace .use_span (span , record_exception = False , set_status_on_exception = False ):
186
+ try :
187
+ inject (mutable_metadata , setter = _carrier_setter )
188
+ metadata = tuple (mutable_metadata .items ())
189
+ rpc_info = RpcInfo (
190
+ full_method = client_info .full_method ,
191
+ metadata = metadata ,
192
+ timeout = client_info .timeout ,
193
+ request = request_or_iterator ,
194
+ )
211
195
212
- rpc_info .request = request_or_iterator
196
+ rpc_info .request = request_or_iterator
213
197
214
- try :
215
198
result = invoker (request_or_iterator , metadata )
216
- except grpc .RpcError as err :
217
- guarded_span .generated_span .set_status (
218
- Status (StatusCode .ERROR )
199
+ except Exception as exc :
200
+ if isinstance (exc , grpc .RpcError ):
201
+ span .set_attribute (
202
+ SpanAttributes .RPC_GRPC_STATUS_CODE , exc .code ().value [0 ]
203
+ )
204
+ span .set_status (
205
+ Status (
206
+ status_code = StatusCode .ERROR ,
207
+ description = "{}: {}" .format (type (exc ).__name__ , exc ),
208
+ )
219
209
)
220
- guarded_span .generated_span .set_attribute (
221
- SpanAttributes .RPC_GRPC_STATUS_CODE , err .code ().value [0 ],
222
- )
223
- raise err
210
+ span .record_exception (exc )
211
+ span .end ()
212
+ raise exc
224
213
225
- return self ._trace_result (guarded_span , rpc_info , result )
214
+ return self ._trace_result (span , rpc_info , result )
0 commit comments