corehttp 1.0.0b5__py3-none-any.whl → 1.0.0b7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- corehttp/_version.py +1 -1
- corehttp/credentials.py +66 -25
- corehttp/exceptions.py +7 -6
- corehttp/instrumentation/__init__.py +9 -0
- corehttp/instrumentation/tracing/__init__.py +14 -0
- corehttp/instrumentation/tracing/_decorator.py +189 -0
- corehttp/instrumentation/tracing/_models.py +72 -0
- corehttp/instrumentation/tracing/_tracer.py +69 -0
- corehttp/instrumentation/tracing/opentelemetry.py +277 -0
- corehttp/instrumentation/tracing/utils.py +31 -0
- corehttp/paging.py +13 -0
- corehttp/rest/_aiohttp.py +21 -9
- corehttp/rest/_http_response_impl.py +9 -15
- corehttp/rest/_http_response_impl_async.py +2 -0
- corehttp/rest/_httpx.py +9 -9
- corehttp/rest/_requests_basic.py +17 -10
- corehttp/rest/_rest_py3.py +6 -10
- corehttp/runtime/pipeline/__init__.py +5 -9
- corehttp/runtime/pipeline/_base.py +3 -2
- corehttp/runtime/pipeline/_base_async.py +6 -8
- corehttp/runtime/pipeline/_tools.py +18 -2
- corehttp/runtime/pipeline/_tools_async.py +2 -4
- corehttp/runtime/policies/__init__.py +2 -0
- corehttp/runtime/policies/_authentication.py +76 -24
- corehttp/runtime/policies/_authentication_async.py +66 -21
- corehttp/runtime/policies/_distributed_tracing.py +169 -0
- corehttp/runtime/policies/_retry.py +8 -12
- corehttp/runtime/policies/_retry_async.py +5 -9
- corehttp/runtime/policies/_universal.py +15 -11
- corehttp/serialization.py +237 -3
- corehttp/settings.py +59 -0
- corehttp/transport/_base.py +1 -3
- corehttp/transport/_base_async.py +1 -3
- corehttp/transport/aiohttp/_aiohttp.py +41 -16
- corehttp/transport/requests/_bigger_block_size_http_adapters.py +1 -1
- corehttp/transport/requests/_requests_basic.py +33 -18
- corehttp/utils/_enum_meta.py +1 -1
- corehttp/utils/_utils.py +2 -1
- corehttp-1.0.0b7.dist-info/METADATA +196 -0
- corehttp-1.0.0b7.dist-info/RECORD +61 -0
- {corehttp-1.0.0b5.dist-info → corehttp-1.0.0b7.dist-info}/WHEEL +1 -1
- corehttp-1.0.0b5.dist-info/METADATA +0 -132
- corehttp-1.0.0b5.dist-info/RECORD +0 -52
- {corehttp-1.0.0b5.dist-info → corehttp-1.0.0b7.dist-info/licenses}/LICENSE +0 -0
- {corehttp-1.0.0b5.dist-info → corehttp-1.0.0b7.dist-info}/top_level.txt +0 -0
corehttp/_version.py
CHANGED
corehttp/credentials.py
CHANGED
|
@@ -5,38 +5,74 @@
|
|
|
5
5
|
# -------------------------------------------------------------------------
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
from types import TracebackType
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import NamedTuple, Optional, AsyncContextManager, Type, TypedDict, ContextManager
|
|
9
9
|
from typing_extensions import Protocol, runtime_checkable
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class
|
|
13
|
-
"""
|
|
12
|
+
class AccessTokenInfo:
|
|
13
|
+
"""Information about an OAuth access token.
|
|
14
|
+
|
|
15
|
+
:param str token: The token string.
|
|
16
|
+
:param int expires_on: The token's expiration time in Unix time.
|
|
17
|
+
:keyword str token_type: The type of access token. Defaults to 'Bearer'.
|
|
18
|
+
:keyword int refresh_on: Specifies the time, in Unix time, when the cached token should be proactively
|
|
19
|
+
refreshed. Optional.
|
|
20
|
+
"""
|
|
14
21
|
|
|
15
22
|
token: str
|
|
23
|
+
"""The token string."""
|
|
16
24
|
expires_on: int
|
|
25
|
+
"""The token's expiration time in Unix time."""
|
|
26
|
+
token_type: str
|
|
27
|
+
"""The type of access token."""
|
|
28
|
+
refresh_on: Optional[int]
|
|
29
|
+
"""Specifies the time, in Unix time, when the cached token should be proactively refreshed. Optional."""
|
|
30
|
+
|
|
31
|
+
def __init__(
|
|
32
|
+
self, token: str, expires_on: int, *, token_type: str = "Bearer", refresh_on: Optional[int] = None
|
|
33
|
+
) -> None:
|
|
34
|
+
self.token = token
|
|
35
|
+
self.expires_on = expires_on
|
|
36
|
+
self.token_type = token_type
|
|
37
|
+
self.refresh_on = refresh_on
|
|
17
38
|
|
|
39
|
+
def __repr__(self) -> str:
|
|
40
|
+
return "AccessTokenInfo(token='{}', expires_on={}, token_type='{}', refresh_on={})".format(
|
|
41
|
+
self.token, self.expires_on, self.token_type, self.refresh_on
|
|
42
|
+
)
|
|
18
43
|
|
|
19
|
-
AccessToken.token.__doc__ = """The token string."""
|
|
20
|
-
AccessToken.expires_on.__doc__ = """The token's expiration time in Unix time."""
|
|
21
44
|
|
|
45
|
+
class TokenRequestOptions(TypedDict, total=False):
|
|
46
|
+
"""Options to use for access token requests. All parameters are optional."""
|
|
22
47
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
48
|
+
claims: str
|
|
49
|
+
"""Additional claims required in the token, such as those returned in a resource provider's claims
|
|
50
|
+
challenge following an authorization failure."""
|
|
51
|
+
tenant_id: str
|
|
52
|
+
"""The tenant ID to include in the token request."""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class TokenCredential(Protocol, ContextManager["TokenCredential"]):
|
|
56
|
+
"""Protocol for classes able to provide OAuth access tokens."""
|
|
26
57
|
|
|
27
|
-
def
|
|
58
|
+
def get_token_info(self, *scopes: str, options: Optional[TokenRequestOptions] = None) -> AccessTokenInfo:
|
|
28
59
|
"""Request an access token for `scopes`.
|
|
29
60
|
|
|
30
61
|
:param str scopes: The type of access needed.
|
|
62
|
+
:keyword options: A dictionary of options for the token request. Unknown options will be ignored. Optional.
|
|
63
|
+
:paramtype options: TokenRequestOptions
|
|
31
64
|
|
|
32
|
-
:
|
|
33
|
-
|
|
65
|
+
:rtype: AccessTokenInfo
|
|
66
|
+
:return: An AccessTokenInfo instance containing information about the token.
|
|
67
|
+
"""
|
|
68
|
+
...
|
|
34
69
|
|
|
70
|
+
def close(self) -> None:
|
|
71
|
+
"""Close the credential, releasing any resources it holds.
|
|
35
72
|
|
|
36
|
-
:
|
|
37
|
-
:
|
|
73
|
+
:return: None
|
|
74
|
+
:rtype: None
|
|
38
75
|
"""
|
|
39
|
-
...
|
|
40
76
|
|
|
41
77
|
|
|
42
78
|
class ServiceNamedKey(NamedTuple):
|
|
@@ -47,10 +83,11 @@ class ServiceNamedKey(NamedTuple):
|
|
|
47
83
|
|
|
48
84
|
|
|
49
85
|
__all__ = [
|
|
50
|
-
"
|
|
86
|
+
"AccessTokenInfo",
|
|
51
87
|
"ServiceKeyCredential",
|
|
52
88
|
"ServiceNamedKeyCredential",
|
|
53
89
|
"TokenCredential",
|
|
90
|
+
"TokenRequestOptions",
|
|
54
91
|
"AsyncTokenCredential",
|
|
55
92
|
]
|
|
56
93
|
|
|
@@ -60,7 +97,7 @@ class ServiceKeyCredential:
|
|
|
60
97
|
It provides the ability to update the key without creating a new client.
|
|
61
98
|
|
|
62
99
|
:param str key: The key used to authenticate to a service
|
|
63
|
-
:raises:
|
|
100
|
+
:raises TypeError: If the key is not a string.
|
|
64
101
|
"""
|
|
65
102
|
|
|
66
103
|
def __init__(self, key: str) -> None:
|
|
@@ -84,7 +121,8 @@ class ServiceKeyCredential:
|
|
|
84
121
|
to update long-lived clients.
|
|
85
122
|
|
|
86
123
|
:param str key: The key used to authenticate to a service
|
|
87
|
-
:raises
|
|
124
|
+
:raises ValueError: If the key is None or empty.
|
|
125
|
+
:raises TypeError: If the key is not a string.
|
|
88
126
|
"""
|
|
89
127
|
if not key:
|
|
90
128
|
raise ValueError("The key used for updating can not be None or empty")
|
|
@@ -99,7 +137,7 @@ class ServiceNamedKeyCredential:
|
|
|
99
137
|
|
|
100
138
|
:param str name: The name of the credential used to authenticate to a service.
|
|
101
139
|
:param str key: The key used to authenticate to a service.
|
|
102
|
-
:raises:
|
|
140
|
+
:raises TypeError: If the name or key is not a string.
|
|
103
141
|
"""
|
|
104
142
|
|
|
105
143
|
def __init__(self, name: str, key: str) -> None:
|
|
@@ -134,21 +172,24 @@ class ServiceNamedKeyCredential:
|
|
|
134
172
|
class AsyncTokenCredential(Protocol, AsyncContextManager["AsyncTokenCredential"]):
|
|
135
173
|
"""Protocol for classes able to provide OAuth tokens."""
|
|
136
174
|
|
|
137
|
-
async def
|
|
175
|
+
async def get_token_info(self, *scopes: str, options: Optional[TokenRequestOptions] = None) -> AccessTokenInfo:
|
|
138
176
|
"""Request an access token for `scopes`.
|
|
139
177
|
|
|
140
178
|
:param str scopes: The type of access needed.
|
|
179
|
+
:keyword options: A dictionary of options for the token request. Unknown options will be ignored. Optional.
|
|
180
|
+
:paramtype options: TokenRequestOptions
|
|
141
181
|
|
|
142
|
-
:
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
:rtype: AccessToken
|
|
146
|
-
:return: An AccessToken instance containing the token string and its expiration time in Unix time.
|
|
182
|
+
:rtype: AccessTokenInfo
|
|
183
|
+
:return: An AccessTokenInfo instance containing the token string and its expiration time in Unix time.
|
|
147
184
|
"""
|
|
148
185
|
...
|
|
149
186
|
|
|
150
187
|
async def close(self) -> None:
|
|
151
|
-
|
|
188
|
+
"""Close the credential, releasing any resources.
|
|
189
|
+
|
|
190
|
+
:return: None
|
|
191
|
+
:rtype: None
|
|
192
|
+
"""
|
|
152
193
|
|
|
153
194
|
async def __aexit__(
|
|
154
195
|
self,
|
corehttp/exceptions.py
CHANGED
|
@@ -72,15 +72,12 @@ class _HttpResponseCommonAPI(Protocol):
|
|
|
72
72
|
"""
|
|
73
73
|
|
|
74
74
|
@property
|
|
75
|
-
def reason(self) -> Optional[str]:
|
|
76
|
-
...
|
|
75
|
+
def reason(self) -> Optional[str]: ...
|
|
77
76
|
|
|
78
77
|
@property
|
|
79
|
-
def status_code(self) -> Optional[int]:
|
|
80
|
-
...
|
|
78
|
+
def status_code(self) -> Optional[int]: ...
|
|
81
79
|
|
|
82
|
-
def text(self) -> str:
|
|
83
|
-
...
|
|
80
|
+
def text(self) -> str: ...
|
|
84
81
|
|
|
85
82
|
@property
|
|
86
83
|
def request(self) -> object: # object as type, since all we need is str() on it
|
|
@@ -190,6 +187,8 @@ class HttpResponseError(BaseError):
|
|
|
190
187
|
:vartype status_code: int
|
|
191
188
|
:ivar response: The response that triggered the exception.
|
|
192
189
|
:vartype response: ~corehttp.rest.HttpResponse or ~corehttp.rest.AsyncHttpResponse
|
|
190
|
+
:ivar model: The response body model
|
|
191
|
+
:vartype model: Any
|
|
193
192
|
"""
|
|
194
193
|
|
|
195
194
|
def __init__(
|
|
@@ -203,6 +202,8 @@ class HttpResponseError(BaseError):
|
|
|
203
202
|
self.reason = response.reason
|
|
204
203
|
self.status_code = response.status_code
|
|
205
204
|
|
|
205
|
+
self.model: Optional[Any] = kwargs.pop("model", None)
|
|
206
|
+
|
|
206
207
|
# By priority, message is:
|
|
207
208
|
# - parameter "message", OR
|
|
208
209
|
# - generic message using "reason"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# ------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation.
|
|
3
|
+
# Licensed under the MIT License.
|
|
4
|
+
# ------------------------------------
|
|
5
|
+
from ._models import SpanKind, Link, TracingOptions
|
|
6
|
+
from ._decorator import distributed_trace, distributed_trace_async
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"Link",
|
|
10
|
+
"SpanKind",
|
|
11
|
+
"TracingOptions",
|
|
12
|
+
"distributed_trace",
|
|
13
|
+
"distributed_trace_async",
|
|
14
|
+
]
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# ------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation.
|
|
3
|
+
# Licensed under the MIT License.
|
|
4
|
+
# ------------------------------------
|
|
5
|
+
"""The decorator to apply if you want the given method traced."""
|
|
6
|
+
from contextvars import ContextVar
|
|
7
|
+
import functools
|
|
8
|
+
from typing import Awaitable, Any, TypeVar, overload, Optional, Callable, TYPE_CHECKING
|
|
9
|
+
from typing_extensions import ParamSpec
|
|
10
|
+
|
|
11
|
+
from ._models import SpanKind
|
|
12
|
+
from ._tracer import get_tracer
|
|
13
|
+
from ...settings import settings
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from ._models import TracingOptions
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
P = ParamSpec("P")
|
|
20
|
+
T = TypeVar("T")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# This context variable is used to determine if we are already in the span context of a decorated function.
|
|
24
|
+
_in_span_context = ContextVar("in_span_context", default=False)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@overload
|
|
28
|
+
def distributed_trace(__func: Callable[P, T]) -> Callable[P, T]:
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@overload
|
|
33
|
+
def distributed_trace(**kwargs: Any) -> Callable[[Callable[P, T]], Callable[P, T]]:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def distributed_trace(__func: Optional[Callable[P, T]] = None, **kwargs: Any) -> Any: # pylint: disable=unused-argument
|
|
38
|
+
"""Decorator to apply to an SDK method to have it traced automatically.
|
|
39
|
+
|
|
40
|
+
Span will use the method's qualified name.
|
|
41
|
+
|
|
42
|
+
Note: This decorator SHOULD NOT be used by application developers. It's intended to be called by client
|
|
43
|
+
libraries only. Application developers should use OpenTelemetry directly to instrument their applications.
|
|
44
|
+
|
|
45
|
+
:param callable __func: A function to decorate
|
|
46
|
+
|
|
47
|
+
:return: The decorated function
|
|
48
|
+
:rtype: Any
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def decorator(func: Callable[P, T]) -> Callable[P, T]:
|
|
52
|
+
|
|
53
|
+
@functools.wraps(func)
|
|
54
|
+
def wrapper_use_tracer(*args: Any, **kwargs: Any) -> T:
|
|
55
|
+
# If we are already in the span context of a decorated function, don't trace.
|
|
56
|
+
if _in_span_context.get():
|
|
57
|
+
return func(*args, **kwargs)
|
|
58
|
+
|
|
59
|
+
# This will be popped in the pipeline or transport runner.
|
|
60
|
+
tracing_options: TracingOptions = kwargs.get("tracing_options", {})
|
|
61
|
+
|
|
62
|
+
# User can explicitly disable tracing for this call
|
|
63
|
+
user_enabled = tracing_options.get("enabled")
|
|
64
|
+
if user_enabled is False:
|
|
65
|
+
return func(*args, **kwargs)
|
|
66
|
+
|
|
67
|
+
# If tracing is disabled globally and user didn't explicitly enable it, don't trace.
|
|
68
|
+
if not settings.tracing_enabled and user_enabled is None:
|
|
69
|
+
return func(*args, **kwargs)
|
|
70
|
+
|
|
71
|
+
config = {}
|
|
72
|
+
if args and hasattr(args[0], "_instrumentation_config"):
|
|
73
|
+
config = args[0]._instrumentation_config # pylint: disable=protected-access
|
|
74
|
+
|
|
75
|
+
method_tracer = get_tracer(
|
|
76
|
+
library_name=config.get("library_name"),
|
|
77
|
+
library_version=config.get("library_version"),
|
|
78
|
+
schema_url=config.get("schema_url"),
|
|
79
|
+
attributes=config.get("attributes"),
|
|
80
|
+
)
|
|
81
|
+
if not method_tracer:
|
|
82
|
+
return func(*args, **kwargs)
|
|
83
|
+
|
|
84
|
+
name = func.__qualname__
|
|
85
|
+
span_suppression_token = _in_span_context.set(True)
|
|
86
|
+
try:
|
|
87
|
+
with method_tracer.start_as_current_span(
|
|
88
|
+
name=name,
|
|
89
|
+
kind=SpanKind.INTERNAL,
|
|
90
|
+
attributes=tracing_options.get("attributes"),
|
|
91
|
+
) as span:
|
|
92
|
+
try:
|
|
93
|
+
return func(*args, **kwargs)
|
|
94
|
+
except Exception as err: # pylint: disable=broad-except
|
|
95
|
+
ex_type = type(err)
|
|
96
|
+
module = ex_type.__module__ if ex_type.__module__ != "builtins" else ""
|
|
97
|
+
error_type = f"{module}.{ex_type.__qualname__}" if module else ex_type.__qualname__
|
|
98
|
+
span.set_attribute("error.type", error_type)
|
|
99
|
+
raise
|
|
100
|
+
finally:
|
|
101
|
+
_in_span_context.reset(span_suppression_token)
|
|
102
|
+
|
|
103
|
+
return wrapper_use_tracer
|
|
104
|
+
|
|
105
|
+
return decorator if __func is None else decorator(__func)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@overload
|
|
109
|
+
def distributed_trace_async(__func: Callable[P, Awaitable[T]]) -> Callable[P, Awaitable[T]]:
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@overload
|
|
114
|
+
def distributed_trace_async(**kwargs: Any) -> Callable[[Callable[P, Awaitable[T]]], Callable[P, Awaitable[T]]]:
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def distributed_trace_async( # pylint: disable=unused-argument
|
|
119
|
+
__func: Optional[Callable[P, Awaitable[T]]] = None,
|
|
120
|
+
**kwargs: Any,
|
|
121
|
+
) -> Any:
|
|
122
|
+
"""Decorator to apply to an SDK method to have it traced automatically.
|
|
123
|
+
|
|
124
|
+
Span will use the method's qualified name.
|
|
125
|
+
|
|
126
|
+
Note: This decorator SHOULD NOT be used by application developers. It's intended to be called by client
|
|
127
|
+
libraries only. Application developers should use OpenTelemetry directly to instrument their applications.
|
|
128
|
+
|
|
129
|
+
:param callable __func: A function to decorate
|
|
130
|
+
|
|
131
|
+
:return: The decorated function
|
|
132
|
+
:rtype: Any
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
def decorator(func: Callable[P, Awaitable[T]]) -> Callable[P, Awaitable[T]]:
|
|
136
|
+
|
|
137
|
+
@functools.wraps(func)
|
|
138
|
+
async def wrapper_use_tracer(*args: Any, **kwargs: Any) -> T:
|
|
139
|
+
# If we are already in the span context of a decorated function, don't trace.
|
|
140
|
+
if _in_span_context.get():
|
|
141
|
+
return await func(*args, **kwargs)
|
|
142
|
+
|
|
143
|
+
# This will be popped in the pipeline or transport runner.
|
|
144
|
+
tracing_options: TracingOptions = kwargs.get("tracing_options", {})
|
|
145
|
+
|
|
146
|
+
# User can explicitly disable tracing for this call
|
|
147
|
+
user_enabled = tracing_options.get("enabled")
|
|
148
|
+
if user_enabled is False:
|
|
149
|
+
return await func(*args, **kwargs)
|
|
150
|
+
|
|
151
|
+
# If tracing is disabled globally and user didn't explicitly enable it, don't trace.
|
|
152
|
+
if not settings.tracing_enabled and user_enabled is None:
|
|
153
|
+
return await func(*args, **kwargs)
|
|
154
|
+
|
|
155
|
+
config = {}
|
|
156
|
+
if args and hasattr(args[0], "_instrumentation_config"):
|
|
157
|
+
config = args[0]._instrumentation_config # pylint: disable=protected-access
|
|
158
|
+
|
|
159
|
+
method_tracer = get_tracer(
|
|
160
|
+
library_name=config.get("library_name"),
|
|
161
|
+
library_version=config.get("library_version"),
|
|
162
|
+
schema_url=config.get("schema_url"),
|
|
163
|
+
attributes=config.get("attributes"),
|
|
164
|
+
)
|
|
165
|
+
if not method_tracer:
|
|
166
|
+
return await func(*args, **kwargs)
|
|
167
|
+
|
|
168
|
+
name = func.__qualname__
|
|
169
|
+
span_suppression_token = _in_span_context.set(True)
|
|
170
|
+
try:
|
|
171
|
+
with method_tracer.start_as_current_span(
|
|
172
|
+
name=name,
|
|
173
|
+
kind=SpanKind.INTERNAL,
|
|
174
|
+
attributes=tracing_options.get("attributes"),
|
|
175
|
+
) as span:
|
|
176
|
+
try:
|
|
177
|
+
return await func(*args, **kwargs)
|
|
178
|
+
except Exception as err: # pylint: disable=broad-except
|
|
179
|
+
ex_type = type(err)
|
|
180
|
+
module = ex_type.__module__ if ex_type.__module__ != "builtins" else ""
|
|
181
|
+
error_type = f"{module}.{ex_type.__qualname__}" if module else ex_type.__qualname__
|
|
182
|
+
span.set_attribute("error.type", error_type)
|
|
183
|
+
raise
|
|
184
|
+
finally:
|
|
185
|
+
_in_span_context.reset(span_suppression_token)
|
|
186
|
+
|
|
187
|
+
return wrapper_use_tracer
|
|
188
|
+
|
|
189
|
+
return decorator if __func is None else decorator(__func)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# ------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation.
|
|
3
|
+
# Licensed under the MIT License.
|
|
4
|
+
# ------------------------------------
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Dict, Mapping, Optional, Union, Sequence, TypedDict
|
|
8
|
+
|
|
9
|
+
from ...utils import CaseInsensitiveEnumMeta
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
AttributeValue = Union[
|
|
13
|
+
str,
|
|
14
|
+
bool,
|
|
15
|
+
int,
|
|
16
|
+
float,
|
|
17
|
+
Sequence[str],
|
|
18
|
+
Sequence[bool],
|
|
19
|
+
Sequence[int],
|
|
20
|
+
Sequence[float],
|
|
21
|
+
]
|
|
22
|
+
Attributes = Mapping[str, AttributeValue]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SpanKind(Enum, metaclass=CaseInsensitiveEnumMeta):
|
|
26
|
+
"""Describes the role or kind of a span within a distributed trace.
|
|
27
|
+
|
|
28
|
+
This helps to categorize spans based on their relationship to other spans and the type
|
|
29
|
+
of operation they represent.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
UNSPECIFIED = 1
|
|
33
|
+
"""Unspecified span kind."""
|
|
34
|
+
|
|
35
|
+
SERVER = 2
|
|
36
|
+
"""Indicates that the span describes an operation that handles a remote request."""
|
|
37
|
+
|
|
38
|
+
CLIENT = 3
|
|
39
|
+
"""Indicates that the span describes a request to some remote service."""
|
|
40
|
+
|
|
41
|
+
PRODUCER = 4
|
|
42
|
+
"""Indicates that the span describes the initiation or scheduling of a local or remote operation."""
|
|
43
|
+
|
|
44
|
+
CONSUMER = 5
|
|
45
|
+
"""Indicates that the span represents the processing of an operation initiated by a producer."""
|
|
46
|
+
|
|
47
|
+
INTERNAL = 6
|
|
48
|
+
"""Indicates that the span is used internally in the application."""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Link:
|
|
52
|
+
"""Represents a reference from one span to another span.
|
|
53
|
+
|
|
54
|
+
:param headers: A dictionary of the request header as key value pairs.
|
|
55
|
+
:type headers: dict
|
|
56
|
+
:param attributes: Any additional attributes that should be added to link
|
|
57
|
+
:type attributes: dict
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
def __init__(self, headers: Dict[str, str], attributes: Optional[Attributes] = None) -> None:
|
|
61
|
+
self.headers = headers
|
|
62
|
+
self.attributes = attributes
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class TracingOptions(TypedDict, total=False):
|
|
66
|
+
"""Options to configure tracing behavior for operations."""
|
|
67
|
+
|
|
68
|
+
enabled: bool
|
|
69
|
+
"""Whether tracing is enabled for the operation. By default, if the global setting is enabled, tracing is
|
|
70
|
+
enabled for all operations. This option can be used to override the global setting for a specific operation."""
|
|
71
|
+
attributes: Attributes
|
|
72
|
+
"""Attributes to include in the spans emitted for the operation."""
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# ------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation.
|
|
3
|
+
# Licensed under the MIT License.
|
|
4
|
+
# ------------------------------------
|
|
5
|
+
from typing import Optional, Union, Mapping, TYPE_CHECKING
|
|
6
|
+
from functools import lru_cache
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
try:
|
|
10
|
+
from .opentelemetry import OpenTelemetryTracer
|
|
11
|
+
except ImportError:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _get_tracer_impl():
|
|
16
|
+
# Check if OpenTelemetry is available/installed.
|
|
17
|
+
try:
|
|
18
|
+
from .opentelemetry import OpenTelemetryTracer
|
|
19
|
+
|
|
20
|
+
return OpenTelemetryTracer
|
|
21
|
+
except ImportError:
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@lru_cache
|
|
26
|
+
def _get_tracer_cached(
|
|
27
|
+
library_name: Optional[str],
|
|
28
|
+
library_version: Optional[str],
|
|
29
|
+
schema_url: Optional[str],
|
|
30
|
+
attributes_key: Optional[frozenset],
|
|
31
|
+
) -> Optional["OpenTelemetryTracer"]:
|
|
32
|
+
tracer_impl = _get_tracer_impl()
|
|
33
|
+
if tracer_impl:
|
|
34
|
+
# Convert attributes_key back to dict if needed
|
|
35
|
+
attributes = dict(attributes_key) if attributes_key else None
|
|
36
|
+
return tracer_impl(
|
|
37
|
+
library_name=library_name,
|
|
38
|
+
library_version=library_version,
|
|
39
|
+
schema_url=schema_url,
|
|
40
|
+
attributes=attributes,
|
|
41
|
+
)
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_tracer(
|
|
46
|
+
*,
|
|
47
|
+
library_name: Optional[str] = None,
|
|
48
|
+
library_version: Optional[str] = None,
|
|
49
|
+
schema_url: Optional[str] = None,
|
|
50
|
+
attributes: Optional[Mapping[str, Union[str, bool, int, float]]] = None,
|
|
51
|
+
) -> Optional["OpenTelemetryTracer"]:
|
|
52
|
+
"""Get the OpenTelemetry tracer instance if available.
|
|
53
|
+
|
|
54
|
+
If OpenTelemetry is not available, this method will return None. This method caches
|
|
55
|
+
the tracer instance for each unique set of parameters.
|
|
56
|
+
|
|
57
|
+
:keyword library_name: The name of the library to use in the tracer.
|
|
58
|
+
:paramtype library_name: str
|
|
59
|
+
:keyword library_version: The version of the library to use in the tracer.
|
|
60
|
+
:paramtype library_version: str
|
|
61
|
+
:keyword schema_url: Specifies the Schema URL of the emitted spans.
|
|
62
|
+
:paramtype schema_url: str
|
|
63
|
+
:keyword attributes: Attributes to add to the emitted spans.
|
|
64
|
+
:paramtype attributes: Mapping[str, Union[str, bool, int, float]]
|
|
65
|
+
:return: The OpenTelemetry tracer instance if available.
|
|
66
|
+
:rtype: Optional[~corehttp.instrumentation.tracing.opentelemetry.OpenTelemetryTracer]
|
|
67
|
+
"""
|
|
68
|
+
attributes_key = frozenset(attributes.items()) if attributes else None
|
|
69
|
+
return _get_tracer_cached(library_name, library_version, schema_url, attributes_key)
|