corehttp 1.0.0b6__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.
Files changed (40) hide show
  1. corehttp/_version.py +1 -1
  2. corehttp/credentials.py +14 -5
  3. corehttp/instrumentation/__init__.py +9 -0
  4. corehttp/instrumentation/tracing/__init__.py +14 -0
  5. corehttp/instrumentation/tracing/_decorator.py +189 -0
  6. corehttp/instrumentation/tracing/_models.py +72 -0
  7. corehttp/instrumentation/tracing/_tracer.py +69 -0
  8. corehttp/instrumentation/tracing/opentelemetry.py +277 -0
  9. corehttp/instrumentation/tracing/utils.py +31 -0
  10. corehttp/paging.py +13 -0
  11. corehttp/rest/_aiohttp.py +17 -5
  12. corehttp/rest/_http_response_impl.py +7 -7
  13. corehttp/rest/_http_response_impl_async.py +2 -0
  14. corehttp/rest/_httpx.py +8 -8
  15. corehttp/rest/_requests_basic.py +13 -5
  16. corehttp/rest/_rest_py3.py +2 -2
  17. corehttp/runtime/pipeline/__init__.py +2 -2
  18. corehttp/runtime/pipeline/_base.py +2 -1
  19. corehttp/runtime/pipeline/_base_async.py +2 -0
  20. corehttp/runtime/pipeline/_tools.py +18 -2
  21. corehttp/runtime/policies/__init__.py +2 -0
  22. corehttp/runtime/policies/_authentication.py +28 -5
  23. corehttp/runtime/policies/_authentication_async.py +22 -3
  24. corehttp/runtime/policies/_distributed_tracing.py +169 -0
  25. corehttp/runtime/policies/_retry.py +7 -11
  26. corehttp/runtime/policies/_retry_async.py +4 -8
  27. corehttp/runtime/policies/_universal.py +11 -0
  28. corehttp/serialization.py +236 -2
  29. corehttp/settings.py +59 -0
  30. corehttp/transport/_base.py +1 -3
  31. corehttp/transport/_base_async.py +1 -3
  32. corehttp/transport/aiohttp/_aiohttp.py +39 -14
  33. corehttp/transport/requests/_requests_basic.py +31 -16
  34. corehttp/utils/_utils.py +2 -1
  35. {corehttp-1.0.0b6.dist-info → corehttp-1.0.0b7.dist-info}/METADATA +52 -6
  36. corehttp-1.0.0b7.dist-info/RECORD +61 -0
  37. {corehttp-1.0.0b6.dist-info → corehttp-1.0.0b7.dist-info}/WHEEL +1 -1
  38. corehttp-1.0.0b6.dist-info/RECORD +0 -52
  39. {corehttp-1.0.0b6.dist-info → corehttp-1.0.0b7.dist-info/licenses}/LICENSE +0 -0
  40. {corehttp-1.0.0b6.dist-info → corehttp-1.0.0b7.dist-info}/top_level.txt +0 -0
corehttp/_version.py CHANGED
@@ -9,4 +9,4 @@
9
9
  # regenerated.
10
10
  # --------------------------------------------------------------------------
11
11
 
12
- VERSION = "1.0.0b6"
12
+ VERSION = "1.0.0b7"
corehttp/credentials.py CHANGED
@@ -68,7 +68,11 @@ class TokenCredential(Protocol, ContextManager["TokenCredential"]):
68
68
  ...
69
69
 
70
70
  def close(self) -> None:
71
- pass
71
+ """Close the credential, releasing any resources it holds.
72
+
73
+ :return: None
74
+ :rtype: None
75
+ """
72
76
 
73
77
 
74
78
  class ServiceNamedKey(NamedTuple):
@@ -93,7 +97,7 @@ class ServiceKeyCredential:
93
97
  It provides the ability to update the key without creating a new client.
94
98
 
95
99
  :param str key: The key used to authenticate to a service
96
- :raises: TypeError
100
+ :raises TypeError: If the key is not a string.
97
101
  """
98
102
 
99
103
  def __init__(self, key: str) -> None:
@@ -117,7 +121,8 @@ class ServiceKeyCredential:
117
121
  to update long-lived clients.
118
122
 
119
123
  :param str key: The key used to authenticate to a service
120
- :raises: ValueError or TypeError
124
+ :raises ValueError: If the key is None or empty.
125
+ :raises TypeError: If the key is not a string.
121
126
  """
122
127
  if not key:
