From 69f667154075230843c0f82cc65dabc93c1555e8 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Sun, 26 Jan 2020 15:42:52 -0800 Subject: [PATCH] Rename DistributedContext to CorrelationContext This code will rely on the Context Propagation work to be fully implemented, but breaking the work into separate PRs to make the review process a bit easier. Signed-off-by: Alex Boten --- .../src/opentelemetry/context/__init__.py | 19 +++ .../correlationcontext/__init__.py | 128 ++++++++++++++++++ .../distributedcontext/__init__.py | 125 ----------------- .../propagation/__init__.py | 18 --- .../propagation/binaryformat.py | 62 --------- .../propagation/httptextformat.py | 114 ---------------- .../test_correlation_context.py | 66 +++++++++ .../test_distributed_context.py | 112 --------------- .../sdk/distributedcontext/__init__.py | 66 --------- .../propagation/__init__.py | 0 .../tests/distributedcontext/__init__.py | 13 -- .../test_distributed_context.py | 42 ------ 12 files changed, 213 insertions(+), 552 deletions(-) create mode 100644 opentelemetry-api/src/opentelemetry/correlationcontext/__init__.py delete mode 100644 opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py delete mode 100644 opentelemetry-api/src/opentelemetry/distributedcontext/propagation/__init__.py delete mode 100644 opentelemetry-api/src/opentelemetry/distributedcontext/propagation/binaryformat.py delete mode 100644 opentelemetry-api/src/opentelemetry/distributedcontext/propagation/httptextformat.py create mode 100644 opentelemetry-api/tests/correlationcontext/test_correlation_context.py delete mode 100644 opentelemetry-api/tests/distributedcontext/test_distributed_context.py delete mode 100644 opentelemetry-sdk/src/opentelemetry/sdk/distributedcontext/__init__.py delete mode 100644 opentelemetry-sdk/src/opentelemetry/sdk/distributedcontext/propagation/__init__.py delete mode 100644 opentelemetry-sdk/tests/distributedcontext/__init__.py delete mode 100644 opentelemetry-sdk/tests/distributedcontext/test_distributed_context.py diff --git a/opentelemetry-api/src/opentelemetry/context/__init__.py b/opentelemetry-api/src/opentelemetry/context/__init__.py index 43a7722f885..2da005995d3 100644 --- a/opentelemetry-api/src/opentelemetry/context/__init__.py +++ b/opentelemetry-api/src/opentelemetry/context/__init__.py @@ -138,6 +138,8 @@ async def main(): asyncio.run(main()) """ +import typing + from .base_context import BaseRuntimeContext __all__ = ["Context"] @@ -150,3 +152,20 @@ async def main(): from .thread_local_context import ThreadLocalRuntimeContext Context = ThreadLocalRuntimeContext() + + +class ContextAPI: + """ + Temporary class, will be replaced once the rest of + context propagation is implemented + """ + + def __init__(self) -> None: + self.contents = {} # type: typing.Dict[str, typing.Any] + + def get_value(self, name: str) -> typing.Any: + return self.contents.get(name) + + def set_value(self, name: str, value: typing.Any) -> "ContextAPI": + self.contents[name] = value + return self diff --git a/opentelemetry-api/src/opentelemetry/correlationcontext/__init__.py b/opentelemetry-api/src/opentelemetry/correlationcontext/__init__.py new file mode 100644 index 00000000000..5bc68739393 --- /dev/null +++ b/opentelemetry-api/src/opentelemetry/correlationcontext/__init__.py @@ -0,0 +1,128 @@ +# Copyright 2019, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy +import itertools +import string +import typing +from contextlib import contextmanager + +from opentelemetry.context import ContextAPI + +CORRELATION_CONTEXT_KEY = "correlation-context-key" + + +class CorrelationContextManager: + """ + Manages access to CorrelationContext entries + """ + + def __init__( + self, entries: typing.Optional[typing.Dict[str, typing.Any]] = None + ) -> None: + if entries: + self._correlation_context = copy.deepcopy(entries) + else: + self._correlation_context = {} + + def get_correlations(self) -> typing.Dict: + """ + Returns the entries in this CorrelationContext. The order of entries is not significant. Based + on the languagespecification, the returned value can be either an immutable collection or an + immutable iterator to the collection of entries in this CorrelationContext. + + Returns: + An immutable iterator to the collection of entries in this CorrelationContext + """ + return self._correlation_context.items() + + def get_correlation( + self, context: ContextAPI, name: str + ) -> typing.Optional[typing.Any]: + """ + To access the value for an entry by a prior event, the Correlations API provides a + function which takes a context and a name as input, and returns a value. Returns + the Value associated with the given Name, or null if the given Name is not present. + + Args: + context: The context in which to find the CorrelationContext + name: The name of the entry to retrieve + Returns: + The value of the entry matching the name + """ + # pylint: disable=no-self-use + correlation_context = context.get_value(CORRELATION_CONTEXT_KEY) + if correlation_context and name in correlation_context: + return correlation_context[name] + return None + + def set_correlation( + self, context: ContextAPI, name: str, value: typing.Any + ) -> ContextAPI: + """ + To record the value for an entry, the Correlations API provides a function which takes a + context, a name, and a value as input. Returns an updated Context which contains the new value. + + Args: + context: The context in which to find the CorrelationContext + name: The name of the entry to set + value: The value of the entry + Returns: + A new Context object with updated correlations + """ + new_correlation_context = self._copy() + new_correlation_context[name] = value + return context.set_value( + CORRELATION_CONTEXT_KEY, new_correlation_context + ) + + def remove_correlation(self, context: ContextAPI, name: str) -> ContextAPI: + """ + To delete an entry, the Correlations API provides a function which takes a context and a name as + input. Returns an updated Context which no longer contains the selected Name. + + Args: + context: The context in which to remove the CorrelationContext + name: The name of the entry to remove + Returns: + A new Context object with the correlation removed + """ + new_correlation_context = self._copy() + if name in new_correlation_context: + del new_correlation_context[name] + return context.set_value( + CORRELATION_CONTEXT_KEY, new_correlation_context + ) + + def clear_correlations(self, context: ContextAPI) -> ContextAPI: + """ + To avoid sending any entries to an untrusted process, the Correlation API provides a function + to remove all Correlations from a context. Returns an updated Context with no correlations. + + Args: + context: The context in which to clear the CorrelationContext + Returns: + A new Context object with no correlations + """ + # pylint: disable=no-self-use + return context.set_value(CORRELATION_CONTEXT_KEY, {}) + + def _copy(self) -> typing.Dict[str, typing.Any]: + """ + Helper function to abstract the mechanism used to copy CorrelationContext values + + Returns: + A copy of the current entries in the CorrelationContext + """ + return copy.deepcopy(self._correlation_context) diff --git a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py b/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py deleted file mode 100644 index 38ef3739b90..00000000000 --- a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import itertools -import string -import typing -from contextlib import contextmanager - -PRINTABLE = frozenset( - itertools.chain( - string.ascii_letters, string.digits, string.punctuation, " " - ) -) - - -class EntryMetadata: - """A class representing metadata of a DistributedContext entry - - Args: - entry_ttl: The time to live (in service hops) of an entry. Must be - initially set to either :attr:`EntryMetadata.NO_PROPAGATION` - or :attr:`EntryMetadata.UNLIMITED_PROPAGATION`. - """ - - NO_PROPAGATION = 0 - UNLIMITED_PROPAGATION = -1 - - def __init__(self, entry_ttl: int) -> None: - self.entry_ttl = entry_ttl - - -class EntryKey(str): - """A class representing a key for a DistributedContext entry""" - - def __new__(cls, value: str) -> "EntryKey": - return cls.create(value) - - @staticmethod - def create(value: str) -> "EntryKey": - # pylint: disable=len-as-condition - if not 0 < len(value) <= 255 or any(c not in PRINTABLE for c in value): - raise ValueError("Invalid EntryKey", value) - - return typing.cast(EntryKey, value) - - -class EntryValue(str): - """A class representing the value of a DistributedContext entry""" - - def __new__(cls, value: str) -> "EntryValue": - return cls.create(value) - - @staticmethod - def create(value: str) -> "EntryValue": - if any(c not in PRINTABLE for c in value): - raise ValueError("Invalid EntryValue", value) - - return typing.cast(EntryValue, value) - - -class Entry: - def __init__( - self, metadata: EntryMetadata, key: EntryKey, value: EntryValue - ) -> None: - self.metadata = metadata - self.key = key - self.value = value - - -class DistributedContext: - """A container for distributed context entries""" - - def __init__(self, entries: typing.Iterable[Entry]) -> None: - self._container = {entry.key: entry for entry in entries} - - def get_entries(self) -> typing.Iterable[Entry]: - """Returns an immutable iterator to entries.""" - return self._container.values() - - def get_entry_value(self, key: EntryKey) -> typing.Optional[EntryValue]: - """Returns the entry associated with a key or None - - Args: - key: the key with which to perform a lookup - """ - if key in self._container: - return self._container[key].value - return None - - -class DistributedContextManager: - def get_current_context(self) -> typing.Optional[DistributedContext]: - """Gets the current DistributedContext. - - Returns: - A DistributedContext instance representing the current context. - """ - - @contextmanager # type: ignore - def use_context( - self, context: DistributedContext - ) -> typing.Iterator[DistributedContext]: - """Context manager for controlling a DistributedContext lifetime. - - Set the context as the active DistributedContext. - - On exiting, the context manager will restore the parent - DistributedContext. - - Args: - context: A DistributedContext instance to make current. - """ - # pylint: disable=no-self-use - yield context diff --git a/opentelemetry-api/src/opentelemetry/distributedcontext/propagation/__init__.py b/opentelemetry-api/src/opentelemetry/distributedcontext/propagation/__init__.py deleted file mode 100644 index c8706281ad7..00000000000 --- a/opentelemetry-api/src/opentelemetry/distributedcontext/propagation/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .binaryformat import BinaryFormat -from .httptextformat import HTTPTextFormat - -__all__ = ["BinaryFormat", "HTTPTextFormat"] diff --git a/opentelemetry-api/src/opentelemetry/distributedcontext/propagation/binaryformat.py b/opentelemetry-api/src/opentelemetry/distributedcontext/propagation/binaryformat.py deleted file mode 100644 index d6d083c0dae..00000000000 --- a/opentelemetry-api/src/opentelemetry/distributedcontext/propagation/binaryformat.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import abc -import typing - -from opentelemetry.distributedcontext import DistributedContext - - -class BinaryFormat(abc.ABC): - """API for serialization of span context into binary formats. - - This class provides an interface that enables converting span contexts - to and from a binary format. - """ - - @staticmethod - @abc.abstractmethod - def to_bytes(context: DistributedContext) -> bytes: - """Creates a byte representation of a DistributedContext. - - to_bytes should read values from a DistributedContext and return a data - format to represent it, in bytes. - - Args: - context: the DistributedContext to serialize - - Returns: - A bytes representation of the DistributedContext. - - """ - - @staticmethod - @abc.abstractmethod - def from_bytes( - byte_representation: bytes, - ) -> typing.Optional[DistributedContext]: - """Return a DistributedContext that was represented by bytes. - - from_bytes should return back a DistributedContext that was constructed - from the data serialized in the byte_representation passed. If it is - not possible to read in a proper DistributedContext, return None. - - Args: - byte_representation: the bytes to deserialize - - Returns: - A bytes representation of the DistributedContext if it is valid. - Otherwise return None. - - """ diff --git a/opentelemetry-api/src/opentelemetry/distributedcontext/propagation/httptextformat.py b/opentelemetry-api/src/opentelemetry/distributedcontext/propagation/httptextformat.py deleted file mode 100644 index 3e2c186283c..00000000000 --- a/opentelemetry-api/src/opentelemetry/distributedcontext/propagation/httptextformat.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import abc -import typing - -from opentelemetry.distributedcontext import DistributedContext - -Setter = typing.Callable[[object, str, str], None] -Getter = typing.Callable[[object, str], typing.List[str]] - - -class HTTPTextFormat(abc.ABC): - """API for propagation of span context via headers. - - This class provides an interface that enables extracting and injecting - span context into headers of HTTP requests. HTTP frameworks and clients - can integrate with HTTPTextFormat by providing the object containing the - headers, and a getter and setter function for the extraction and - injection of values, respectively. - - Example:: - - import flask - import requests - from opentelemetry.context.propagation import HTTPTextFormat - - PROPAGATOR = HTTPTextFormat() - - def get_header_from_flask_request(request, key): - return request.headers.get_all(key) - - def set_header_into_requests_request(request: requests.Request, - key: str, value: str): - request.headers[key] = value - - def example_route(): - distributed_context = PROPAGATOR.extract( - get_header_from_flask_request, - flask.request - ) - request_to_downstream = requests.Request( - "GET", "http://httpbin.org/get" - ) - PROPAGATOR.inject( - distributed_context, - set_header_into_requests_request, - request_to_downstream - ) - session = requests.Session() - session.send(request_to_downstream.prepare()) - - - .. _Propagation API Specification: - https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-propagators.md - """ - - @abc.abstractmethod - def extract( - self, get_from_carrier: Getter, carrier: object - ) -> DistributedContext: - """Create a DistributedContext from values in the carrier. - - The extract function should retrieve values from the carrier - object using get_from_carrier, and use values to populate a - DistributedContext value and return it. - - Args: - get_from_carrier: a function that can retrieve zero - or more values from the carrier. In the case that - the value does not exist, return an empty list. - carrier: and object which contains values that are - used to construct a DistributedContext. This object - must be paired with an appropriate get_from_carrier - which understands how to extract a value from it. - Returns: - A DistributedContext with configuration found in the carrier. - - """ - - @abc.abstractmethod - def inject( - self, - context: DistributedContext, - set_in_carrier: Setter, - carrier: object, - ) -> None: - """Inject values from a DistributedContext into a carrier. - - inject enables the propagation of values into HTTP clients or - other objects which perform an HTTP request. Implementations - should use the set_in_carrier method to set values on the - carrier. - - Args: - context: The DistributedContext to read values from. - set_in_carrier: A setter function that can set values - on the carrier. - carrier: An object that a place to define HTTP headers. - Should be paired with set_in_carrier, which should - know how to set header values on the carrier. - - """ diff --git a/opentelemetry-api/tests/correlationcontext/test_correlation_context.py b/opentelemetry-api/tests/correlationcontext/test_correlation_context.py new file mode 100644 index 00000000000..057567dc819 --- /dev/null +++ b/opentelemetry-api/tests/correlationcontext/test_correlation_context.py @@ -0,0 +1,66 @@ +# Copyright 2019, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +from opentelemetry import correlationcontext +from opentelemetry.context import ContextAPI + + +class TestCorrelationContextManager(unittest.TestCase): + def setUp(self): + self.context = ContextAPI() + self.manager = correlationcontext.CorrelationContextManager() + self.manager.set_correlation( + self.context, "client-version", "initial.version" + ) + + def test_get_correlation(self): + self.assertEqual( + self.manager.get_correlation(self.context, "client-version"), + "initial.version", + ) + + def test_set_correlation(self): + context = self.manager.set_correlation( + self.context, "client-version", "test.point.oh" + ) + self.assertEqual( + self.manager.get_correlation(context, "client-version"), + "test.point.oh", + ) + + def test_remove_correlation(self): + context = self.manager.set_correlation( + self.context, "new-correlation", "value" + ) + self.assertEqual( + self.manager.get_correlation(context, "new-correlation"), "value" + ) + context = self.manager.remove_correlation(context, "new-correlation") + self.assertIsNone( + self.manager.get_correlation(context, "new-correlation") + ) + + def test_clear_correlation(self): + context = self.manager.set_correlation( + self.context, "new-correlation", "value" + ) + self.assertEqual( + self.manager.get_correlation(context, "new-correlation"), "value" + ) + context = self.manager.clear_correlations(context) + self.assertIsNone( + self.manager.get_correlation(context, "new-correlation") + ) diff --git a/opentelemetry-api/tests/distributedcontext/test_distributed_context.py b/opentelemetry-api/tests/distributedcontext/test_distributed_context.py deleted file mode 100644 index c730603b162..00000000000 --- a/opentelemetry-api/tests/distributedcontext/test_distributed_context.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import unittest - -from opentelemetry import distributedcontext - - -class TestEntryMetadata(unittest.TestCase): - def test_entry_ttl_no_propagation(self): - metadata = distributedcontext.EntryMetadata( - distributedcontext.EntryMetadata.NO_PROPAGATION - ) - self.assertEqual(metadata.entry_ttl, 0) - - def test_entry_ttl_unlimited_propagation(self): - metadata = distributedcontext.EntryMetadata( - distributedcontext.EntryMetadata.UNLIMITED_PROPAGATION - ) - self.assertEqual(metadata.entry_ttl, -1) - - -class TestEntryKey(unittest.TestCase): - def test_create_empty(self): - with self.assertRaises(ValueError): - distributedcontext.EntryKey.create("") - - def test_create_too_long(self): - with self.assertRaises(ValueError): - distributedcontext.EntryKey.create("a" * 256) - - def test_create_invalid_character(self): - with self.assertRaises(ValueError): - distributedcontext.EntryKey.create("\x00") - - def test_create_valid(self): - key = distributedcontext.EntryKey.create("ok") - self.assertEqual(key, "ok") - - def test_key_new(self): - key = distributedcontext.EntryKey("ok") - self.assertEqual(key, "ok") - - -class TestEntryValue(unittest.TestCase): - def test_create_invalid_character(self): - with self.assertRaises(ValueError): - distributedcontext.EntryValue.create("\x00") - - def test_create_valid(self): - key = distributedcontext.EntryValue.create("ok") - self.assertEqual(key, "ok") - - def test_key_new(self): - key = distributedcontext.EntryValue("ok") - self.assertEqual(key, "ok") - - -class TestDistributedContext(unittest.TestCase): - def setUp(self): - entry = self.entry = distributedcontext.Entry( - distributedcontext.EntryMetadata( - distributedcontext.EntryMetadata.NO_PROPAGATION - ), - distributedcontext.EntryKey("key"), - distributedcontext.EntryValue("value"), - ) - self.context = distributedcontext.DistributedContext((entry,)) - - def test_get_entries(self): - self.assertIn(self.entry, self.context.get_entries()) - - def test_get_entry_value_present(self): - value = self.context.get_entry_value(self.entry.key) - self.assertIs(value, self.entry.value) - - def test_get_entry_value_missing(self): - key = distributedcontext.EntryKey("missing") - value = self.context.get_entry_value(key) - self.assertIsNone(value) - - -class TestDistributedContextManager(unittest.TestCase): - def setUp(self): - self.manager = distributedcontext.DistributedContextManager() - - def test_get_current_context(self): - self.assertIsNone(self.manager.get_current_context()) - - def test_use_context(self): - expected = distributedcontext.DistributedContext( - ( - distributedcontext.Entry( - distributedcontext.EntryMetadata(0), - distributedcontext.EntryKey("0"), - distributedcontext.EntryValue(""), - ), - ) - ) - with self.manager.use_context(expected) as output: - self.assertIs(output, expected) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/distributedcontext/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/distributedcontext/__init__.py deleted file mode 100644 index a20cbf89635..00000000000 --- a/opentelemetry-sdk/src/opentelemetry/sdk/distributedcontext/__init__.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import typing -from contextlib import contextmanager - -from opentelemetry import distributedcontext as dctx_api -from opentelemetry.context import Context - - -class DistributedContextManager(dctx_api.DistributedContextManager): - """See `opentelemetry.distributedcontext.DistributedContextManager` - - Args: - name: The name of the context manager - """ - - def __init__(self, name: str = "") -> None: - if name: - slot_name = "DistributedContext.{}".format(name) - else: - slot_name = "DistributedContext" - - self._current_context = Context.register_slot(slot_name) - - def get_current_context( - self, - ) -> typing.Optional[dctx_api.DistributedContext]: - """Gets the current DistributedContext. - - Returns: - A DistributedContext instance representing the current context. - """ - return self._current_context.get() - - @contextmanager - def use_context( - self, context: dctx_api.DistributedContext - ) -> typing.Iterator[dctx_api.DistributedContext]: - """Context manager for controlling a DistributedContext lifetime. - - Set the context as the active DistributedContext. - - On exiting, the context manager will restore the parent - DistributedContext. - - Args: - context: A DistributedContext instance to make current. - """ - snapshot = self._current_context.get() - self._current_context.set(context) - try: - yield context - finally: - self._current_context.set(snapshot) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/distributedcontext/propagation/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/distributedcontext/propagation/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/opentelemetry-sdk/tests/distributedcontext/__init__.py b/opentelemetry-sdk/tests/distributedcontext/__init__.py deleted file mode 100644 index d853a7bcf65..00000000000 --- a/opentelemetry-sdk/tests/distributedcontext/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/opentelemetry-sdk/tests/distributedcontext/test_distributed_context.py b/opentelemetry-sdk/tests/distributedcontext/test_distributed_context.py deleted file mode 100644 index eddb61330dc..00000000000 --- a/opentelemetry-sdk/tests/distributedcontext/test_distributed_context.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import unittest - -from opentelemetry import distributedcontext as dctx_api -from opentelemetry.sdk import distributedcontext - - -class TestDistributedContextManager(unittest.TestCase): - def setUp(self): - self.manager = distributedcontext.DistributedContextManager() - - def test_use_context(self): - # Context is None initially - self.assertIsNone(self.manager.get_current_context()) - - # Start initial context - dctx = dctx_api.DistributedContext(()) - with self.manager.use_context(dctx) as current: - self.assertIs(current, dctx) - self.assertIs(self.manager.get_current_context(), dctx) - - # Context is overridden - nested_dctx = dctx_api.DistributedContext(()) - with self.manager.use_context(nested_dctx) as current: - self.assertIs(current, nested_dctx) - self.assertIs(self.manager.get_current_context(), nested_dctx) - - # Context is restored - self.assertIs(self.manager.get_current_context(), dctx)