diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6f5acb1c8c..5efac69e52 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,7 +6,7 @@ on: - 'release/*' pull_request: env: - CORE_REPO_SHA: 3b236f5309c36d089c0d9dc6dc6c985bb1668776 + CORE_REPO_SHA: c4cdffd0c8bd47b2e5c4f4a823722ca514f10db3 jobs: build: diff --git a/CHANGELOG.md b/CHANGELOG.md index 6acedf12e3..8edd0ac74b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `opentelemetry-instrumentation-botocore` now supports context propagation for lambda invoke via Payload embedded headers. ([#458](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/458)) +- Added support for CreateKey functionality. + ([#502](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/502)) ## [0.21b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.2.0-0.21b0) - 2021-05-11 diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py index 1eb7aed740..d6581dd5cc 100644 --- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py +++ b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/spanprocessor.py @@ -18,6 +18,7 @@ import typing from opentelemetry.context import Context, attach, detach, set_value +from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY from opentelemetry.sdk.trace import Span, SpanProcessor from opentelemetry.sdk.trace.export import SpanExporter from opentelemetry.trace import INVALID_TRACE_ID @@ -163,7 +164,7 @@ def export(self) -> None: del self.traces_spans_ended_count[trace_id] if len(export_trace_ids) > 0: - token = attach(set_value("suppress_instrumentation", True)) + token = attach(set_value(_SUPPRESS_INSTRUMENTATION_KEY, True)) for trace_id in export_trace_ids: with self.traces_lock: diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py index b9441ca108..d4000584bb 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py @@ -75,6 +75,7 @@ def strip_query_params(url: yarl.URL) -> str: from opentelemetry.instrumentation.aiohttp_client.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.utils import ( + _SUPPRESS_INSTRUMENTATION_KEY, http_status_to_status_code, unwrap, ) @@ -155,7 +156,7 @@ async def on_request_start( trace_config_ctx: types.SimpleNamespace, params: aiohttp.TraceRequestStartParams, ): - if context_api.get_value("suppress_instrumentation"): + if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY): trace_config_ctx.span = None return @@ -248,7 +249,7 @@ def _instrument( """ # pylint:disable=unused-argument def instrumented_init(wrapped, instance, args, kwargs): - if context_api.get_value("suppress_instrumentation"): + if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY): return wrapped(*args, **kwargs) trace_configs = list(kwargs.get("trace_configs") or ()) diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py index a9f82202d8..7acb52f38f 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py @@ -30,6 +30,7 @@ from opentelemetry.instrumentation.aiohttp_client import ( AioHttpClientInstrumentor, ) +from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode @@ -448,7 +449,7 @@ async def uninstrument_request(server: aiohttp.test_utils.TestServer): def test_suppress_instrumentation(self): token = context.attach( - context.set_value("suppress_instrumentation", True) + context.set_value(_SUPPRESS_INSTRUMENTATION_KEY, True) ) try: run_with_test_server( @@ -462,7 +463,7 @@ def test_suppress_instrumentation(self): async def suppressed_request(server: aiohttp.test_utils.TestServer): async with aiohttp.test_utils.TestClient(server) as client: token = context.attach( - context.set_value("suppress_instrumentation", True) + context.set_value(_SUPPRESS_INSTRUMENTATION_KEY, True) ) await client.get(TestAioHttpClientInstrumentor.URL) context.detach(token) diff --git a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py index 457d312463..0439490c5c 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py @@ -58,7 +58,10 @@ from opentelemetry.instrumentation.botocore.package import _instruments from opentelemetry.instrumentation.botocore.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from opentelemetry.instrumentation.utils import unwrap +from opentelemetry.instrumentation.utils import ( + _SUPPRESS_INSTRUMENTATION_KEY, + unwrap, +) from opentelemetry.propagate import inject from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind, get_tracer @@ -128,7 +131,7 @@ def _patch_lambda_invoke(api_params): # pylint: disable=too-many-branches def _patched_api_call(self, original_func, instance, args, kwargs): - if context_api.get_value("suppress_instrumentation"): + if context_api.get_value(_SUPPRESS_INSTRUMENTATION_KEY): return original_func(*args, **kwargs) # pylint: disable=protected-access diff --git a/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py b/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py index 58a065cca8..e77a255d13 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_instrumentation.py @@ -34,6 +34,7 @@ from opentelemetry import trace as trace_api from opentelemetry.context import attach, detach, set_value from opentelemetry.instrumentation.botocore import BotocoreInstrumentor +from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY from opentelemetry.propagate import get_global_textmap, set_global_textmap from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.mock_textmap import MockTextMapPropagator @@ -509,7 +510,7 @@ def test_suppress_instrumentation_xray_client(self): xray_client = self.session.create_client( "xray", region_name="us-east-1" ) - token = attach(set_value("suppress_instrumentation", True)) + token = attach(set_value(_SUPPRESS_INSTRUMENTATION_KEY, True)) xray_client.put_trace_segments(TraceSegmentDocuments=["str1"]) xray_client.put_trace_segments(TraceSegmentDocuments=["str2"]) detach(token) diff --git a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py b/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py index 451dca22a8..d0e1473b19 100644 --- a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py @@ -45,7 +45,10 @@ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.requests.package import _instruments from opentelemetry.instrumentation.requests.version import __version__ -from opentelemetry.instrumentation.utils import http_status_to_status_code +from opentelemetry.instrumentation.utils import ( + _SUPPRESS_INSTRUMENTATION_KEY, + http_status_to_status_code, +) from opentelemetry.propagate import inject from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind, get_tracer @@ -54,7 +57,9 @@ # A key to a context variable to avoid creating duplicate spans when instrumenting # both, Session.request and Session.send, since Session.request calls into Session.send -_SUPPRESS_HTTP_INSTRUMENTATION_KEY = "suppress_http_instrumentation" +_SUPPRESS_HTTP_INSTRUMENTATION_KEY = context.create_key( + "suppress_http_instrumentation" +) # pylint: disable=unused-argument @@ -111,9 +116,9 @@ def call_wrapped(): def _instrumented_requests_call( method: str, url: str, call_wrapped, get_or_create_headers ): - if context.get_value("suppress_instrumentation") or context.get_value( - _SUPPRESS_HTTP_INSTRUMENTATION_KEY - ): + if context.get_value( + _SUPPRESS_INSTRUMENTATION_KEY + ) or context.get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY): return call_wrapped() # See diff --git a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py index 95006d0602..e00bd3bd4f 100644 --- a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py +++ b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py @@ -21,6 +21,7 @@ import opentelemetry.instrumentation.requests from opentelemetry import context, trace from opentelemetry.instrumentation.requests import RequestsInstrumentor +from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY from opentelemetry.propagate import get_global_textmap, set_global_textmap from opentelemetry.sdk import resources from opentelemetry.semconv.trace import SpanAttributes @@ -165,7 +166,7 @@ def test_uninstrument_session(self): def test_suppress_instrumentation(self): token = context.attach( - context.set_value("suppress_instrumentation", True) + context.set_value(_SUPPRESS_INSTRUMENTATION_KEY, True) ) try: result = self.perform_request(self.URL) diff --git a/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py b/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py index 1081a67d13..3a5f50908e 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py @@ -48,7 +48,10 @@ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.urllib.package import _instruments from opentelemetry.instrumentation.urllib.version import __version__ -from opentelemetry.instrumentation.utils import http_status_to_status_code +from opentelemetry.instrumentation.utils import ( + _SUPPRESS_INSTRUMENTATION_KEY, + http_status_to_status_code, +) from opentelemetry.propagate import inject from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind, get_tracer @@ -56,7 +59,10 @@ from opentelemetry.util.http import remove_url_credentials # A key to a context variable to avoid creating duplicate spans when instrumenting -_SUPPRESS_HTTP_INSTRUMENTATION_KEY = "suppress_http_instrumentation" +# both, Session.request and Session.send, since Session.request calls into Session.send +_SUPPRESS_HTTP_INSTRUMENTATION_KEY = context.create_key( + "suppress_http_instrumentation" +) class URLLibInstrumentor(BaseInstrumentor): @@ -129,9 +135,9 @@ def call_wrapped(): def _instrumented_open_call( _, request, call_wrapped, get_or_create_headers ): # pylint: disable=too-many-locals - if context.get_value("suppress_instrumentation") or context.get_value( - _SUPPRESS_HTTP_INSTRUMENTATION_KEY - ): + if context.get_value( + _SUPPRESS_INSTRUMENTATION_KEY + ) or context.get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY): return call_wrapped() method = request.get_method().upper() diff --git a/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py b/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py index d35ceb4c9e..9681c09686 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py +++ b/instrumentation/opentelemetry-instrumentation-urllib/tests/test_urllib_integration.py @@ -28,6 +28,7 @@ from opentelemetry.instrumentation.urllib import ( # pylint: disable=no-name-in-module,import-error URLLibInstrumentor, ) +from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY from opentelemetry.propagate import get_global_textmap, set_global_textmap from opentelemetry.sdk import resources from opentelemetry.semconv.trace import SpanAttributes @@ -198,7 +199,7 @@ def test_uninstrument_session(self): def test_suppress_instrumentation(self): token = context.attach( - context.set_value("suppress_instrumentation", True) + context.set_value(_SUPPRESS_INSTRUMENTATION_KEY, True) ) try: result = self.perform_request(self.URL) diff --git a/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py b/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py index 3e6cb1008a..0d2d7ed17b 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py @@ -56,6 +56,7 @@ def span_name_callback(method: str, url: str, headers): from opentelemetry.instrumentation.urllib3.package import _instruments from opentelemetry.instrumentation.urllib3.version import __version__ from opentelemetry.instrumentation.utils import ( + _SUPPRESS_INSTRUMENTATION_KEY, http_status_to_status_code, unwrap, ) @@ -64,7 +65,11 @@ def span_name_callback(method: str, url: str, headers): from opentelemetry.trace import Span, SpanKind, get_tracer from opentelemetry.trace.status import Status -_SUPPRESS_HTTP_INSTRUMENTATION_KEY = "suppress_http_instrumentation" +# A key to a context variable to avoid creating duplicate spans when instrumenting +# both, Session.request and Session.send, since Session.request calls into Session.send +_SUPPRESS_HTTP_INSTRUMENTATION_KEY = context.create_key( + "suppress_http_instrumentation" +) _UrlFilterT = typing.Optional[typing.Callable[[str], str]] _SpanNameT = typing.Optional[ @@ -214,7 +219,7 @@ def _apply_response(span: Span, response: urllib3.response.HTTPResponse): def _is_instrumentation_suppressed() -> bool: return bool( - context.get_value("suppress_instrumentation") + context.get_value(_SUPPRESS_INSTRUMENTATION_KEY) or context.get_value(_SUPPRESS_HTTP_INSTRUMENTATION_KEY) ) diff --git a/instrumentation/opentelemetry-instrumentation-urllib3/tests/test_urllib3_integration.py b/instrumentation/opentelemetry-instrumentation-urllib3/tests/test_urllib3_integration.py index 658044887b..670e7917d8 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib3/tests/test_urllib3_integration.py +++ b/instrumentation/opentelemetry-instrumentation-urllib3/tests/test_urllib3_integration.py @@ -20,7 +20,11 @@ import urllib3.exceptions from opentelemetry import context, trace -from opentelemetry.instrumentation.urllib3 import URLLib3Instrumentor +from opentelemetry.instrumentation.urllib3 import ( + _SUPPRESS_HTTP_INSTRUMENTATION_KEY, + URLLib3Instrumentor, +) +from opentelemetry.instrumentation.utils import _SUPPRESS_INSTRUMENTATION_KEY from opentelemetry.propagate import get_global_textmap, set_global_textmap from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.test.mock_textmap import MockTextMapPropagator @@ -165,8 +169,8 @@ def test_uninstrument(self): def test_suppress_instrumntation(self): suppression_keys = ( - "suppress_instrumentation", - "suppress_http_instrumentation", + _SUPPRESS_HTTP_INSTRUMENTATION_KEY, + _SUPPRESS_INSTRUMENTATION_KEY, ) for key in suppression_keys: self.memory_exporter.clear() diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py index dec070570f..16f75aae6c 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py @@ -16,8 +16,14 @@ from wrapt import ObjectProxy +from opentelemetry.context import create_key from opentelemetry.trace import StatusCode +# FIXME This is a temporary location for the suppress instrumentation key. +# Once the decision around how to suppress instrumentation is made in the +# spec, this key should be moved accordingly. +_SUPPRESS_INSTRUMENTATION_KEY = create_key("suppress_instrumentation") + def extract_attributes_from_object( obj: any, attributes: Sequence[str], existing: Dict[str, str] = None diff --git a/tox.ini b/tox.ini index e2b97cc61f..ee63f91552 100644 --- a/tox.ini +++ b/tox.ini @@ -228,11 +228,10 @@ commands_pre = ; cases but it saves a lot of boilerplate in this file. test: pip install {toxinidir}/opentelemetry-python-core/opentelemetry-api[test] test: pip install {toxinidir}/opentelemetry-python-core/opentelemetry-semantic-conventions[test] + test: pip install {toxinidir}/opentelemetry-instrumentation[test] test: pip install {toxinidir}/opentelemetry-python-core/opentelemetry-sdk[test] test: pip install {toxinidir}/opentelemetry-python-core/tests/util[test] - test: pip install {toxinidir}/opentelemetry-instrumentation[test] - celery: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-celery[test] grpc: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-grpc[test] @@ -325,8 +324,8 @@ deps = commands_pre = python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-api python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-semantic-conventions - python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-sdk python -m pip install {toxinidir}/opentelemetry-instrumentation + python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-sdk python -m pip install {toxinidir}/util/opentelemetry-util-http changedir = docs @@ -352,9 +351,9 @@ commands_pre = sudo apt-get install libsnappy-dev python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-api python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-semantic-conventions + python -m pip install -e {toxinidir}/opentelemetry-instrumentation[test] python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-sdk python -m pip install {toxinidir}/opentelemetry-python-core/tests/util - python -m pip install -e {toxinidir}/opentelemetry-instrumentation[test] python -m pip install -e {toxinidir}/util/opentelemetry-util-http[test] python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-wsgi[test] python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi[test] @@ -420,9 +419,9 @@ changedir = commands_pre = pip install -e {toxinidir}/opentelemetry-python-core/opentelemetry-api \ -e {toxinidir}/opentelemetry-python-core/opentelemetry-semantic-conventions \ + -e {toxinidir}/opentelemetry-instrumentation \ -e {toxinidir}/opentelemetry-python-core/opentelemetry-sdk \ -e {toxinidir}/opentelemetry-python-core/tests/util \ - -e {toxinidir}/opentelemetry-instrumentation \ -e {toxinidir}/instrumentation/opentelemetry-instrumentation-asyncpg \ -e {toxinidir}/instrumentation/opentelemetry-instrumentation-celery \ -e {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi \