3
3
# Licensed under the MIT License.
4
4
# ------------------------------------
5
5
"""Protocol that defines what functions wrappers of tracing libraries should implement."""
6
+ from __future__ import annotations
6
7
from enum import Enum
7
8
from urllib .parse import urlparse
8
9
9
- from typing import (
10
- TYPE_CHECKING ,
11
- Any ,
12
- Sequence ,
13
- Optional ,
14
- Union ,
15
- Callable ,
16
- ContextManager ,
17
- Dict ,
18
- )
10
+ from typing import Any , Sequence , Optional , Union , Callable , Dict , Type
11
+ from types import TracebackType
12
+ from typing_extensions import Protocol , ContextManager
19
13
from azure .core .pipeline .transport import HttpRequest , HttpResponse , AsyncHttpResponse
20
14
from azure .core .rest import (
21
15
HttpResponse as RestHttpResponse ,
26
20
HttpResponseType = Union [HttpResponse , AsyncHttpResponse , RestHttpResponse , AsyncRestHttpResponse ]
27
21
HttpRequestType = Union [HttpRequest , RestHttpRequest ]
28
22
29
- if TYPE_CHECKING :
30
- AttributeValue = Union [
31
- str ,
32
- bool ,
33
- int ,
34
- float ,
35
- Sequence [str ],
36
- Sequence [bool ],
37
- Sequence [int ],
38
- Sequence [float ],
39
- ]
40
- Attributes = Optional [Dict [str , AttributeValue ]]
41
-
42
- try :
43
- from typing_extensions import Protocol
44
- except ImportError :
45
- Protocol = object # type: ignore
23
+ AttributeValue = Union [
24
+ str ,
25
+ bool ,
26
+ int ,
27
+ float ,
28
+ Sequence [str ],
29
+ Sequence [bool ],
30
+ Sequence [int ],
31
+ Sequence [float ],
32
+ ]
33
+ Attributes = Dict [str , AttributeValue ]
46
34
47
35
48
36
class SpanKind (Enum ):
@@ -67,11 +55,11 @@ class AbstractSpan(Protocol):
67
55
"""
68
56
69
57
def __init__ ( # pylint: disable=super-init-not-called
70
- self , span : Optional [Any ] = None , name : Optional [str ] = None , ** kwargs
58
+ self , span : Optional [Any ] = None , name : Optional [str ] = None , ** kwargs : Any
71
59
) -> None :
72
60
pass
73
61
74
- def span (self , name : str = "child_span" , ** kwargs ) -> " AbstractSpan" :
62
+ def span (self , name : str = "child_span" , ** kwargs : Any ) -> AbstractSpan :
75
63
"""
76
64
Create a child span for the current span and append it to the child spans list.
77
65
The child span must be wrapped by an implementation of AbstractSpan
@@ -98,10 +86,15 @@ def kind(self, value: SpanKind) -> None:
98
86
:type value: SpanKind
99
87
"""
100
88
101
- def __enter__ (self ):
89
+ def __enter__ (self ) -> AbstractSpan :
102
90
"""Start a span."""
103
91
104
- def __exit__ (self , exception_type , exception_value , traceback ):
92
+ def __exit__ (
93
+ self ,
94
+ exception_type : Optional [Type [BaseException ]],
95
+ exception_value : Optional [BaseException ],
96
+ traceback : TracebackType ,
97
+ ) -> None :
105
98
"""Finish a span.
106
99
107
100
:param exception_type: The type of the exception
@@ -159,7 +152,7 @@ def span_instance(self) -> Any:
159
152
"""
160
153
161
154
@classmethod
162
- def link (cls , traceparent : str , attributes : Optional [" Attributes" ] = None ) -> None :
155
+ def link (cls , traceparent : str , attributes : Optional [Attributes ] = None ) -> None :
163
156
"""
164
157
Given a traceparent, extracts the context and links the context to the current tracer.
165
158
@@ -170,7 +163,7 @@ def link(cls, traceparent: str, attributes: Optional["Attributes"] = None) -> No
170
163
"""
171
164
172
165
@classmethod
173
- def link_from_headers (cls , headers : Dict [str , str ], attributes : Optional [" Attributes" ] = None ) -> None :
166
+ def link_from_headers (cls , headers : Dict [str , str ], attributes : Optional [Attributes ] = None ) -> None :
174
167
"""
175
168
Given a dictionary, extracts the context and links the context to the current tracer.
176
169
@@ -215,7 +208,7 @@ def set_current_tracer(cls, tracer: Any) -> None:
215
208
"""
216
209
217
210
@classmethod
218
- def change_context (cls , span : " AbstractSpan" ) -> ContextManager :
211
+ def change_context (cls , span : AbstractSpan ) -> ContextManager [ AbstractSpan ] :
219
212
"""Change the context for the life of this context manager.
220
213
221
214
:param span: The span to run in the new context
@@ -235,14 +228,7 @@ def with_current_context(cls, func: Callable) -> Callable:
235
228
"""
236
229
237
230
238
- # https://github.com/python/mypy/issues/5837
239
- if TYPE_CHECKING :
240
- _MIXIN_BASE = AbstractSpan
241
- else :
242
- _MIXIN_BASE = object
243
-
244
-
245
- class HttpSpanMixin (_MIXIN_BASE ):
231
+ class HttpSpanMixin :
246
232
"""Can be used to get HTTP span attributes settings for free."""
247
233
248
234
_SPAN_COMPONENT = "component"
@@ -253,7 +239,9 @@ class HttpSpanMixin(_MIXIN_BASE):
253
239
_NET_PEER_NAME = "net.peer.name"
254
240
_NET_PEER_PORT = "net.peer.port"
255
241
256
- def set_http_attributes (self , request : HttpRequestType , response : Optional [HttpResponseType ] = None ) -> None :
242
+ def set_http_attributes (
243
+ self : AbstractSpan , request : HttpRequestType , response : Optional [HttpResponseType ] = None
244
+ ) -> None :
257
245
"""
258
246
Add correct attributes for a http client span.
259
247
@@ -262,24 +250,25 @@ def set_http_attributes(self, request: HttpRequestType, response: Optional[HttpR
262
250
:param response: The response received from the server. Is None if no response received.
263
251
:type response: ~azure.core.pipeline.transport.HttpResponse or ~azure.core.pipeline.transport.AsyncHttpResponse
264
252
"""
253
+ # Also see https://github.com/python/mypy/issues/5837
265
254
self .kind = SpanKind .CLIENT
266
- self .add_attribute (self ._SPAN_COMPONENT , "http" )
267
- self .add_attribute (self ._HTTP_METHOD , request .method )
268
- self .add_attribute (self ._HTTP_URL , request .url )
255
+ self .add_attribute (HttpSpanMixin ._SPAN_COMPONENT , "http" )
256
+ self .add_attribute (HttpSpanMixin ._HTTP_METHOD , request .method )
257
+ self .add_attribute (HttpSpanMixin ._HTTP_URL , request .url )
269
258
270
259
parsed_url = urlparse (request .url )
271
260
if parsed_url .hostname :
272
- self .add_attribute (self ._NET_PEER_NAME , parsed_url .hostname )
261
+ self .add_attribute (HttpSpanMixin ._NET_PEER_NAME , parsed_url .hostname )
273
262
if parsed_url .port and parsed_url .port not in [80 , 443 ]:
274
- self .add_attribute (self ._NET_PEER_PORT , parsed_url .port )
263
+ self .add_attribute (HttpSpanMixin ._NET_PEER_PORT , parsed_url .port )
275
264
276
265
user_agent = request .headers .get ("User-Agent" )
277
266
if user_agent :
278
- self .add_attribute (self ._HTTP_USER_AGENT , user_agent )
267
+ self .add_attribute (HttpSpanMixin ._HTTP_USER_AGENT , user_agent )
279
268
if response and response .status_code :
280
- self .add_attribute (self ._HTTP_STATUS_CODE , response .status_code )
269
+ self .add_attribute (HttpSpanMixin ._HTTP_STATUS_CODE , response .status_code )
281
270
else :
282
- self .add_attribute (self ._HTTP_STATUS_CODE , 504 )
271
+ self .add_attribute (HttpSpanMixin ._HTTP_STATUS_CODE , 504 )
283
272
284
273
285
274
class Link :
@@ -291,6 +280,6 @@ class Link:
291
280
:type attributes: dict
292
281
"""
293
282
294
- def __init__ (self , headers : Dict [str , str ], attributes : Optional [" Attributes" ] = None ) -> None :
283
+ def __init__ (self , headers : Dict [str , str ], attributes : Optional [Attributes ] = None ) -> None :
295
284
self .headers = headers
296
285
self .attributes = attributes
0 commit comments