123
128
  raise ValueError("The key used for updating can not be None or empty")
@@ -132,7 +137,7 @@ class ServiceNamedKeyCredential:
132
137
 
133
138
  :param str name: The name of the credential used to authenticate to a service.
134
139
  :param str key: The key used to authenticate to a service.
135
- :raises: TypeError
140
+ :raises TypeError: If the name or key is not a string.
136
141
  """
137
142
 
138
143
  def __init__(self, name: str, key: str) -> None:
@@ -180,7 +185,11 @@ class AsyncTokenCredential(Protocol, AsyncContextManager["AsyncTokenCredential"]
180
185
  ...
181
186
 
182
187
  async def close(self) -> None:
183
- pass
188
+ """Close the credential, releasing any resources.
189
+
190
+ :return: None
191
+ :rtype: None
192
+ """
184
193
 
185
194
  async def __aexit__(
186
195
  self,
@@ -0,0 +1,9 @@
1
+ # ------------------------------------
2
+ # Copyright (c) Microsoft Corporation.
3
+ # Licensed under the MIT License.
4
+ # ------------------------------------
5
+ from .tracing._tracer import get_tracer
6
+
7
+ __all__ = [
8
+ "get_tracer",
9
+ ]
@@ -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)
@@ -0,0 +1,277 @@
1
+ # ------------------------------------
2
+ # Copyright (c) Microsoft Corporation.
3
+ # Licensed under the MIT License.
4
+ # ------------------------------------
5
+ from __future__ import annotations
6
+ from contextlib import contextmanager
7
+ from contextvars import Token
8
+ from typing import Any, Optional, Dict, Sequence, cast, Callable, Iterator, TYPE_CHECKING
9
+
10
+ from opentelemetry import context as otel_context_module, trace
11
+ from opentelemetry.trace import (
12
+ Span,
13
+ SpanKind as OpenTelemetrySpanKind,
14
+ Link as OpenTelemetryLink,
15
+ StatusCode,
16
+ )
17
+ from opentelemetry.trace.propagation import get_current_span as get_current_span_otel
18
+ from opentelemetry.propagate import extract, inject
19
+
20
+ try:
21
+ from opentelemetry.context import _SUPPRESS_HTTP_INSTRUMENTATION_KEY # type: ignore[attr-defined]
22
+ except ImportError:
23
+ _SUPPRESS_HTTP_INSTRUMENTATION_KEY = "suppress_http_instrumentation"
24
+
25
+ from ..._version import VERSION
26
+ from ._models import (
27
+ Attributes,
28
+ SpanKind as _SpanKind,
29
+ Link as _Link,
30
+ )
31
+
32
+ if TYPE_CHECKING:
33
+ from corehttp.instrumentation.tracing import Link, SpanKind
34
+
35
+
36
+ _DEFAULT_SCHEMA_URL = "https://opentelemetry.io/schemas/1.23.1"
37
+ _DEFAULT_MODULE_NAME = "corehttp"
38
+
39
+ _KIND_MAPPINGS = {
40
+ _SpanKind.CLIENT: OpenTelemetrySpanKind.CLIENT,
41
+ _SpanKind.CONSUMER: OpenTelemetrySpanKind.CONSUMER,
42
+ _SpanKind.PRODUCER: OpenTelemetrySpanKind.PRODUCER,
43
+ _SpanKind.SERVER: OpenTelemetrySpanKind.SERVER,
44
+ _SpanKind.INTERNAL: OpenTelemetrySpanKind.INTERNAL,
45
+ _SpanKind.UNSPECIFIED: OpenTelemetrySpanKind.INTERNAL,
46
+ }
47
+
48
+
49
+ class OpenTelemetryTracer:
50
+ """A tracer that uses OpenTelemetry to trace operations.
51
+
52
+ :keyword library_name: The name of the library to use in the tracer.
53
+ :paramtype library_name: str
54
+ :keyword library_version: The version of the library to use in the tracer.
55
+ :paramtype library_version: str
56
+ :keyword schema_url: Specifies the Schema URL of the emitted spans. Defaults to
57
+ "https://opentelemetry.io/schemas/1.23.1".
58
+ :paramtype schema_url: str
59
+ :keyword attributes: Attributes to add to the emitted spans.
60
+ """
61
+
62
+ def __init__(
63
+ self,
64
+ *,
65
+ library_name: Optional[str] = None,
66
+ library_version: Optional[str] = None,
67
+ schema_url: Optional[str] = None,
68
+ attributes: Optional[Attributes] = None,
69
+ ) -> None:
70
+ self._tracer = trace.get_tracer(
71
+ instrumenting_module_name=library_name or _DEFAULT_MODULE_NAME,
72
+ instrumenting_library_version=library_version or VERSION,
73
+ schema_url=schema_url or _DEFAULT_SCHEMA_URL,
74
+ attributes=attributes,
75
+ )
76
+
77
+ def start_span(
78
+ self,
79
+ name: str,
80
+ *,
81
+ kind: SpanKind = _SpanKind.INTERNAL,
82
+ attributes: Optional[Attributes] = None,
83
+ links: Optional[Sequence[Link]] = None,
84
+ start_time: Optional[int] = None,
85
+ context: Optional[Dict[str, Any]] = None,
86
+ ) -> Span:
87
+ """Starts a span without setting it as the current span in the context.
88
+
89
+ :param name: The name of the span
90
+ :type name: str
91
+ :keyword kind: The kind of the span. INTERNAL by default.
92
+ :paramtype kind: ~corehttp.instrumentation.tracing.SpanKind
93
+ :keyword attributes: Attributes to add to the span.
94
+ :paramtype attributes: Mapping[str, AttributeValue]
95
+ :keyword links: Links to add to the span.
96
+ :paramtype links: list[~corehttp.instrumentation.tracing.Link]
97
+ :keyword start_time: The start time of the span in nanoseconds since the epoch.
98
+ :paramtype start_time: Optional[int]
99
+ :keyword context: A dictionary of context values corresponding to the parent span. If not provided,
100
+ the current global context will be used.
101
+ :paramtype context: Optional[Dict[str, any]]
102
+ :return: The span that was started
103
+ :rtype: ~opentelemetry.trace.Span
104
+ """
105
+ otel_kind = _KIND_MAPPINGS.get(kind, OpenTelemetrySpanKind.INTERNAL)
106
+ otel_links = self._parse_links(links)
107
+
108
+ otel_context = None
109
+ if context:
110
+ otel_context = extract(context)
111
+
112
+ otel_span = self._tracer.start_span(
113
+ name,
114
+ context=otel_context,
115
+ kind=otel_kind,
116
+ attributes=attributes,
117
+ links=otel_links,
118
+ start_time=start_time,
119
+ record_exception=False,
120
+ )
121
+
122
+ return otel_span
123
+
124
+ @contextmanager
125
+ def start_as_current_span(
126
+ self,
127
+ name: str,
128
+ *,
129
+ kind: SpanKind = _SpanKind.INTERNAL,
130
+ attributes: Optional[Attributes] = None,
131
+ links: Optional[Sequence[Link]] = None,
132
+ start_time: Optional[int] = None,
133
+ context: Optional[Dict[str, Any]] = None,
134
+ end_on_exit: bool = True,
135
+ ) -> Iterator[Span]:
136
+ """Context manager that starts a span and sets it as the current span in the context.
137
+
138
+ .. code:: python
139
+
140
+ with tracer.start_as_current_span("span_name") as span:
141
+ # Do something with the span
142
+ span.set_attribute("key", "value")
143
+
144
+ :param name: The name of the span
145
+ :type name: str
146
+ :keyword kind: The kind of the span. INTERNAL by default.
147
+ :paramtype kind: ~corehttp.instrumentation.tracing.SpanKind
148
+ :keyword attributes: Attributes to add to the span.
149
+ :paramtype attributes: Optional[Attributes]
150
+ :keyword links: Links to add to the span.
151
+ :paramtype links: Optional[Sequence[Link]]
152
+ :keyword start_time: The start time of the span in nanoseconds since the epoch.
153
+ :paramtype start_time: Optional[int]
154
+ :keyword context: A dictionary of context values corresponding to the parent span. If not provided,
155
+ the current global context will be used.
156
+ :paramtype context: Optional[Dict[str, any]]
157
+ :keyword end_on_exit: Whether to end the span when exiting the context manager. Defaults to True.
158
+ :paramtype end_on_exit: bool
159
+ :return: The span that was started
160
+ :rtype: Iterator[~opentelemetry.trace.Span]
161
+ """
162
+ span = self.start_span(
163
+ name, kind=kind, attributes=attributes, links=links, start_time=start_time, context=context
164
+ )
165
+ with trace.use_span( # pylint: disable=not-context-manager
166
+ span, record_exception=False, end_on_exit=end_on_exit
167
+ ) as span:
168
+ yield span
169
+
170
+ @classmethod
171
+ @contextmanager
172
+ def use_span(cls, span: Span, *, end_on_exit: bool = True) -> Iterator[Span]:
173
+ """Context manager that takes a non-active span and activates it in the current context.
174
+
175
+ :param span: The span to set as the current span
176
+ :type span: ~opentelemetry.trace.Span
177
+ :keyword end_on_exit: Whether to end the span when exiting the context manager. Defaults to True.
178
+ :paramtype end_on_exit: bool
179
+ :return: The span that was activated.
180
+ :rtype: Iterator[~opentelemetry.trace.Span]
181
+ """
182
+ with trace.use_span( # pylint: disable=not-context-manager
183
+ span, record_exception=False, end_on_exit=end_on_exit
184
+ ) as active_span:
185
+ yield active_span
186
+
187
+ @staticmethod
188
+ def set_span_error_status(span: Span, description: Optional[str] = None) -> None:
189
+ """Set the status of a span to ERROR with the provided description, if any.
190
+
191
+ :param span: The span to set the ERROR status on.
192
+ :type span: ~opentelemetry.trace.Span
193
+ :param description: An optional description of the error.
194
+ :type description: str
195
+ """
196
+ span.set_status(StatusCode.ERROR, description=description)
197
+
198
+ def _parse_links(self, links: Optional[Sequence[Link]]) -> Optional[Sequence[OpenTelemetryLink]]:
199
+ if not links:
200
+ return None
201
+
202
+ try:
203
+ otel_links = []
204
+ for link in links:
205
+ ctx = extract(link.headers)
206
+ span_ctx = get_current_span_otel(ctx).get_span_context()
207
+ otel_links.append(OpenTelemetryLink(span_ctx, link.attributes))
208
+ return otel_links
209
+ except AttributeError:
210
+ # We will just send the links as is if it's not ~corehttp.instrumentation.tracing.Link without
211
+ # any validation assuming the user knows what they are doing.
212
+ return cast(Sequence[OpenTelemetryLink], links)
213
+
214
+ @classmethod
215
+ def get_current_span(cls) -> Span:
216
+ """Returns the current span in the context.
217
+
218
+ :return: The current span
219
+ :rtype: ~opentelemetry.trace.Span
220
+ """
221
+ return get_current_span_otel()
222
+
223
+ @classmethod
224
+ def with_current_context(cls, func: Callable) -> Callable:
225
+ """Passes the current spans to the new context the function will be run in.
226
+
227
+ :param func: The function that will be run in the new context
228
+ :type func: callable
229
+ :return: The wrapped function
230
+ :rtype: callable
231
+ """
232
+ current_context = otel_context_module.get_current()
233
+
234
+ def call_with_current_context(*args, **kwargs):
235
+ token = None
236
+ try:
237
+ token = otel_context_module.attach(current_context)
238
+ return func(*args, **kwargs)
239
+ finally:
240
+ if token is not None:
241
+ otel_context_module.detach(token)
242
+
243
+ return call_with_current_context
244
+
245
+ @classmethod
246
+ def get_trace_context(cls) -> Dict[str, str]:
247
+ """Returns the Trace Context header values associated with the current span.
248
+
249
+ These are generally the W3C Trace Context headers (i.e. "traceparent" and "tracestate").
250
+ :return: A key value pair dictionary
251
+ :rtype: dict[str, str]
252
+ """
253
+ trace_context: Dict[str, str] = {}
254
+ inject(trace_context)
255
+ return trace_context
256
+
257
+ @classmethod
258
+ def _suppress_auto_http_instrumentation(cls) -> Token:
259
+ """Enabled automatic HTTP instrumentation suppression.
260
+
261
+ Since corehttp already instruments HTTP calls, we need to suppress any automatic HTTP
262
+ instrumentation provided by other libraries to prevent duplicate spans. This has no effect if no
263
+ automatic HTTP instrumentation libraries are being used.
264
+
265
+ :return: A token that can be used to detach the suppression key from the context
266
+ :rtype: ~contextvars.Token
267
+ """
268
+ return otel_context_module.attach(otel_context_module.set_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY, True))
269
+
270
+ @classmethod
271
+ def _detach_from_context(cls, token: Token) -> None:
272
+ """Detach a token from the context.
273
+
274
+ :param token: The token to detach
275
+ :type token: ~contextvars.Token
276
+ """
277
+ otel_context_module.detach(token)