From 109299173e7543df4e5636f1530cc93e8d25dcc3 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Sun, 10 Jan 2021 16:46:38 -0600 Subject: [PATCH 01/11] Remove Configuration --- CHANGELOG.md | 4 ++ .../instrumentation/boto/__init__.py | 2 - .../instrumentation/django/__init__.py | 8 +-- .../instrumentation/django/middleware.py | 63 +++++++++++++++---- .../tests/test_middleware.py | 10 +-- .../instrumentation/falcon/__init__.py | 57 ++++++++++++++--- .../tests/test_falcon.py | 14 ++--- .../instrumentation/fastapi/__init__.py | 32 +++++++++- .../tests/test_fastapi_instrumentation.py | 4 +- .../instrumentation/flask/__init__.py | 54 ++++++++++++---- .../tests/base_test.py | 6 -- .../tests/test_programmatic.py | 8 ++- .../instrumentation/pyramid/callbacks.py | 50 +++++++++++---- .../tests/pyramid_base_test.py | 6 -- .../tests/test_programmatic.py | 4 +- .../instrumentation/starlette/__init__.py | 32 +++++++++- .../tests/test_starlette_instrumentation.py | 4 +- .../instrumentation/tornado/__init__.py | 59 ++++++++++++++--- .../tests/test_instrumentation.py | 10 +-- 19 files changed, 323 insertions(+), 104 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index adfaace015..bb9ce1ccef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.17b0](https://github.com/open-telemetry/opentelemetry-python-contrib/releases/tag/v0.17b0) - 2021-01-20 ### Added +- Remove Configuration + ([#285](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/285)) - `opentelemetry-instrumentation-sqlalchemy` Ensure spans have kind set to "CLIENT" ([#278](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/278)) - `opentelemetry-instrumentation-celery` Add support for Celery version 5.x @@ -48,6 +50,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#273](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/273)) ### Changed +- Remove Configuration + ([#285](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/285)) - `opentelemetry-instrumentation-asgi`, `opentelemetry-instrumentation-wsgi` Return `None` for `CarrierGetter` if key not found ([#233](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/233)) - `opentelemetry-instrumentation-grpc` Comply with updated spec, rework tests diff --git a/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py b/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py index 58dee0ba7f..2eb88001ae 100644 --- a/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-boto/src/opentelemetry/instrumentation/boto/__init__.py @@ -84,8 +84,6 @@ def _instrument(self, **kwargs): # For exemple EC2 uses AWSQueryConnection and S3 uses # AWSAuthConnection - # FIXME should the tracer provider be accessed via Configuration - # instead? # pylint: disable=attribute-defined-outside-init self._tracer = get_tracer( __name__, __version__, kwargs.get("tracer_provider") diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py index 26e21a1f7f..c4101ef181 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py @@ -13,10 +13,10 @@ # limitations under the License. from logging import getLogger +from os import environ from django.conf import settings -from opentelemetry.configuration import Configuration from opentelemetry.instrumentation.django.middleware import _DjangoMiddleware from opentelemetry.instrumentation.django.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor @@ -43,11 +43,7 @@ def _instrument(self, **kwargs): # FIXME this is probably a pattern that will show up in the rest of the # ext. Find a better way of implementing this. - # FIXME Probably the evaluation of strings into boolean values can be - # built inside the Configuration class itself with the magic method - # __bool__ - - if Configuration().DJANGO_INSTRUMENT is False: + if environ.get("OTEL_PYTHON_DJANGO_INSTRUMENT") == "False": return # This can not be solved, but is an inherent problem of this approach: diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py index edb585cdb4..0f0eed11a4 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -12,12 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -import time from logging import getLogger +from os import environ +from re import compile as re_compile +from re import search +from time import time from django.conf import settings -from opentelemetry.configuration import Configuration from opentelemetry.context import attach, detach from opentelemetry.instrumentation.django.version import __version__ from opentelemetry.instrumentation.utils import extract_attributes_from_object @@ -51,6 +53,46 @@ ] +class _ExcludeList: + """Class to exclude certain paths (given as a list of regexes) from tracing requests""" + + def __init__(self, excluded_urls): + self._excluded_urls = excluded_urls + if self._excluded_urls: + self._regex = re_compile("|".join(excluded_urls)) + + def url_disabled(self, url: str) -> bool: + return bool(self._excluded_urls and search(self._regex, url)) + + +_root = r"OTEL_PYTHON_{}" + + +def _get_traced_request_attrs(): + traced_request_attrs = environ.get( + _root.format("DJANGO_TRACED_REQUEST_ATTRS"), [] + ) + + if traced_request_attrs: + traced_request_attrs = [ + traced_request_attr.strip() + for traced_request_attr in traced_request_attrs.split(",") + ] + + return traced_request_attrs + + +def _get_excluded_urls(): + excluded_urls = environ.get(_root.format("DJANGO_EXCLUDED_URLS"), []) + + if excluded_urls: + excluded_urls = [ + excluded_url.strip() for excluded_url in excluded_urls.split(",") + ] + + return _ExcludeList(excluded_urls) + + class _DjangoMiddleware(MiddlewareMixin): """Django Middleware for OpenTelemetry""" @@ -61,9 +103,8 @@ class _DjangoMiddleware(MiddlewareMixin): _environ_span_key = "opentelemetry-instrumentor-django.span_key" _environ_exception_key = "opentelemetry-instrumentor-django.exception_key" - _excluded_urls = Configuration()._excluded_urls("django") - - _traced_request_attrs = Configuration()._traced_request_attrs("django") + _traced_request_attrs = _get_traced_request_attrs() + _excluded_urls = _get_excluded_urls() @staticmethod def _get_span_name(request): @@ -111,23 +152,23 @@ def process_request(self, request): return # pylint:disable=W0212 - request._otel_start_time = time.time() + request._otel_start_time = time() - environ = request.META + request_meta = request.META - token = attach(extract(carrier_getter, environ)) + token = attach(extract(carrier_getter, request_meta)) tracer = get_tracer(__name__, __version__) span = tracer.start_span( self._get_span_name(request), kind=SpanKind.SERVER, - start_time=environ.get( + start_time=request_meta.get( "opentelemetry-instrumentor-django.starttime_key" ), ) - attributes = collect_request_attributes(environ) + attributes = collect_request_attributes(request_meta) # pylint:disable=W0212 request._otel_labels = self._get_metric_labels_from_attributes( attributes @@ -215,7 +256,7 @@ def process_response(self, request, response): if metric_recorder is not None: # pylint:disable=W0212 metric_recorder.record_server_duration_range( - request._otel_start_time, time.time(), request._otel_labels + request._otel_start_time, time(), request._otel_labels ) except Exception as ex: # pylint: disable=W0703 _logger.warning("Error recording duration metrics: %s", ex) diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py index b75a8cd0e9..fe3f25255c 100644 --- a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py @@ -21,8 +21,11 @@ from django.test import Client from django.test.utils import setup_test_environment, teardown_test_environment -from opentelemetry.configuration import Configuration from opentelemetry.instrumentation.django import DjangoInstrumentor +from opentelemetry.instrumentation.django.middleware import ( + _get_excluded_urls, + _get_traced_request_attrs, +) from opentelemetry.sdk.util import get_dict_as_key from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase @@ -64,7 +67,6 @@ def setUp(self): super().setUp() setup_test_environment() _django_instrumentor.instrument() - Configuration._reset() # pylint: disable=protected-access self.env_patch = patch.dict( "os.environ", { @@ -75,11 +77,11 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.django.middleware._DjangoMiddleware._excluded_urls", - Configuration()._excluded_urls("django"), + _get_excluded_urls(), ) self.traced_patch = patch( "opentelemetry.instrumentation.django.middleware._DjangoMiddleware._traced_request_attrs", - Configuration()._traced_request_attrs("django"), + _get_traced_request_attrs(), ) self.exclude_patch.start() self.traced_patch.start() diff --git a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py index e9b1f16800..a3ffb0d5fa 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py @@ -43,14 +43,16 @@ def on_get(self, req, resp): --- """ -import sys from logging import getLogger +from os import environ +from re import compile as re_compile +from re import search +from sys import exc_info import falcon import opentelemetry.instrumentation.wsgi as otel_wsgi -from opentelemetry import configuration, context, propagators, trace -from opentelemetry.configuration import Configuration +from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.falcon.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.utils import ( @@ -68,8 +70,49 @@ def on_get(self, req, resp): _ENVIRON_TOKEN = "opentelemetry-falcon.token" _ENVIRON_EXC = "opentelemetry-falcon.exc" -cfg = configuration.Configuration() -_excluded_urls = cfg._excluded_urls("falcon") + +class _ExcludeList: + """Class to exclude certain paths (given as a list of regexes) from tracing requests""" + + def __init__(self, excluded_urls): + self._excluded_urls = excluded_urls + if self._excluded_urls: + self._regex = re_compile("|".join(excluded_urls)) + + def url_disabled(self, url: str) -> bool: + return bool(self._excluded_urls and search(self._regex, url)) + + +_root = r"OTEL_PYTHON_{}" + + +def _get_traced_request_attrs(): + traced_request_attrs = environ.get( + _root.format("FALCON_TRACED_REQUEST_ATTRS"), [] + ) + + if traced_request_attrs: + traced_request_attrs = [ + traced_request_attr.strip() + for traced_request_attr in traced_request_attrs.split(",") + ] + + return traced_request_attrs + + +def _get_excluded_urls(): + excluded_urls = environ.get(_root.format("FALCON_EXCLUDED_URLS"), []) + + if excluded_urls: + excluded_urls = [ + excluded_url.strip() for excluded_url in excluded_urls.split(",") + ] + + return _ExcludeList(excluded_urls) + + +_excluded_urls = _get_excluded_urls() +_traced_request_attrs = _get_traced_request_attrs() class FalconInstrumentor(BaseInstrumentor): @@ -149,7 +192,7 @@ class _TraceMiddleware: def __init__(self, tracer=None, traced_request_attrs=None): self.tracer = tracer - self._traced_request_attrs = cfg._traced_request_attrs("falcon") + self._traced_request_attrs = _traced_request_attrs def process_request(self, req, resp): span = req.env.get(_ENVIRON_SPAN_KEY) @@ -186,7 +229,7 @@ def process_response( status = "404" reason = "NotFound" - exc_type, exc, _ = sys.exc_info() + exc_type, exc, _ = exc_info() if exc_type and not req_succeeded: if "HTTPNotFound" in exc_type.__name__: status = "404" diff --git a/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py b/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py index 73088d7611..0fcc9a589b 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py @@ -16,8 +16,11 @@ from falcon import testing -from opentelemetry.configuration import Configuration -from opentelemetry.instrumentation.falcon import FalconInstrumentor +from opentelemetry.instrumentation.falcon import ( + FalconInstrumentor, + _get_excluded_urls, + _get_traced_request_attrs, +) from opentelemetry.test.test_base import TestBase from opentelemetry.trace.status import StatusCode @@ -30,7 +33,6 @@ def setUp(self): FalconInstrumentor().instrument() self.app = make_app() # pylint: disable=protected-access - Configuration()._reset() self.env_patch = patch.dict( "os.environ", { @@ -41,15 +43,13 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.falcon._excluded_urls", - Configuration()._excluded_urls("falcon"), + _get_excluded_urls(), ) middleware = self.app._middleware[0][ # pylint:disable=W0212 0 ].__self__ self.traced_patch = patch.object( - middleware, - "_traced_request_attrs", - Configuration()._traced_request_attrs("falcon"), + middleware, "_traced_request_attrs", _get_traced_request_attrs(), ) self.exclude_patch.start() self.traced_patch.start() diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py index b938464065..ad3e3eae6c 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py @@ -11,17 +11,43 @@ # 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 typing import Optional + +from os import environ +from re import compile as re_compile +from re import search import fastapi from starlette.routing import Match -from opentelemetry.configuration import Configuration from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware from opentelemetry.instrumentation.fastapi.version import __version__ # noqa from opentelemetry.instrumentation.instrumentor import BaseInstrumentor -_excluded_urls = Configuration()._excluded_urls("fastapi") + +class _ExcludeList: + """Class to exclude certain paths (given as a list of regexes) from tracing requests""" + + def __init__(self, excluded_urls): + self._excluded_urls = excluded_urls + if self._excluded_urls: + self._regex = re_compile("|".join(excluded_urls)) + + def url_disabled(self, url: str) -> bool: + return bool(self._excluded_urls and search(self._regex, url)) + + +def _get_excluded_urls(): + excluded_urls = environ.get("OTEL_PYTHON_FASTAPI_EXCLUDED_URLS", []) + + if excluded_urls: + excluded_urls = [ + excluded_url.strip() for excluded_url in excluded_urls.split(",") + ] + + return _ExcludeList(excluded_urls) + + +_excluded_urls = _get_excluded_urls() class FastAPIInstrumentor(BaseInstrumentor): diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py index 6d5a1b1808..13d90e410f 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py @@ -19,7 +19,6 @@ from fastapi.testclient import TestClient import opentelemetry.instrumentation.fastapi as otel_fastapi -from opentelemetry.configuration import Configuration from opentelemetry.test.test_base import TestBase @@ -31,7 +30,6 @@ def _create_app(self): def setUp(self): super().setUp() - Configuration()._reset() self.env_patch = patch.dict( "os.environ", {"OTEL_PYTHON_FASTAPI_EXCLUDED_URLS": "/exclude/123,healthzz"}, @@ -39,7 +37,7 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.fastapi._excluded_urls", - Configuration()._excluded_urls("fastapi"), + otel_fastapi._get_excluded_urls(), ) self.exclude_patch.start() self._instrumentor = otel_fastapi.FastAPIInstrumentor() diff --git a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py index b5045f3a72..e0ced69599 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -48,11 +48,14 @@ def hello(): """ from logging import getLogger +from os import environ +from re import compile as re_compile +from re import search import flask import opentelemetry.instrumentation.wsgi as otel_wsgi -from opentelemetry import configuration, context, propagators, trace +from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.flask.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.util import time_ns @@ -65,7 +68,30 @@ def hello(): _ENVIRON_TOKEN = "opentelemetry-flask.token" -_excluded_urls = configuration.Configuration()._excluded_urls("flask") +class _ExcludeList: + """Class to exclude certain paths (given as a list of regexes) from tracing requests""" + + def __init__(self, excluded_urls): + self._excluded_urls = excluded_urls + if self._excluded_urls: + self._regex = re_compile("|".join(excluded_urls)) + + def url_disabled(self, url: str) -> bool: + return bool(self._excluded_urls and search(self._regex, url)) + + +def _get_excluded_urls(): + excluded_urls = environ.get("OTEL_PYTHON_FLASK_EXCLUDED_URLS", []) + + if excluded_urls: + excluded_urls = [ + excluded_url.strip() for excluded_url in excluded_urls.split(",") + ] + + return _ExcludeList(excluded_urls) + + +_excluded_urls = _get_excluded_urls() def get_default_span_name(): @@ -78,12 +104,12 @@ def get_default_span_name(): def _rewrapped_app(wsgi_app): - def _wrapped_app(environ, start_response): + def _wrapped_app(wrapped_app_environ, start_response): # We want to measure the time for route matching, etc. # In theory, we could start the span here and use # update_name later but that API is "highly discouraged" so # we better avoid it. - environ[_ENVIRON_STARTTIME_KEY] = time_ns() + wrapped_app_environ[_ENVIRON_STARTTIME_KEY] = time_ns() def _start_response(status, response_headers, *args, **kwargs): if not _excluded_urls.url_disabled(flask.request.url): @@ -102,7 +128,7 @@ def _start_response(status, response_headers, *args, **kwargs): return start_response(status, response_headers, *args, **kwargs) - return wsgi_app(environ, _start_response) + return wsgi_app(wrapped_app_environ, _start_response) return _wrapped_app @@ -112,10 +138,12 @@ def _before_request(): if _excluded_urls.url_disabled(flask.request.url): return - environ = flask.request.environ + flask_request_environ = flask.request.environ span_name = name_callback() token = context.attach( - propagators.extract(otel_wsgi.carrier_getter, environ) + propagators.extract( + otel_wsgi.carrier_getter, flask_request_environ + ) ) tracer = trace.get_tracer(__name__, __version__) @@ -123,10 +151,12 @@ def _before_request(): span = tracer.start_span( span_name, kind=trace.SpanKind.SERVER, - start_time=environ.get(_ENVIRON_STARTTIME_KEY), + start_time=flask_request_environ.get(_ENVIRON_STARTTIME_KEY), ) if span.is_recording(): - attributes = otel_wsgi.collect_request_attributes(environ) + attributes = otel_wsgi.collect_request_attributes( + flask_request_environ + ) if flask.request.url_rule: # For 404 that result from no route found, etc, we # don't have a url_rule. @@ -136,9 +166,9 @@ def _before_request(): activation = tracer.use_span(span, end_on_exit=True) activation.__enter__() - environ[_ENVIRON_ACTIVATION_KEY] = activation - environ[_ENVIRON_SPAN_KEY] = span - environ[_ENVIRON_TOKEN] = token + flask_request_environ[_ENVIRON_ACTIVATION_KEY] = activation + flask_request_environ[_ENVIRON_SPAN_KEY] = span + flask_request_environ[_ENVIRON_TOKEN] = token return _before_request diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/base_test.py b/instrumentation/opentelemetry-instrumentation-flask/tests/base_test.py index c2bc646e1b..d989c66474 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/base_test.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/base_test.py @@ -15,14 +15,8 @@ from werkzeug.test import Client from werkzeug.wrappers import BaseResponse -from opentelemetry.configuration import Configuration - class InstrumentationTest: - def setUp(self): # pylint: disable=invalid-name - super().setUp() # pylint: disable=no-member - Configuration._reset() # pylint: disable=protected-access - @staticmethod def _hello_endpoint(helloid): if helloid == 500: diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index 377ce88842..c2278d7de7 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -17,8 +17,10 @@ from flask import Flask, request from opentelemetry import trace -from opentelemetry.configuration import Configuration -from opentelemetry.instrumentation.flask import FlaskInstrumentor +from opentelemetry.instrumentation.flask import ( + FlaskInstrumentor, + _get_excluded_urls, +) from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase @@ -62,7 +64,7 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.flask._excluded_urls", - Configuration()._excluded_urls("flask"), + _get_excluded_urls(), ) self.exclude_patch.start() diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py index 40894e2c62..dd6a26755b 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py @@ -1,4 +1,7 @@ from logging import getLogger +from os import environ +from re import compile as re_compile +from re import search from pyramid.events import BeforeTraversal from pyramid.httpexceptions import HTTPException @@ -6,7 +9,7 @@ from pyramid.tweens import EXCVIEW import opentelemetry.instrumentation.wsgi as otel_wsgi -from opentelemetry import configuration, context, propagators, trace +from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.pyramid.version import __version__ from opentelemetry.util import time_ns @@ -22,7 +25,30 @@ _logger = getLogger(__name__) -_excluded_urls = configuration.Configuration()._excluded_urls("pyramid") +class _ExcludeList: + """Class to exclude certain paths (given as a list of regexes) from tracing requests""" + + def __init__(self, excluded_urls): + self._excluded_urls = excluded_urls + if self._excluded_urls: + self._regex = re_compile("|".join(excluded_urls)) + + def url_disabled(self, url: str) -> bool: + return bool(self._excluded_urls and search(self._regex, url)) + + +def _get_excluded_urls(): + excluded_urls = environ.get("OTEL_PYTHON_PYRAMID_EXCLUDED_URLS", []) + + if excluded_urls: + excluded_urls = [ + excluded_url.strip() for excluded_url in excluded_urls.split(",") + ] + + return _ExcludeList(excluded_urls) + + +_excluded_urls = _get_excluded_urls() def includeme(config): @@ -44,10 +70,10 @@ def _insert_tween(config): def _before_traversal(event): request = event.request - environ = request.environ - span_name = otel_wsgi.get_default_span_name(environ) + request_environ = request.environ + span_name = otel_wsgi.get_default_span_name(request_environ) - enabled = environ.get(_ENVIRON_ENABLED_KEY) + enabled = request_environ.get(_ENVIRON_ENABLED_KEY) if enabled is None: _logger.warning( "Opentelemetry pyramid tween 'opentelemetry.instrumentation.pyramid.trace_tween_factory'" @@ -60,24 +86,24 @@ def _before_traversal(event): # Tracing not enabled, return return - start_time = environ.get(_ENVIRON_STARTTIME_KEY) + start_time = request_environ.get(_ENVIRON_STARTTIME_KEY) token = context.attach( - propagators.extract(otel_wsgi.carrier_getter, environ) + propagators.extract(otel_wsgi.carrier_getter, request_environ) ) tracer = trace.get_tracer(__name__, __version__) if request.matched_route: span_name = request.matched_route.pattern else: - span_name = otel_wsgi.get_default_span_name(environ) + span_name = otel_wsgi.get_default_span_name(request_environ) span = tracer.start_span( span_name, kind=trace.SpanKind.SERVER, start_time=start_time, ) if span.is_recording(): - attributes = otel_wsgi.collect_request_attributes(environ) + attributes = otel_wsgi.collect_request_attributes(request_environ) if request.matched_route: attributes["http.route"] = request.matched_route.pattern for key, value in attributes.items(): @@ -85,9 +111,9 @@ def _before_traversal(event): activation = tracer.use_span(span, end_on_exit=True) activation.__enter__() - environ[_ENVIRON_ACTIVATION_KEY] = activation - environ[_ENVIRON_SPAN_KEY] = span - environ[_ENVIRON_TOKEN] = token + request_environ[_ENVIRON_ACTIVATION_KEY] = activation + request_environ[_ENVIRON_SPAN_KEY] = span + request_environ[_ENVIRON_TOKEN] = token def trace_tween_factory(handler, registry): diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/tests/pyramid_base_test.py b/instrumentation/opentelemetry-instrumentation-pyramid/tests/pyramid_base_test.py index 21a6a1ab95..70ab268c23 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/tests/pyramid_base_test.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/tests/pyramid_base_test.py @@ -17,14 +17,8 @@ from werkzeug.test import Client from werkzeug.wrappers import BaseResponse -from opentelemetry.configuration import Configuration - class InstrumentationTest: - def setUp(self): # pylint: disable=invalid-name - super().setUp() # pylint: disable=no-member - Configuration._reset() # pylint: disable=protected-access - @staticmethod def _hello_endpoint(request): helloid = int(request.matchdict["helloid"]) diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py index 2affc3f5d3..b214f69f84 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py @@ -17,8 +17,8 @@ from pyramid.config import Configurator from opentelemetry import trace -from opentelemetry.configuration import Configuration from opentelemetry.instrumentation.pyramid import PyramidInstrumentor +from opentelemetry.instrumentation.pyramid.callbacks import _get_excluded_urls from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase @@ -62,7 +62,7 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.pyramid.callbacks._excluded_urls", - Configuration()._excluded_urls("pyramid"), + _get_excluded_urls(), ) self.exclude_patch.start() diff --git a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py index 1725123b6d..cff9b2d5cc 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py @@ -11,17 +11,43 @@ # 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 typing import Optional + +from os import environ +from re import compile as re_compile +from re import search from starlette import applications from starlette.routing import Match -from opentelemetry.configuration import Configuration from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.starlette.version import __version__ # noqa -_excluded_urls = Configuration()._excluded_urls("starlette") + +class _ExcludeList: + """Class to exclude certain paths (given as a list of regexes) from tracing requests""" + + def __init__(self, excluded_urls): + self._excluded_urls = excluded_urls + if self._excluded_urls: + self._regex = re_compile("|".join(excluded_urls)) + + def url_disabled(self, url: str) -> bool: + return bool(self._excluded_urls and search(self._regex, url)) + + +def _get_excluded_urls(): + excluded_urls = environ.get("OTEL_PYTHON_STARLETTE_EXCLUDED_URLS", []) + + if excluded_urls: + excluded_urls = [ + excluded_url.strip() for excluded_url in excluded_urls.split(",") + ] + + return _ExcludeList(excluded_urls) + + +_excluded_urls = _get_excluded_urls() class StarletteInstrumentor(BaseInstrumentor): diff --git a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py index 1729741363..3df7896d12 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py @@ -21,7 +21,6 @@ from starlette.testclient import TestClient import opentelemetry.instrumentation.starlette as otel_starlette -from opentelemetry.configuration import Configuration from opentelemetry.test.test_base import TestBase @@ -33,7 +32,6 @@ def _create_app(self): def setUp(self): super().setUp() - Configuration()._reset() self.env_patch = patch.dict( "os.environ", {"OTEL_PYTHON_STARLETTE_EXCLUDED_URLS": "/exclude/123,healthzz"}, @@ -41,7 +39,7 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.starlette._excluded_urls", - Configuration()._excluded_urls("starlette"), + otel_starlette._get_excluded_urls(), ) self.exclude_patch.start() self._instrumentor = otel_starlette.StarletteInstrumentor() diff --git a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py index 5806b3664c..17c0f9e30c 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py @@ -35,18 +35,18 @@ def get(self): tornado.ioloop.IOLoop.current().start() """ -import inspect -import typing from collections import namedtuple -from functools import partial, wraps +from functools import partial from logging import getLogger +from os import environ +from re import compile as re_compile +from re import search import tornado.web import wrapt -from tornado.routing import Rule from wrapt import wrap_function_wrapper -from opentelemetry import configuration, context, propagators, trace +from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.tornado.version import __version__ from opentelemetry.instrumentation.utils import ( @@ -65,10 +65,49 @@ def get(self): _HANDLER_CONTEXT_KEY = "_otel_trace_context_key" _OTEL_PATCHED_KEY = "_otel_patched_key" -cfg = configuration.Configuration() -_excluded_urls = cfg._excluded_urls("tornado") -_traced_attrs = cfg._traced_request_attrs("tornado") +class _ExcludeList: + """Class to exclude certain paths (given as a list of regexes) from tracing requests""" + + def __init__(self, excluded_urls): + self._excluded_urls = excluded_urls + if self._excluded_urls: + self._regex = re_compile("|".join(excluded_urls)) + + def url_disabled(self, url: str) -> bool: + return bool(self._excluded_urls and search(self._regex, url)) + + +_root = r"OTEL_PYTHON_{}" + + +def _get_traced_request_attrs(): + traced_request_attrs = environ.get( + _root.format("TORNADO_TRACED_REQUEST_ATTRS"), [] + ) + + if traced_request_attrs: + traced_request_attrs = [ + traced_request_attr.strip() + for traced_request_attr in traced_request_attrs.split(",") + ] + + return traced_request_attrs + + +def _get_excluded_urls(): + excluded_urls = environ.get(_root.format("TORNADO_EXCLUDED_URLS"), []) + + if excluded_urls: + excluded_urls = [ + excluded_url.strip() for excluded_url in excluded_urls.split(",") + ] + + return _ExcludeList(excluded_urls) + + +_excluded_urls = _get_excluded_urls() +_traced_request_attrs = _get_traced_request_attrs() carrier_getter = DictGetter() @@ -186,7 +225,9 @@ def _get_attributes_from_request(request): if request.remote_ip: attrs["net.peer.ip"] = request.remote_ip - return extract_attributes_from_object(request, _traced_attrs, attrs) + return extract_attributes_from_object( + request, _traced_request_attrs, attrs + ) def _get_operation_name(handler, request): diff --git a/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py b/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py index 3bdf007717..edc67a85ad 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py @@ -18,9 +18,10 @@ from tornado.testing import AsyncHTTPTestCase from opentelemetry import trace -from opentelemetry.configuration import Configuration from opentelemetry.instrumentation.tornado import ( TornadoInstrumentor, + _get_excluded_urls, + _get_traced_request_attrs, patch_handler_class, unpatch_handler_class, ) @@ -45,7 +46,6 @@ def setUp(self): TornadoInstrumentor().instrument() super().setUp() # pylint: disable=protected-access - Configuration()._reset() self.env_patch = patch.dict( "os.environ", { @@ -56,11 +56,11 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.tornado._excluded_urls", - Configuration()._excluded_urls("tornado"), + _get_excluded_urls(), ) self.traced_patch = patch( - "opentelemetry.instrumentation.tornado._traced_attrs", - Configuration()._traced_request_attrs("tornado"), + "opentelemetry.instrumentation.tornado._traced_request_attrs", + _get_traced_request_attrs(), ) self.exclude_patch.start() self.traced_patch.start() From d5380422eb305b2a7f092d3cc8810b86fb40ad82 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 15 Jan 2021 19:32:51 -0600 Subject: [PATCH 02/11] Fix Changelog --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb9ce1ccef..38e65c98d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,8 +14,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.17b0](https://github.com/open-telemetry/opentelemetry-python-contrib/releases/tag/v0.17b0) - 2021-01-20 ### Added -- Remove Configuration - ([#285](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/285)) - `opentelemetry-instrumentation-sqlalchemy` Ensure spans have kind set to "CLIENT" ([#278](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/278)) - `opentelemetry-instrumentation-celery` Add support for Celery version 5.x @@ -50,8 +48,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#273](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/273)) ### Changed -- Remove Configuration - ([#285](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/285)) - `opentelemetry-instrumentation-asgi`, `opentelemetry-instrumentation-wsgi` Return `None` for `CarrierGetter` if key not found ([#233](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/233)) - `opentelemetry-instrumentation-grpc` Comply with updated spec, rework tests @@ -79,6 +75,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update TraceState to adhere to specs ([#276](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/276)) +### Removed +- Remove Configuration + ([#285](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/285)) + ## [0.16b1](https://github.com/open-telemetry/opentelemetry-python-contrib/releases/tag/v0.16b1) - 2020-11-26 ## [0.16b0](https://github.com/open-telemetry/opentelemetry-python-contrib/releases/tag/v0.16b0) - 2020-11-25 From fd770852f74ca412e805eb3f3162b388eb802f21 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Mon, 18 Jan 2021 09:49:33 -0600 Subject: [PATCH 03/11] Add HTTP util This moves the WSGI and ASGI instrumentations and some other functionality to a new package for HTTP-related functionality. --- .pylintrc | 1 + .../setup.cfg | 2 +- .../instrumentation/django/middleware.py | 54 +---- .../tests/test_middleware.py | 9 +- .../setup.cfg | 2 +- .../instrumentation/falcon/__init__.py | 52 +---- .../tests/test_falcon.py | 13 +- .../setup.cfg | 2 +- .../instrumentation/fastapi/__init__.py | 34 +-- .../tests/test_fastapi_instrumentation.py | 3 +- .../setup.cfg | 2 +- .../instrumentation/flask/__init__.py | 35 +-- .../tests/test_programmatic.py | 8 +- .../tests/_server.py | 3 + .../tests/test_client_interceptor.py | 4 +- .../setup.cfg | 2 +- .../instrumentation/pyramid/callbacks.py | 31 +-- .../tests/test_programmatic.py | 4 +- .../setup.cfg | 2 +- .../instrumentation/starlette/__init__.py | 34 +-- .../tests/test_starlette_instrumentation.py | 3 +- .../setup.cfg | 1 + .../instrumentation/tornado/__init__.py | 48 +---- .../tests/test_instrumentation.py | 7 +- .../LICENSE | 201 ------------------ .../MANIFEST.in | 9 - .../README.rst | 26 --- tox.ini | 27 +-- .../opentelemetry-util-http}/README.rst | 21 +- .../opentelemetry-util-http}/setup.cfg | 7 +- .../opentelemetry-util-http}/setup.py | 2 +- .../src/opentelemetry/util/http/__init__.py | 59 +++++ .../opentelemetry/util/http}/asgi/__init__.py | 5 +- .../opentelemetry/util/http}/asgi/version.py | 0 .../src/opentelemetry/util/http}/version.py | 0 .../opentelemetry/util/http}/wsgi/__init__.py | 12 +- .../opentelemetry/util/http/wsgi/version.py | 13 +- .../tests/__init__.py | 0 .../tests/asgi/__init__.py | 0 .../tests/asgi}/test_asgi_middleware.py | 2 +- .../tests/wsgi}/__init__.py | 0 .../tests/wsgi}/test_getter.py | 2 +- .../tests/wsgi}/test_wsgi_middleware.py | 2 +- 43 files changed, 160 insertions(+), 584 deletions(-) delete mode 100644 instrumentation/opentelemetry-instrumentation-wsgi/LICENSE delete mode 100644 instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in delete mode 100644 instrumentation/opentelemetry-instrumentation-wsgi/README.rst rename {instrumentation/opentelemetry-instrumentation-asgi => util/opentelemetry-util-http}/README.rst (57%) rename {instrumentation/opentelemetry-instrumentation-wsgi => util/opentelemetry-util-http}/setup.cfg (90%) rename {instrumentation/opentelemetry-instrumentation-asgi => util/opentelemetry-util-http}/setup.py (91%) create mode 100644 util/opentelemetry-util-http/src/opentelemetry/util/http/__init__.py rename {instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation => util/opentelemetry-util-http/src/opentelemetry/util/http}/asgi/__init__.py (97%) rename {instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation => util/opentelemetry-util-http/src/opentelemetry/util/http}/asgi/version.py (100%) rename {instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi => util/opentelemetry-util-http/src/opentelemetry/util/http}/version.py (100%) rename {instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation => util/opentelemetry-util-http/src/opentelemetry/util/http}/wsgi/__init__.py (95%) rename instrumentation/opentelemetry-instrumentation-wsgi/setup.py => util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/version.py (64%) rename {instrumentation/opentelemetry-instrumentation-asgi => util/opentelemetry-util-http}/tests/__init__.py (100%) create mode 100644 util/opentelemetry-util-http/tests/asgi/__init__.py rename {instrumentation/opentelemetry-instrumentation-asgi/tests => util/opentelemetry-util-http/tests/asgi}/test_asgi_middleware.py (99%) rename {instrumentation/opentelemetry-instrumentation-wsgi/tests => util/opentelemetry-util-http/tests/wsgi}/__init__.py (100%) rename {instrumentation/opentelemetry-instrumentation-wsgi/tests => util/opentelemetry-util-http/tests/wsgi}/test_getter.py (94%) rename {instrumentation/opentelemetry-instrumentation-wsgi/tests => util/opentelemetry-util-http/tests/wsgi}/test_wsgi_middleware.py (99%) diff --git a/.pylintrc b/.pylintrc index 2a2ad87040..22720cf232 100644 --- a/.pylintrc +++ b/.pylintrc @@ -79,6 +79,7 @@ disable=missing-docstring, super-init-not-called, # temp-pylint-upgrade invalid-overridden-method, # temp-pylint-upgrade missing-module-docstring, # temp-pylint-upgrade + import-error, # needed as a workaround as reported here: https://github.com/open-telemetry/opentelemetry-python-contrib/issues/290 # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/instrumentation/opentelemetry-instrumentation-django/setup.cfg b/instrumentation/opentelemetry-instrumentation-django/setup.cfg index 6bb8d05ede..33f41f88c9 100644 --- a/instrumentation/opentelemetry-instrumentation-django/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-django/setup.cfg @@ -40,7 +40,7 @@ package_dir= packages=find_namespace: install_requires = django >= 1.10 - opentelemetry-instrumentation-wsgi == 0.18.dev0 + opentelemetry-util-http == 0.18.dev0 opentelemetry-instrumentation == 0.18.dev0 opentelemetry-api == 0.18.dev0 diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py index 0f0eed11a4..64be5c53f0 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -13,9 +13,6 @@ # limitations under the License. from logging import getLogger -from os import environ -from re import compile as re_compile -from re import search from time import time from django.conf import settings @@ -23,13 +20,14 @@ from opentelemetry.context import attach, detach from opentelemetry.instrumentation.django.version import __version__ from opentelemetry.instrumentation.utils import extract_attributes_from_object -from opentelemetry.instrumentation.wsgi import ( +from opentelemetry.propagators import extract +from opentelemetry.trace import SpanKind, get_tracer +from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs +from opentelemetry.util.http.wsgi import ( add_response_attributes, carrier_getter, collect_request_attributes, ) -from opentelemetry.propagators import extract -from opentelemetry.trace import SpanKind, get_tracer try: from django.core.urlresolvers import ( # pylint: disable=no-name-in-module @@ -53,46 +51,6 @@ ] -class _ExcludeList: - """Class to exclude certain paths (given as a list of regexes) from tracing requests""" - - def __init__(self, excluded_urls): - self._excluded_urls = excluded_urls - if self._excluded_urls: - self._regex = re_compile("|".join(excluded_urls)) - - def url_disabled(self, url: str) -> bool: - return bool(self._excluded_urls and search(self._regex, url)) - - -_root = r"OTEL_PYTHON_{}" - - -def _get_traced_request_attrs(): - traced_request_attrs = environ.get( - _root.format("DJANGO_TRACED_REQUEST_ATTRS"), [] - ) - - if traced_request_attrs: - traced_request_attrs = [ - traced_request_attr.strip() - for traced_request_attr in traced_request_attrs.split(",") - ] - - return traced_request_attrs - - -def _get_excluded_urls(): - excluded_urls = environ.get(_root.format("DJANGO_EXCLUDED_URLS"), []) - - if excluded_urls: - excluded_urls = [ - excluded_url.strip() for excluded_url in excluded_urls.split(",") - ] - - return _ExcludeList(excluded_urls) - - class _DjangoMiddleware(MiddlewareMixin): """Django Middleware for OpenTelemetry""" @@ -103,8 +61,8 @@ class _DjangoMiddleware(MiddlewareMixin): _environ_span_key = "opentelemetry-instrumentor-django.span_key" _environ_exception_key = "opentelemetry-instrumentor-django.exception_key" - _traced_request_attrs = _get_traced_request_attrs() - _excluded_urls = _get_excluded_urls() + _traced_request_attrs = get_traced_request_attrs("DJANGO") + _excluded_urls = get_excluded_urls("DJANGO") @staticmethod def _get_span_name(request): diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py index fe3f25255c..21cbf53346 100644 --- a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py @@ -22,15 +22,12 @@ from django.test.utils import setup_test_environment, teardown_test_environment from opentelemetry.instrumentation.django import DjangoInstrumentor -from opentelemetry.instrumentation.django.middleware import ( - _get_excluded_urls, - _get_traced_request_attrs, -) from opentelemetry.sdk.util import get_dict_as_key from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase from opentelemetry.trace import SpanKind from opentelemetry.trace.status import StatusCode +from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs # pylint: disable=import-error from .views import ( @@ -77,11 +74,11 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.django.middleware._DjangoMiddleware._excluded_urls", - _get_excluded_urls(), + get_excluded_urls("DJANGO"), ) self.traced_patch = patch( "opentelemetry.instrumentation.django.middleware._DjangoMiddleware._traced_request_attrs", - _get_traced_request_attrs(), + get_traced_request_attrs("DJANGO"), ) self.exclude_patch.start() self.traced_patch.start() diff --git a/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg b/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg index bbc9268b9b..ceb07f7f4e 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg @@ -41,7 +41,7 @@ package_dir= packages=find_namespace: install_requires = falcon ~= 2.0 - opentelemetry-instrumentation-wsgi == 0.18.dev0 + opentelemetry-util-http == 0.18.dev0 opentelemetry-instrumentation == 0.18.dev0 opentelemetry-api == 0.18.dev0 diff --git a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py index a3ffb0d5fa..51ecf0d645 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py @@ -14,7 +14,7 @@ """ This library builds on the OpenTelemetry WSGI middleware to track web requests -in Falcon applications. In addition to opentelemetry-instrumentation-wsgi, +in Falcon applications. In addition to opentelemetry-util-http, it supports falcon-specific features such as: * The Falcon resource and method name is used as the Span name. @@ -44,14 +44,11 @@ def on_get(self, req, resp): """ from logging import getLogger -from os import environ -from re import compile as re_compile -from re import search from sys import exc_info import falcon -import opentelemetry.instrumentation.wsgi as otel_wsgi +import opentelemetry.util.http.wsgi as otel_wsgi from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.falcon.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor @@ -61,6 +58,7 @@ def on_get(self, req, resp): ) from opentelemetry.trace.status import Status from opentelemetry.util import time_ns +from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs _logger = getLogger(__name__) @@ -71,48 +69,8 @@ def on_get(self, req, resp): _ENVIRON_EXC = "opentelemetry-falcon.exc" -class _ExcludeList: - """Class to exclude certain paths (given as a list of regexes) from tracing requests""" - - def __init__(self, excluded_urls): - self._excluded_urls = excluded_urls - if self._excluded_urls: - self._regex = re_compile("|".join(excluded_urls)) - - def url_disabled(self, url: str) -> bool: - return bool(self._excluded_urls and search(self._regex, url)) - - -_root = r"OTEL_PYTHON_{}" - - -def _get_traced_request_attrs(): - traced_request_attrs = environ.get( - _root.format("FALCON_TRACED_REQUEST_ATTRS"), [] - ) - - if traced_request_attrs: - traced_request_attrs = [ - traced_request_attr.strip() - for traced_request_attr in traced_request_attrs.split(",") - ] - - return traced_request_attrs - - -def _get_excluded_urls(): - excluded_urls = environ.get(_root.format("FALCON_EXCLUDED_URLS"), []) - - if excluded_urls: - excluded_urls = [ - excluded_url.strip() for excluded_url in excluded_urls.split(",") - ] - - return _ExcludeList(excluded_urls) - - -_excluded_urls = _get_excluded_urls() -_traced_request_attrs = _get_traced_request_attrs() +_excluded_urls = get_excluded_urls("FALCON") +_traced_request_attrs = get_traced_request_attrs("FALCON") class FalconInstrumentor(BaseInstrumentor): diff --git a/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py b/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py index 0fcc9a589b..b39b20ac38 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py @@ -16,13 +16,10 @@ from falcon import testing -from opentelemetry.instrumentation.falcon import ( - FalconInstrumentor, - _get_excluded_urls, - _get_traced_request_attrs, -) +from opentelemetry.instrumentation.falcon import FalconInstrumentor from opentelemetry.test.test_base import TestBase from opentelemetry.trace.status import StatusCode +from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs from .app import make_app @@ -43,13 +40,15 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.falcon._excluded_urls", - _get_excluded_urls(), + get_excluded_urls("FALCON"), ) middleware = self.app._middleware[0][ # pylint:disable=W0212 0 ].__self__ self.traced_patch = patch.object( - middleware, "_traced_request_attrs", _get_traced_request_attrs(), + middleware, + "_traced_request_attrs", + get_traced_request_attrs("FALCON"), ) self.exclude_patch.start() self.traced_patch.start() diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg b/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg index 6828ea1af4..7e83ba60a1 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg @@ -39,7 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 0.18.dev0 - opentelemetry-instrumentation-asgi == 0.18.dev0 + opentelemetry-util-http == 0.18.dev0 [options.entry_points] opentelemetry_instrumentor = diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py index ad3e3eae6c..7c6429ba32 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py @@ -12,42 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -from os import environ -from re import compile as re_compile -from re import search - import fastapi from starlette.routing import Match -from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware -from opentelemetry.instrumentation.fastapi.version import __version__ # noqa from opentelemetry.instrumentation.instrumentor import BaseInstrumentor +from opentelemetry.util.http import get_excluded_urls +from opentelemetry.util.http.asgi import OpenTelemetryMiddleware - -class _ExcludeList: - """Class to exclude certain paths (given as a list of regexes) from tracing requests""" - - def __init__(self, excluded_urls): - self._excluded_urls = excluded_urls - if self._excluded_urls: - self._regex = re_compile("|".join(excluded_urls)) - - def url_disabled(self, url: str) -> bool: - return bool(self._excluded_urls and search(self._regex, url)) - - -def _get_excluded_urls(): - excluded_urls = environ.get("OTEL_PYTHON_FASTAPI_EXCLUDED_URLS", []) - - if excluded_urls: - excluded_urls = [ - excluded_url.strip() for excluded_url in excluded_urls.split(",") - ] - - return _ExcludeList(excluded_urls) - - -_excluded_urls = _get_excluded_urls() +_excluded_urls = get_excluded_urls("FASTAPI") class FastAPIInstrumentor(BaseInstrumentor): diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py index 13d90e410f..fe6c27928a 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py @@ -20,6 +20,7 @@ import opentelemetry.instrumentation.fastapi as otel_fastapi from opentelemetry.test.test_base import TestBase +from opentelemetry.util.http import get_excluded_urls class TestFastAPIManualInstrumentation(TestBase): @@ -37,7 +38,7 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.fastapi._excluded_urls", - otel_fastapi._get_excluded_urls(), + get_excluded_urls("FASTAPI"), ) self.exclude_patch.start() self._instrumentor = otel_fastapi.FastAPIInstrumentor() diff --git a/instrumentation/opentelemetry-instrumentation-flask/setup.cfg b/instrumentation/opentelemetry-instrumentation-flask/setup.cfg index bf98fb7880..f99dbe81fb 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-flask/setup.cfg @@ -40,7 +40,7 @@ package_dir= packages=find_namespace: install_requires = flask ~= 1.0 - opentelemetry-instrumentation-wsgi == 0.18.dev0 + opentelemetry-util-http == 0.18.dev0 opentelemetry-instrumentation == 0.18.dev0 opentelemetry-api == 0.18.dev0 diff --git a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py index e0ced69599..1f8adb3d00 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -17,8 +17,8 @@ """ This library builds on the OpenTelemetry WSGI middleware to track web requests -in Flask applications. In addition to opentelemetry-instrumentation-wsgi, it supports -flask-specific features such as: +in Flask applications. In addition to opentelemetry-util-http, it +supports Flask-specific features such as: * The Flask url rule pattern is used as the Span name. * The ``http.route`` Span attribute is set so that one can see which URL rule @@ -48,17 +48,15 @@ def hello(): """ from logging import getLogger -from os import environ -from re import compile as re_compile -from re import search import flask -import opentelemetry.instrumentation.wsgi as otel_wsgi +import opentelemetry.util.http.wsgi as otel_wsgi from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.flask.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.util import time_ns +from opentelemetry.util.http import get_excluded_urls _logger = getLogger(__name__) @@ -68,30 +66,7 @@ def hello(): _ENVIRON_TOKEN = "opentelemetry-flask.token" -class _ExcludeList: - """Class to exclude certain paths (given as a list of regexes) from tracing requests""" - - def __init__(self, excluded_urls): - self._excluded_urls = excluded_urls - if self._excluded_urls: - self._regex = re_compile("|".join(excluded_urls)) - - def url_disabled(self, url: str) -> bool: - return bool(self._excluded_urls and search(self._regex, url)) - - -def _get_excluded_urls(): - excluded_urls = environ.get("OTEL_PYTHON_FLASK_EXCLUDED_URLS", []) - - if excluded_urls: - excluded_urls = [ - excluded_url.strip() for excluded_url in excluded_urls.split(",") - ] - - return _ExcludeList(excluded_urls) - - -_excluded_urls = _get_excluded_urls() +_excluded_urls = get_excluded_urls("FLASK") def get_default_span_name(): diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index c2278d7de7..0e9ead6f50 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -17,12 +17,10 @@ from flask import Flask, request from opentelemetry import trace -from opentelemetry.instrumentation.flask import ( - FlaskInstrumentor, - _get_excluded_urls, -) +from opentelemetry.instrumentation.flask import FlaskInstrumentor from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase +from opentelemetry.util.http import get_excluded_urls # pylint: disable=import-error from .base_test import InstrumentationTest @@ -64,7 +62,7 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.flask._excluded_urls", - _get_excluded_urls(), + get_excluded_urls("FLASK"), ) self.exclude_patch.start() diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/_server.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/_server.py index a4e1c266b8..1f4f205417 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/tests/_server.py +++ b/instrumentation/opentelemetry-instrumentation-grpc/tests/_server.py @@ -22,6 +22,9 @@ class TestServer(test_server_pb2_grpc.GRPCTestServerServicer): + # pylint: disable=invalid-name + # pylint: disable=no-self-use + def SimpleMethod(self, request, context): if request.request_data == "error": context.set_code(grpc.StatusCode.INVALID_ARGUMENT) diff --git a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py index 0eaeebbc23..f272a90240 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py +++ b/instrumentation/opentelemetry-instrumentation-grpc/tests/test_client_interceptor.py @@ -13,7 +13,9 @@ # limitations under the License. import grpc -from tests.protobuf import test_server_pb2_grpc +from tests.protobuf import ( # pylint: disable=no-name-in-module + test_server_pb2_grpc, +) import opentelemetry.instrumentation.grpc from opentelemetry import trace diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg b/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg index b449fb34f5..240ebf8054 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg @@ -42,7 +42,7 @@ install_requires = pyramid >= 1.7 opentelemetry-instrumentation == 0.18.dev0 opentelemetry-api == 0.18.dev0 - opentelemetry-instrumentation-wsgi == 0.18.dev0 + opentelemetry-util-http == 0.18.dev0 wrapt >= 1.0.0, < 2.0.0 [options.extras_require] diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py index dd6a26755b..0aa8a02371 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py @@ -1,17 +1,15 @@ from logging import getLogger -from os import environ -from re import compile as re_compile -from re import search from pyramid.events import BeforeTraversal from pyramid.httpexceptions import HTTPException from pyramid.settings import asbool from pyramid.tweens import EXCVIEW -import opentelemetry.instrumentation.wsgi as otel_wsgi +import opentelemetry.util.http.wsgi as otel_wsgi from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.pyramid.version import __version__ from opentelemetry.util import time_ns +from opentelemetry.util.http import get_excluded_urls TWEEN_NAME = "opentelemetry.instrumentation.pyramid.trace_tween_factory" SETTING_TRACE_ENABLED = "opentelemetry-pyramid.trace_enabled" @@ -25,30 +23,7 @@ _logger = getLogger(__name__) -class _ExcludeList: - """Class to exclude certain paths (given as a list of regexes) from tracing requests""" - - def __init__(self, excluded_urls): - self._excluded_urls = excluded_urls - if self._excluded_urls: - self._regex = re_compile("|".join(excluded_urls)) - - def url_disabled(self, url: str) -> bool: - return bool(self._excluded_urls and search(self._regex, url)) - - -def _get_excluded_urls(): - excluded_urls = environ.get("OTEL_PYTHON_PYRAMID_EXCLUDED_URLS", []) - - if excluded_urls: - excluded_urls = [ - excluded_url.strip() for excluded_url in excluded_urls.split(",") - ] - - return _ExcludeList(excluded_urls) - - -_excluded_urls = _get_excluded_urls() +_excluded_urls = get_excluded_urls("PYRAMID") def includeme(config): diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py index b214f69f84..9d037be37e 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_programmatic.py @@ -18,9 +18,9 @@ from opentelemetry import trace from opentelemetry.instrumentation.pyramid import PyramidInstrumentor -from opentelemetry.instrumentation.pyramid.callbacks import _get_excluded_urls from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase +from opentelemetry.util.http import get_excluded_urls # pylint: disable=import-error from .pyramid_base_test import InstrumentationTest @@ -62,7 +62,7 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.pyramid.callbacks._excluded_urls", - _get_excluded_urls(), + get_excluded_urls("PYRAMID"), ) self.exclude_patch.start() diff --git a/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg b/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg index 4b2123d9b7..4977126ce9 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg @@ -39,7 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 0.18.dev0 - opentelemetry-instrumentation-asgi == 0.18.dev0 + opentelemetry-util-http == 0.18.dev0 [options.entry_points] opentelemetry_instrumentor = diff --git a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py index cff9b2d5cc..f222225e76 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py @@ -12,42 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -from os import environ -from re import compile as re_compile -from re import search - from starlette import applications from starlette.routing import Match -from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware from opentelemetry.instrumentation.instrumentor import BaseInstrumentor -from opentelemetry.instrumentation.starlette.version import __version__ # noqa - - -class _ExcludeList: - """Class to exclude certain paths (given as a list of regexes) from tracing requests""" - - def __init__(self, excluded_urls): - self._excluded_urls = excluded_urls - if self._excluded_urls: - self._regex = re_compile("|".join(excluded_urls)) - - def url_disabled(self, url: str) -> bool: - return bool(self._excluded_urls and search(self._regex, url)) - - -def _get_excluded_urls(): - excluded_urls = environ.get("OTEL_PYTHON_STARLETTE_EXCLUDED_URLS", []) - - if excluded_urls: - excluded_urls = [ - excluded_url.strip() for excluded_url in excluded_urls.split(",") - ] - - return _ExcludeList(excluded_urls) - +from opentelemetry.util.http import get_excluded_urls +from opentelemetry.util.http.asgi import OpenTelemetryMiddleware -_excluded_urls = _get_excluded_urls() +_excluded_urls = get_excluded_urls("STARLETTE") class StarletteInstrumentor(BaseInstrumentor): diff --git a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py index 3df7896d12..56116c5a06 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py @@ -22,6 +22,7 @@ import opentelemetry.instrumentation.starlette as otel_starlette from opentelemetry.test.test_base import TestBase +from opentelemetry.util.http import get_excluded_urls class TestStarletteManualInstrumentation(TestBase): @@ -39,7 +40,7 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.starlette._excluded_urls", - otel_starlette._get_excluded_urls(), + get_excluded_urls("STARLETTE"), ) self.exclude_patch.start() self._instrumentor = otel_starlette.StarletteInstrumentor() diff --git a/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg b/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg index 035572e32f..69b32a3e3f 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-tornado/setup.cfg @@ -41,6 +41,7 @@ install_requires = tornado >= 6.0 opentelemetry-instrumentation == 0.18.dev0 opentelemetry-api == 0.18.dev0 + opentelemetry-util-http == 0.18.dev0 [options.extras_require] test = diff --git a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py index 17c0f9e30c..f030c65801 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py @@ -38,9 +38,6 @@ def get(self): from collections import namedtuple from functools import partial from logging import getLogger -from os import environ -from re import compile as re_compile -from re import search import tornado.web import wrapt @@ -57,6 +54,7 @@ def get(self): from opentelemetry.trace.propagation.textmap import DictGetter from opentelemetry.trace.status import Status from opentelemetry.util import time_ns +from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs from .client import fetch_async # pylint: disable=E0401 @@ -66,48 +64,8 @@ def get(self): _OTEL_PATCHED_KEY = "_otel_patched_key" -class _ExcludeList: - """Class to exclude certain paths (given as a list of regexes) from tracing requests""" - - def __init__(self, excluded_urls): - self._excluded_urls = excluded_urls - if self._excluded_urls: - self._regex = re_compile("|".join(excluded_urls)) - - def url_disabled(self, url: str) -> bool: - return bool(self._excluded_urls and search(self._regex, url)) - - -_root = r"OTEL_PYTHON_{}" - - -def _get_traced_request_attrs(): - traced_request_attrs = environ.get( - _root.format("TORNADO_TRACED_REQUEST_ATTRS"), [] - ) - - if traced_request_attrs: - traced_request_attrs = [ - traced_request_attr.strip() - for traced_request_attr in traced_request_attrs.split(",") - ] - - return traced_request_attrs - - -def _get_excluded_urls(): - excluded_urls = environ.get(_root.format("TORNADO_EXCLUDED_URLS"), []) - - if excluded_urls: - excluded_urls = [ - excluded_url.strip() for excluded_url in excluded_urls.split(",") - ] - - return _ExcludeList(excluded_urls) - - -_excluded_urls = _get_excluded_urls() -_traced_request_attrs = _get_traced_request_attrs() +_excluded_urls = get_excluded_urls("TORNADO") +_traced_request_attrs = get_traced_request_attrs("TORNADO") carrier_getter = DictGetter() diff --git a/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py b/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py index edc67a85ad..6d2c04f89f 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-tornado/tests/test_instrumentation.py @@ -20,13 +20,12 @@ from opentelemetry import trace from opentelemetry.instrumentation.tornado import ( TornadoInstrumentor, - _get_excluded_urls, - _get_traced_request_attrs, patch_handler_class, unpatch_handler_class, ) from opentelemetry.test.test_base import TestBase from opentelemetry.trace import SpanKind +from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs from .tornado_test_app import ( AsyncHandler, @@ -56,11 +55,11 @@ def setUp(self): self.env_patch.start() self.exclude_patch = patch( "opentelemetry.instrumentation.tornado._excluded_urls", - _get_excluded_urls(), + get_excluded_urls("TORNADO"), ) self.traced_patch = patch( "opentelemetry.instrumentation.tornado._traced_request_attrs", - _get_traced_request_attrs(), + get_traced_request_attrs("TORNADO"), ) self.exclude_patch.start() self.traced_patch.start() diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/LICENSE b/instrumentation/opentelemetry-instrumentation-wsgi/LICENSE deleted file mode 100644 index 261eeb9e9f..0000000000 --- a/instrumentation/opentelemetry-instrumentation-wsgi/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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/instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in deleted file mode 100644 index aed3e33273..0000000000 --- a/instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -graft src -graft tests -global-exclude *.pyc -global-exclude *.pyo -global-exclude __pycache__/* -include CHANGELOG.md -include MANIFEST.in -include README.rst -include LICENSE diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/README.rst b/instrumentation/opentelemetry-instrumentation-wsgi/README.rst deleted file mode 100644 index c3f06bfedb..0000000000 --- a/instrumentation/opentelemetry-instrumentation-wsgi/README.rst +++ /dev/null @@ -1,26 +0,0 @@ -OpenTelemetry WSGI Middleware -============================= - -|pypi| - -.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-wsgi.svg - :target: https://pypi.org/project/opentelemetry-instrumentation-wsgi/ - - -This library provides a WSGI middleware that can be used on any WSGI framework -(such as Django / Flask) to track requests timing through OpenTelemetry. - -Installation ------------- - -:: - - pip install opentelemetry-instrumentation-wsgi - - -References ----------- - -* `OpenTelemetry WSGI Middleware `_ -* `OpenTelemetry Project `_ -* `WSGI `_ diff --git a/tox.ini b/tox.ini index 87462e4c87..6e0a483d49 100644 --- a/tox.ini +++ b/tox.ini @@ -94,10 +94,6 @@ envlist = py3{5,6,7,8}-test-instrumentation-pyramid pypy3-test-instrumentation-pyramid - ; opentelemetry-instrumentation-asgi - py3{5,6,7,8}-test-instrumentation-asgi - pypy3-test-instrumentation-asgi - ; opentelemetry-instrumentation-asyncpg py3{5,6,7,8}-test-instrumentation-asyncpg ; ext-asyncpg intentionally excluded from pypy3 @@ -106,10 +102,6 @@ envlist = py3{5,6,7,8}-test-instrumentation-sqlite3 pypy3-test-instrumentation-sqlite3 - ; opentelemetry-instrumentation-wsgi - py3{5,6,7,8}-test-instrumentation-wsgi - pypy3-test-instrumentation-wsgi - ; opentelemetry-instrumentation-grpc py3{5,6,7,8}-test-instrumentation-grpc @@ -138,6 +130,10 @@ envlist = py3{5,6,7,8}-test-instrumentation-tornado pypy3-test-instrumentation-tornado + ; opentelemetry-util-http + py3{5,6,7,8}-test-util-http + pypy3-test-util-http + lint docker-tests docs @@ -164,7 +160,6 @@ deps = changedir = test-instrumentation-aiohttp-client: instrumentation/opentelemetry-instrumentation-aiohttp-client/tests test-instrumentation-aiopg: instrumentation/opentelemetry-instrumentation-aiopg/tests - test-instrumentation-asgi: instrumentation/opentelemetry-instrumentation-asgi/tests test-instrumentation-asyncpg: instrumentation/opentelemetry-instrumentation-asyncpg/tests test-instrumentation-boto: instrumentation/opentelemetry-instrumentation-boto/tests test-instrumentation-botocore: instrumentation/opentelemetry-instrumentation-botocore/tests @@ -192,7 +187,7 @@ changedir = test-instrumentation-starlette: instrumentation/opentelemetry-instrumentation-starlette/tests test-instrumentation-system-metrics: instrumentation/opentelemetry-instrumentation-system-metrics/tests test-instrumentation-tornado: instrumentation/opentelemetry-instrumentation-tornado/tests - test-instrumentation-wsgi: instrumentation/opentelemetry-instrumentation-wsgi/tests + test-util-http: util/opentelemetry-util-http/tests test-sdkextension-aws: sdk-extension/opentelemetry-sdk-extension-aws/tests test-exporter-datadog: exporter/opentelemetry-exporter-datadog/tests @@ -211,8 +206,7 @@ commands_pre = grpc: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-grpc[test] - wsgi,falcon,flask,django,pyramid: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-wsgi - asgi,starlette,fastapi: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-asgi + falcon,flask,django,pyramid,starlette,fastapi,tornado: pip install {toxinidir}/util/opentelemetry-util-http asyncpg: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-asyncpg @@ -234,7 +228,6 @@ commands_pre = fastapi: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-fastapi[test] mysql: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi {toxinidir}/instrumentation/opentelemetry-instrumentation-mysql[test] - pymemcache: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymemcache[test] pymongo: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymongo[test] @@ -271,10 +264,11 @@ commands_pre = elasticsearch{2,5,6,7}: pip install {toxinidir}/opentelemetry-python-core/opentelemetry-instrumentation {toxinidir}/instrumentation/opentelemetry-instrumentation-elasticsearch[test] - aws: pip install requests {toxinidir}/sdk-extension/opentelemetry-sdk-extension-aws -; In order to get a healthy coverage report, + http: pip install {toxinidir}/util/opentelemetry-util-http + +; In order to get a health coverage report, ; we have to install packages in editable mode. coverage: python {toxinidir}/scripts/eachdist.py install --editable @@ -314,9 +308,8 @@ commands_pre = python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-instrumentation 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}/instrumentation/opentelemetry-instrumentation-wsgi[test] + python -m pip install {toxinidir}/util/opentelemetry-util-http python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi[test] - python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-asgi[test] python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-botocore[test] python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-django[test] python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-starlette[test] diff --git a/instrumentation/opentelemetry-instrumentation-asgi/README.rst b/util/opentelemetry-util-http/README.rst similarity index 57% rename from instrumentation/opentelemetry-instrumentation-asgi/README.rst rename to util/opentelemetry-util-http/README.rst index 3eb8e2dda7..3ec70435d9 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/README.rst +++ b/util/opentelemetry-util-http/README.rst @@ -1,21 +1,22 @@ -OpenTelemetry ASGI Instrumentation -================================== +OpenTelemetry Util HTTP +======================= |pypi| -.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-asgi.svg - :target: https://pypi.org/project/opentelemetry-instrumentation-asgi/ +.. |pypi| image:: https://badge.fury.io/py/opentelemetry-util-http.svg + :target: https://pypi.org/project/opentelemetry-util-http/ -This library provides a ASGI middleware that can be used on any ASGI framework -(such as Django, Starlette, FastAPI or Quart) to track requests timing through OpenTelemetry. +This library provides ASGI, WSGI middleware and other HTTP-related +functionality that is common to instrumented web frameworks (such as Django, +Starlette, FastAPI, etc.) to track requests timing through OpenTelemetry. Installation ------------ :: - pip install opentelemetry-instrumentation-asgi + pip install opentelemetry-util-http Usage (Quart) @@ -24,7 +25,7 @@ Usage (Quart) .. code-block:: python from quart import Quart - from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware + from opentelemetry.util.http.asgi import OpenTelemetryMiddleware app = Quart(__name__) app.asgi_app = OpenTelemetryMiddleware(app.asgi_app) @@ -46,7 +47,7 @@ Modify the application's ``asgi.py`` file as shown below. import os from django.core.asgi import get_asgi_application - from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware + from opentelemetry.util.http.asgi import OpenTelemetryMiddleware os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'asgi_example.settings') @@ -59,7 +60,7 @@ Usage (Raw ASGI) .. code-block:: python - from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware + from opentelemetry.util.http.asgi import OpenTelemetryMiddleware app = ... # An ASGI application. app = OpenTelemetryMiddleware(app) diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg b/util/opentelemetry-util-http/setup.cfg similarity index 90% rename from instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg rename to util/opentelemetry-util-http/setup.cfg index 8085f59187..e304fea9d8 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg +++ b/util/opentelemetry-util-http/setup.cfg @@ -13,13 +13,13 @@ # limitations under the License. # [metadata] -name = opentelemetry-instrumentation-wsgi -description = WSGI Middleware for OpenTelemetry +name = opentelemetry-util-http +description = Web util for OpenTelemetry long_description = file: README.rst long_description_content_type = text/x-rst author = OpenTelemetry Authors author_email = cncf-opentelemetry-contributors@lists.cncf.io -url = https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-wsgi +url = https://github.com/open-telemetry/opentelemetry-python-contrib/util/opentelemetry-util-http platforms = any license = Apache-2.0 classifiers = @@ -41,6 +41,7 @@ packages=find_namespace: install_requires = opentelemetry-api == 0.18.dev0 opentelemetry-instrumentation == 0.18.dev0 + asgiref ~= 3.0 [options.extras_require] test = diff --git a/instrumentation/opentelemetry-instrumentation-asgi/setup.py b/util/opentelemetry-util-http/setup.py similarity index 91% rename from instrumentation/opentelemetry-instrumentation-asgi/setup.py rename to util/opentelemetry-util-http/setup.py index 3369352fe1..1202dd07e3 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/setup.py +++ b/util/opentelemetry-util-http/setup.py @@ -17,7 +17,7 @@ BASE_DIR = os.path.dirname(__file__) VERSION_FILENAME = os.path.join( - BASE_DIR, "src", "opentelemetry", "instrumentation", "asgi", "version.py" + BASE_DIR, "src", "opentelemetry", "util", "http", "version.py" ) PACKAGE_INFO = {} with open(VERSION_FILENAME) as f: diff --git a/util/opentelemetry-util-http/src/opentelemetry/util/http/__init__.py b/util/opentelemetry-util-http/src/opentelemetry/util/http/__init__.py new file mode 100644 index 0000000000..068511010d --- /dev/null +++ b/util/opentelemetry-util-http/src/opentelemetry/util/http/__init__.py @@ -0,0 +1,59 @@ +# Copyright The 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 os import environ +from re import compile as re_compile +from re import search + + +class ExcludeList: + """Class to exclude certain paths (given as a list of regexes) from tracing requests""" + + def __init__(self, excluded_urls): + self._excluded_urls = excluded_urls + if self._excluded_urls: + self._regex = re_compile("|".join(excluded_urls)) + + def url_disabled(self, url: str) -> bool: + return bool(self._excluded_urls and search(self._regex, url)) + + +_root = r"OTEL_PYTHON_{}" + + +def get_traced_request_attrs(instrumentation): + traced_request_attrs = environ.get( + _root.format("{}_TRACED_REQUEST_ATTRS".format(instrumentation)), [] + ) + + if traced_request_attrs: + traced_request_attrs = [ + traced_request_attr.strip() + for traced_request_attr in traced_request_attrs.split(",") + ] + + return traced_request_attrs + + +def get_excluded_urls(instrumentation): + excluded_urls = environ.get( + _root.format("{}_EXCLUDED_URLS".format(instrumentation)), [] + ) + + if excluded_urls: + excluded_urls = [ + excluded_url.strip() for excluded_url in excluded_urls.split(",") + ] + + return ExcludeList(excluded_urls) diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/__init__.py similarity index 97% rename from instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py rename to util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/__init__.py index b81b8b77f7..8959901f5e 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/__init__.py @@ -13,12 +13,11 @@ # limitations under the License. """ -The opentelemetry-instrumentation-asgi package provides an ASGI middleware that can be used +The opentelemetry-util-web package provides an ASGI middleware that can be used on any ASGI framework (such as Django-channels / Quart) to track requests timing through OpenTelemetry. """ -import operator import typing import urllib from functools import wraps @@ -27,10 +26,10 @@ from asgiref.compatibility import guarantee_single_callable from opentelemetry import context, propagators, trace -from opentelemetry.instrumentation.asgi.version import __version__ # noqa from opentelemetry.instrumentation.utils import http_status_to_status_code from opentelemetry.trace.propagation.textmap import DictGetter from opentelemetry.trace.status import Status, StatusCode +from opentelemetry.util.http.asgi.version import __version__ # noqa class CarrierGetter(DictGetter): diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/version.py b/util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/version.py similarity index 100% rename from instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/version.py rename to util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/version.py diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/version.py b/util/opentelemetry-util-http/src/opentelemetry/util/http/version.py similarity index 100% rename from instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/version.py rename to util/opentelemetry-util-http/src/opentelemetry/util/http/version.py diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py b/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/__init__.py similarity index 95% rename from instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py rename to util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/__init__.py index c336a1320b..9b7308b64d 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py +++ b/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/__init__.py @@ -21,7 +21,7 @@ .. code-block:: python from flask import Flask - from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware + from opentelemetry.util.http.wsgi import OpenTelemetryMiddleware app = Flask(__name__) app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app) @@ -42,7 +42,7 @@ def hello(): .. code-block:: python import os - from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware + from opentelemetry.util.http.wsgi import OpenTelemetryMiddleware from django.core.wsgi import get_wsgi_application os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings') @@ -60,9 +60,9 @@ def hello(): from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.utils import http_status_to_status_code -from opentelemetry.instrumentation.wsgi.version import __version__ from opentelemetry.trace.propagation.textmap import DictGetter from opentelemetry.trace.status import Status, StatusCode +from opentelemetry.util.http.wsgi.version import __version__ _HTTP_VERSION_PREFIX = "HTTP/" @@ -233,9 +233,9 @@ def __call__(self, environ, start_response): raise -# Put this in a subfunction to not delay the call to the wrapped -# WSGI application (instrumentation should change the application -# behavior as little as possible). +# FIXME Put this in a subfunction to not delay the call to the wrapped WSGI +# application (instrumentation should change the application behavior as little +# as possible). def _end_span_after_iterating(iterable, span, tracer, token): try: with tracer.use_span(span): diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/setup.py b/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/version.py similarity index 64% rename from instrumentation/opentelemetry-instrumentation-wsgi/setup.py rename to util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/version.py index fb4ffa7437..ab6ccdf1ba 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/setup.py +++ b/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/version.py @@ -11,16 +11,5 @@ # 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 os -import setuptools - -BASE_DIR = os.path.dirname(__file__) -VERSION_FILENAME = os.path.join( - BASE_DIR, "src", "opentelemetry", "instrumentation", "wsgi", "version.py" -) -PACKAGE_INFO = {} -with open(VERSION_FILENAME) as f: - exec(f.read(), PACKAGE_INFO) - -setuptools.setup(version=PACKAGE_INFO["__version__"]) +__version__ = "0.170" diff --git a/instrumentation/opentelemetry-instrumentation-asgi/tests/__init__.py b/util/opentelemetry-util-http/tests/__init__.py similarity index 100% rename from instrumentation/opentelemetry-instrumentation-asgi/tests/__init__.py rename to util/opentelemetry-util-http/tests/__init__.py diff --git a/util/opentelemetry-util-http/tests/asgi/__init__.py b/util/opentelemetry-util-http/tests/asgi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py b/util/opentelemetry-util-http/tests/asgi/test_asgi_middleware.py similarity index 99% rename from instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py rename to util/opentelemetry-util-http/tests/asgi/test_asgi_middleware.py index 7c4ae20a77..264cbf2c8c 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py +++ b/util/opentelemetry-util-http/tests/asgi/test_asgi_middleware.py @@ -16,7 +16,7 @@ import unittest import unittest.mock as mock -import opentelemetry.instrumentation.asgi as otel_asgi +import opentelemetry.util.http.asgi as otel_asgi from opentelemetry import trace as trace_api from opentelemetry.test.asgitestutil import ( AsgiTestBase, diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/tests/__init__.py b/util/opentelemetry-util-http/tests/wsgi/__init__.py similarity index 100% rename from instrumentation/opentelemetry-instrumentation-wsgi/tests/__init__.py rename to util/opentelemetry-util-http/tests/wsgi/__init__.py diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_getter.py b/util/opentelemetry-util-http/tests/wsgi/test_getter.py similarity index 94% rename from instrumentation/opentelemetry-instrumentation-wsgi/tests/test_getter.py rename to util/opentelemetry-util-http/tests/wsgi/test_getter.py index 80cf6b1ecd..937f01b629 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_getter.py +++ b/util/opentelemetry-util-http/tests/wsgi/test_getter.py @@ -14,7 +14,7 @@ from unittest import TestCase -from opentelemetry.instrumentation.wsgi import CarrierGetter +from opentelemetry.util.http.wsgi import CarrierGetter class TestCarrierGetter(TestCase): diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py b/util/opentelemetry-util-http/tests/wsgi/test_wsgi_middleware.py similarity index 99% rename from instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py rename to util/opentelemetry-util-http/tests/wsgi/test_wsgi_middleware.py index d5168e3280..b058a86727 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py +++ b/util/opentelemetry-util-http/tests/wsgi/test_wsgi_middleware.py @@ -18,7 +18,7 @@ import wsgiref.util as wsgiref_util from urllib.parse import urlsplit -import opentelemetry.instrumentation.wsgi as otel_wsgi +import opentelemetry.util.http.wsgi as otel_wsgi from opentelemetry import trace as trace_api from opentelemetry.test.wsgitestutil import WsgiTestBase from opentelemetry.trace.status import StatusCode From 8a9e37a5d1d759568421a1a16da948bffe45cdab Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 28 Jan 2021 17:47:03 -0600 Subject: [PATCH 04/11] Some fixes --- .../src/opentelemetry/util/http/asgi/__init__.py | 6 +++--- .../src/opentelemetry/util/http/wsgi/version.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/__init__.py b/util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/__init__.py index 8959901f5e..2cdb054d08 100644 --- a/util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/__init__.py +++ b/util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/__init__.py @@ -13,9 +13,9 @@ # limitations under the License. """ -The opentelemetry-util-web package provides an ASGI middleware that can be used -on any ASGI framework (such as Django-channels / Quart) to track requests -timing through OpenTelemetry. +The opentelemetry.util.http.asgi package provides an ASGI middleware that can +be used on any ASGI framework (such as Django-channels / Quart) to track +requests timing through OpenTelemetry. """ import typing diff --git a/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/version.py b/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/version.py index ab6ccdf1ba..ebb75f6c11 100644 --- a/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/version.py +++ b/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.170" +__version__ = "0.18.dev0" From e45d3f414e53f1f5290b9dc40b5c94f77cbcf17f Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 28 Jan 2021 17:55:34 -0600 Subject: [PATCH 05/11] Use environment variable from module --- .../instrumentation/django/__init__.py | 5 ++++- .../django/environment_variables.py | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/environment_variables.py diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py index c4101ef181..1834313f03 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py @@ -19,6 +19,9 @@ from opentelemetry.instrumentation.django.middleware import _DjangoMiddleware from opentelemetry.instrumentation.django.version import __version__ +from opentelemetry.instrumentation.django.environment_variables import ( + OTEL_PYTHON_DJANGO_INSTRUMENT +) from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.metric import ( HTTPMetricRecorder, @@ -43,7 +46,7 @@ def _instrument(self, **kwargs): # FIXME this is probably a pattern that will show up in the rest of the # ext. Find a better way of implementing this. - if environ.get("OTEL_PYTHON_DJANGO_INSTRUMENT") == "False": + if environ.get(OTEL_PYTHON_DJANGO_INSTRUMENT) == "False": return # This can not be solved, but is an inherent problem of this approach: diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/environment_variables.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/environment_variables.py new file mode 100644 index 0000000000..4972a62e93 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/environment_variables.py @@ -0,0 +1,15 @@ +# Copyright The 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. + +OTEL_PYTHON_DJANGO_INSTRUMENT = "OTEL_PYTHON_DJANGO_INSTRUMENT" From f005d90ed3bc75ee6eb7297f9e3a6b55a55b22aa Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 28 Jan 2021 18:11:01 -0600 Subject: [PATCH 06/11] Fix lint --- docs/instrumentation/asgi/asgi.rst | 9 --------- docs/nitpick-exceptions.ini | 1 - .../src/opentelemetry/instrumentation/django/__init__.py | 6 +++--- 3 files changed, 3 insertions(+), 13 deletions(-) delete mode 100644 docs/instrumentation/asgi/asgi.rst diff --git a/docs/instrumentation/asgi/asgi.rst b/docs/instrumentation/asgi/asgi.rst deleted file mode 100644 index b988e4de43..0000000000 --- a/docs/instrumentation/asgi/asgi.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. include:: ../../../instrumentation/opentelemetry-instrumentation-asgi/README.rst - -API ---- - -.. automodule:: opentelemetry.instrumentation.asgi - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/nitpick-exceptions.ini b/docs/nitpick-exceptions.ini index 3143b9cd75..f322eb1dd2 100644 --- a/docs/nitpick-exceptions.ini +++ b/docs/nitpick-exceptions.ini @@ -4,7 +4,6 @@ class_references= opentelemetry.trace.propagation.textmap.TextMapPropagator ; - AwsXRayFormat opentelemetry.trace.propagation.textmap.DictGetter - ; - instrumentation.asgi.CarrierGetter ; API opentelemetry.trace.propagation.textmap.Getter ; - DatadogFormat diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py index 1834313f03..f8ed60ee55 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py @@ -17,11 +17,11 @@ from django.conf import settings -from opentelemetry.instrumentation.django.middleware import _DjangoMiddleware -from opentelemetry.instrumentation.django.version import __version__ from opentelemetry.instrumentation.django.environment_variables import ( - OTEL_PYTHON_DJANGO_INSTRUMENT + OTEL_PYTHON_DJANGO_INSTRUMENT, ) +from opentelemetry.instrumentation.django.middleware import _DjangoMiddleware +from opentelemetry.instrumentation.django.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.instrumentation.metric import ( HTTPMetricRecorder, From 5f9bc0e08cfe8720ee640d2caa607792b389d833 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 29 Jan 2021 17:51:44 -0600 Subject: [PATCH 07/11] Downgrade version to clear cache and make docs tests pass --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5c42f4a4e4..b14e27b102 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -105,7 +105,7 @@ jobs: run: pip install -U tox - name: Cache tox environment # Preserves .tox directory between runs for faster installs - uses: actions/cache@v2 + uses: actions/cache@v1 with: path: .tox key: tox-cache-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} From 30149212864efb89f2476db664b58e552a971971 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 29 Jan 2021 18:08:35 -0600 Subject: [PATCH 08/11] Another try --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b14e27b102..e6db699b05 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -51,7 +51,7 @@ jobs: run: pip install -U tox-factor - name: Cache tox environment # Preserves .tox directory between runs for faster installs - uses: actions/cache@v2 + uses: actions/cache@v1 with: path: .tox key: tox-cache-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} From e6dfad1d9712b08a87f3e116f32549c379081b32 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 29 Jan 2021 18:22:07 -0600 Subject: [PATCH 09/11] Update workflow --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e6db699b05..c437b4abdc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,7 +6,7 @@ on: - 'release/*' pull_request: env: - CORE_REPO_SHA: f3ee81243b4266729ba5196a7883ce897549aaba + CORE_REPO_SHA: 09b010cfcc85e2aa07326e9204541b80a7dd52f0 jobs: build: @@ -51,7 +51,7 @@ jobs: run: pip install -U tox-factor - name: Cache tox environment # Preserves .tox directory between runs for faster installs - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: .tox key: tox-cache-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} @@ -105,7 +105,7 @@ jobs: run: pip install -U tox - name: Cache tox environment # Preserves .tox directory between runs for faster installs - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: .tox key: tox-cache-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} From 0b0705ec1627260eef9ced3e7318aaece4ef86ea Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 29 Jan 2021 19:10:08 -0600 Subject: [PATCH 10/11] Fix docs --- docs-requirements.txt | 7 ------- docs/instrumentation/wsgi/wsgi.rst | 7 ------- eachdist.ini | 3 +-- .../src/opentelemetry/exporter/datadog/exporter.py | 2 +- .../tests/test_datadog_exporter.py | 2 +- scripts/coverage.sh | 1 - tox.ini | 6 ++++++ 7 files changed, 9 insertions(+), 19 deletions(-) delete mode 100644 docs/instrumentation/wsgi/wsgi.rst diff --git a/docs-requirements.txt b/docs-requirements.txt index dc1cbc7790..472b32512a 100644 --- a/docs-requirements.txt +++ b/docs-requirements.txt @@ -2,18 +2,11 @@ sphinx~=2.4 sphinx-rtd-theme~=0.4 sphinx-autodoc-typehints~=1.10.2 -# Need to install the api/sdk in the venv for autodoc. Modifying sys.path -# doesn't work for pkg_resources. --e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-api&subdirectory=opentelemetry-api" --e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk" - # Required by opentelemetry-instrumentation fastapi~=0.58.1 psutil~=5.7.0 pymemcache~=1.3 --e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-instrumentation&subdirectory=opentelemetry-instrumentation" - # Required by conf django>=2.2 diff --git a/docs/instrumentation/wsgi/wsgi.rst b/docs/instrumentation/wsgi/wsgi.rst deleted file mode 100644 index 39ad5ffd58..0000000000 --- a/docs/instrumentation/wsgi/wsgi.rst +++ /dev/null @@ -1,7 +0,0 @@ -OpenTelemetry WSGI Instrumentation -================================== - -.. automodule:: opentelemetry.instrumentation.wsgi - :members: - :undoc-members: - :show-inheritance: diff --git a/eachdist.ini b/eachdist.ini index 49671d8e22..71e854068b 100644 --- a/eachdist.ini +++ b/eachdist.ini @@ -7,9 +7,8 @@ ignore= opentelemetry-python-core sortfirst= - instrumentation/opentelemetry-instrumentation-wsgi + util/opentelemetry-util-http instrumentation/opentelemetry-instrumentation-dbapi - instrumentation/opentelemetry-instrumentation-asgi instrumentation/opentelemetry-instrumentation-botocore instrumentation/* exporter/* diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py index 129e0d0c48..fdf443d0cd 100644 --- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py +++ b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py @@ -51,7 +51,7 @@ "opentelemetry.instrumentation.redis": DatadogSpanTypes.REDIS, "opentelemetry.instrumentation.requests": DatadogSpanTypes.HTTP, "opentelemetry.instrumentation.sqlalchemy": DatadogSpanTypes.SQL, - "opentelemetry.instrumentation.wsgi": DatadogSpanTypes.WEB, + "opentelemetry.util.http.wsgi": DatadogSpanTypes.WEB, } diff --git a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py index 4a576c5de1..40070c147e 100644 --- a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py +++ b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py @@ -334,7 +334,7 @@ def test_span_types(self): "opentelemetry.instrumentation.redis", "opentelemetry.instrumentation.requests", "opentelemetry.instrumentation.sqlalchemy", - "opentelemetry.instrumentation.wsgi", + "opentelemetry.util.http.wsgi", ] for index, instrumentation in enumerate(test_instrumentations): diff --git a/scripts/coverage.sh b/scripts/coverage.sh index 8055adb0de..15960a3108 100755 --- a/scripts/coverage.sh +++ b/scripts/coverage.sh @@ -20,7 +20,6 @@ coverage erase cov exporter/opentelemetry-exporter-datadog cov instrumentation/opentelemetry-instrumentation-flask cov instrumentation/opentelemetry-instrumentation-requests -cov instrumentation/opentelemetry-instrumentation-wsgi # aiohttp is only supported on Python 3.5+. if [ ${PYTHON_VERSION_INFO[1]} -gt 4 ]; then diff --git a/tox.ini b/tox.ini index 6e0a483d49..d9feb0801f 100644 --- a/tox.ini +++ b/tox.ini @@ -282,6 +282,12 @@ deps = -r {toxinidir}/docs-requirements.txt pytest +commands_pre = + python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-api + python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-sdk + python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-instrumentation + python -m pip install {toxinidir}/util/opentelemetry-util-http + changedir = docs commands = From 602dca3b25633c1dcd2bb883bbde7af877a3b77c Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 3 Feb 2021 23:26:17 -0600 Subject: [PATCH 11/11] Put asgi and wsgi back as instrumentations --- docs-requirements.txt | 7 + docs/instrumentation/asgi/asgi.rst | 9 + docs/instrumentation/wsgi/wsgi.rst | 7 + eachdist.ini | 2 + .../exporter/datadog/exporter.py | 2 +- .../tests/test_datadog_exporter.py | 2 +- .../README.rst | 71 +++++++ .../setup.py | 26 +++ .../instrumentation}/asgi/__init__.py | 8 +- .../instrumentation}/asgi/version.py | 0 .../tests}/__init__.py | 0 .../tests}/test_asgi_middleware.py | 2 +- .../setup.cfg | 1 + .../instrumentation/django/middleware.py | 8 +- .../setup.cfg | 1 + .../instrumentation/falcon/__init__.py | 4 +- .../setup.cfg | 1 + .../instrumentation/fastapi/__init__.py | 2 +- .../setup.cfg | 1 + .../instrumentation/flask/__init__.py | 2 +- .../setup.cfg | 1 + .../instrumentation/pyramid/callbacks.py | 2 +- .../setup.cfg | 1 + .../instrumentation/starlette/__init__.py | 2 +- .../LICENSE | 201 ++++++++++++++++++ .../MANIFEST.in | 9 + .../README.rst | 26 +++ .../setup.cfg | 50 +++++ .../setup.py | 26 +++ .../instrumentation}/wsgi/__init__.py | 12 +- .../instrumentation}/wsgi/version.py | 0 .../tests}/__init__.py | 0 .../tests}/test_getter.py | 2 +- .../tests}/test_wsgi_middleware.py | 2 +- scripts/coverage.sh | 1 + tox.ini | 19 +- util/opentelemetry-util-http/README.rst | 6 +- 37 files changed, 486 insertions(+), 30 deletions(-) create mode 100644 docs/instrumentation/asgi/asgi.rst create mode 100644 docs/instrumentation/wsgi/wsgi.rst create mode 100644 instrumentation/opentelemetry-instrumentation-asgi/README.rst create mode 100644 instrumentation/opentelemetry-instrumentation-asgi/setup.py rename {util/opentelemetry-util-http/src/opentelemetry/util/http => instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation}/asgi/__init__.py (96%) rename {util/opentelemetry-util-http/src/opentelemetry/util/http => instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation}/asgi/version.py (100%) rename {util/opentelemetry-util-http/tests/asgi => instrumentation/opentelemetry-instrumentation-asgi/tests}/__init__.py (100%) rename {util/opentelemetry-util-http/tests/asgi => instrumentation/opentelemetry-instrumentation-asgi/tests}/test_asgi_middleware.py (99%) create mode 100644 instrumentation/opentelemetry-instrumentation-wsgi/LICENSE create mode 100644 instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in create mode 100644 instrumentation/opentelemetry-instrumentation-wsgi/README.rst create mode 100644 instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg create mode 100644 instrumentation/opentelemetry-instrumentation-wsgi/setup.py rename {util/opentelemetry-util-http/src/opentelemetry/util/http => instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation}/wsgi/__init__.py (95%) rename {util/opentelemetry-util-http/src/opentelemetry/util/http => instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation}/wsgi/version.py (100%) rename {util/opentelemetry-util-http/tests/wsgi => instrumentation/opentelemetry-instrumentation-wsgi/tests}/__init__.py (100%) rename {util/opentelemetry-util-http/tests/wsgi => instrumentation/opentelemetry-instrumentation-wsgi/tests}/test_getter.py (94%) rename {util/opentelemetry-util-http/tests/wsgi => instrumentation/opentelemetry-instrumentation-wsgi/tests}/test_wsgi_middleware.py (99%) diff --git a/docs-requirements.txt b/docs-requirements.txt index 472b32512a..dc1cbc7790 100644 --- a/docs-requirements.txt +++ b/docs-requirements.txt @@ -2,11 +2,18 @@ sphinx~=2.4 sphinx-rtd-theme~=0.4 sphinx-autodoc-typehints~=1.10.2 +# Need to install the api/sdk in the venv for autodoc. Modifying sys.path +# doesn't work for pkg_resources. +-e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-api&subdirectory=opentelemetry-api" +-e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-sdk&subdirectory=opentelemetry-sdk" + # Required by opentelemetry-instrumentation fastapi~=0.58.1 psutil~=5.7.0 pymemcache~=1.3 +-e "git+https://github.com/open-telemetry/opentelemetry-python.git#egg=opentelemetry-instrumentation&subdirectory=opentelemetry-instrumentation" + # Required by conf django>=2.2 diff --git a/docs/instrumentation/asgi/asgi.rst b/docs/instrumentation/asgi/asgi.rst new file mode 100644 index 0000000000..b988e4de43 --- /dev/null +++ b/docs/instrumentation/asgi/asgi.rst @@ -0,0 +1,9 @@ +.. include:: ../../../instrumentation/opentelemetry-instrumentation-asgi/README.rst + +API +--- + +.. automodule:: opentelemetry.instrumentation.asgi + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/instrumentation/wsgi/wsgi.rst b/docs/instrumentation/wsgi/wsgi.rst new file mode 100644 index 0000000000..39ad5ffd58 --- /dev/null +++ b/docs/instrumentation/wsgi/wsgi.rst @@ -0,0 +1,7 @@ +OpenTelemetry WSGI Instrumentation +================================== + +.. automodule:: opentelemetry.instrumentation.wsgi + :members: + :undoc-members: + :show-inheritance: diff --git a/eachdist.ini b/eachdist.ini index 71e854068b..65e6fc501e 100644 --- a/eachdist.ini +++ b/eachdist.ini @@ -8,7 +8,9 @@ ignore= sortfirst= util/opentelemetry-util-http + instrumentation/opentelemetry-instrumentation-wsgi instrumentation/opentelemetry-instrumentation-dbapi + instrumentation/opentelemetry-instrumentation-asgi instrumentation/opentelemetry-instrumentation-botocore instrumentation/* exporter/* diff --git a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py index fdf443d0cd..129e0d0c48 100644 --- a/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py +++ b/exporter/opentelemetry-exporter-datadog/src/opentelemetry/exporter/datadog/exporter.py @@ -51,7 +51,7 @@ "opentelemetry.instrumentation.redis": DatadogSpanTypes.REDIS, "opentelemetry.instrumentation.requests": DatadogSpanTypes.HTTP, "opentelemetry.instrumentation.sqlalchemy": DatadogSpanTypes.SQL, - "opentelemetry.util.http.wsgi": DatadogSpanTypes.WEB, + "opentelemetry.instrumentation.wsgi": DatadogSpanTypes.WEB, } diff --git a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py index 40070c147e..4a576c5de1 100644 --- a/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py +++ b/exporter/opentelemetry-exporter-datadog/tests/test_datadog_exporter.py @@ -334,7 +334,7 @@ def test_span_types(self): "opentelemetry.instrumentation.redis", "opentelemetry.instrumentation.requests", "opentelemetry.instrumentation.sqlalchemy", - "opentelemetry.util.http.wsgi", + "opentelemetry.instrumentation.wsgi", ] for index, instrumentation in enumerate(test_instrumentations): diff --git a/instrumentation/opentelemetry-instrumentation-asgi/README.rst b/instrumentation/opentelemetry-instrumentation-asgi/README.rst new file mode 100644 index 0000000000..3eb8e2dda7 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-asgi/README.rst @@ -0,0 +1,71 @@ +OpenTelemetry ASGI Instrumentation +================================== + +|pypi| + +.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-asgi.svg + :target: https://pypi.org/project/opentelemetry-instrumentation-asgi/ + + +This library provides a ASGI middleware that can be used on any ASGI framework +(such as Django, Starlette, FastAPI or Quart) to track requests timing through OpenTelemetry. + +Installation +------------ + +:: + + pip install opentelemetry-instrumentation-asgi + + +Usage (Quart) +------------- + +.. code-block:: python + + from quart import Quart + from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware + + app = Quart(__name__) + app.asgi_app = OpenTelemetryMiddleware(app.asgi_app) + + @app.route("/") + async def hello(): + return "Hello!" + + if __name__ == "__main__": + app.run(debug=True) + + +Usage (Django 3.0) +------------------ + +Modify the application's ``asgi.py`` file as shown below. + +.. code-block:: python + + import os + from django.core.asgi import get_asgi_application + from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware + + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'asgi_example.settings') + + application = get_asgi_application() + application = OpenTelemetryMiddleware(application) + + +Usage (Raw ASGI) +---------------- + +.. code-block:: python + + from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware + + app = ... # An ASGI application. + app = OpenTelemetryMiddleware(app) + + +References +---------- + +* `OpenTelemetry Project `_ diff --git a/instrumentation/opentelemetry-instrumentation-asgi/setup.py b/instrumentation/opentelemetry-instrumentation-asgi/setup.py new file mode 100644 index 0000000000..3369352fe1 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-asgi/setup.py @@ -0,0 +1,26 @@ +# Copyright The 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 os + +import setuptools + +BASE_DIR = os.path.dirname(__file__) +VERSION_FILENAME = os.path.join( + BASE_DIR, "src", "opentelemetry", "instrumentation", "asgi", "version.py" +) +PACKAGE_INFO = {} +with open(VERSION_FILENAME) as f: + exec(f.read(), PACKAGE_INFO) + +setuptools.setup(version=PACKAGE_INFO["__version__"]) diff --git a/util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py similarity index 96% rename from util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/__init__.py rename to instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index 2cdb054d08..f52e5a4067 100644 --- a/util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -13,9 +13,9 @@ # limitations under the License. """ -The opentelemetry.util.http.asgi package provides an ASGI middleware that can -be used on any ASGI framework (such as Django-channels / Quart) to track -requests timing through OpenTelemetry. +The opentelemetry-instrumentation-asgi package provides an ASGI middleware that can be used +on any ASGI framework (such as Django-channels / Quart) to track requests +timing through OpenTelemetry. """ import typing @@ -26,10 +26,10 @@ from asgiref.compatibility import guarantee_single_callable from opentelemetry import context, propagators, trace +from opentelemetry.instrumentation.asgi.version import __version__ # noqa from opentelemetry.instrumentation.utils import http_status_to_status_code from opentelemetry.trace.propagation.textmap import DictGetter from opentelemetry.trace.status import Status, StatusCode -from opentelemetry.util.http.asgi.version import __version__ # noqa class CarrierGetter(DictGetter): diff --git a/util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/version.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/version.py similarity index 100% rename from util/opentelemetry-util-http/src/opentelemetry/util/http/asgi/version.py rename to instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/version.py diff --git a/util/opentelemetry-util-http/tests/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/tests/__init__.py similarity index 100% rename from util/opentelemetry-util-http/tests/asgi/__init__.py rename to instrumentation/opentelemetry-instrumentation-asgi/tests/__init__.py diff --git a/util/opentelemetry-util-http/tests/asgi/test_asgi_middleware.py b/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py similarity index 99% rename from util/opentelemetry-util-http/tests/asgi/test_asgi_middleware.py rename to instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py index 264cbf2c8c..7c4ae20a77 100644 --- a/util/opentelemetry-util-http/tests/asgi/test_asgi_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py @@ -16,7 +16,7 @@ import unittest import unittest.mock as mock -import opentelemetry.util.http.asgi as otel_asgi +import opentelemetry.instrumentation.asgi as otel_asgi from opentelemetry import trace as trace_api from opentelemetry.test.asgitestutil import ( AsgiTestBase, diff --git a/instrumentation/opentelemetry-instrumentation-django/setup.cfg b/instrumentation/opentelemetry-instrumentation-django/setup.cfg index 33f41f88c9..6528f616c0 100644 --- a/instrumentation/opentelemetry-instrumentation-django/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-django/setup.cfg @@ -41,6 +41,7 @@ packages=find_namespace: install_requires = django >= 1.10 opentelemetry-util-http == 0.18.dev0 + opentelemetry-instrumentation-wsgi == 0.18.dev0 opentelemetry-instrumentation == 0.18.dev0 opentelemetry-api == 0.18.dev0 diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py index 64be5c53f0..a167cb9ab4 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -20,14 +20,14 @@ from opentelemetry.context import attach, detach from opentelemetry.instrumentation.django.version import __version__ from opentelemetry.instrumentation.utils import extract_attributes_from_object -from opentelemetry.propagators import extract -from opentelemetry.trace import SpanKind, get_tracer -from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs -from opentelemetry.util.http.wsgi import ( +from opentelemetry.instrumentation.wsgi import ( add_response_attributes, carrier_getter, collect_request_attributes, ) +from opentelemetry.propagators import extract +from opentelemetry.trace import SpanKind, get_tracer +from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs try: from django.core.urlresolvers import ( # pylint: disable=no-name-in-module diff --git a/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg b/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg index ceb07f7f4e..7ec050464f 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-falcon/setup.cfg @@ -41,6 +41,7 @@ package_dir= packages=find_namespace: install_requires = falcon ~= 2.0 + opentelemetry-instrumentation-wsgi == 0.18.dev0 opentelemetry-util-http == 0.18.dev0 opentelemetry-instrumentation == 0.18.dev0 opentelemetry-api == 0.18.dev0 diff --git a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py index 51ecf0d645..19b238fe1e 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py @@ -14,7 +14,7 @@ """ This library builds on the OpenTelemetry WSGI middleware to track web requests -in Falcon applications. In addition to opentelemetry-util-http, +in Falcon applications. In addition to opentelemetry-instrumentation-wsgi, it supports falcon-specific features such as: * The Falcon resource and method name is used as the Span name. @@ -48,7 +48,7 @@ def on_get(self, req, resp): import falcon -import opentelemetry.util.http.wsgi as otel_wsgi +import opentelemetry.instrumentation.wsgi as otel_wsgi from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.falcon.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg b/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg index 7e83ba60a1..388f0c23b6 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-fastapi/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 0.18.dev0 + opentelemetry-instrumentation-asgi == 0.18.dev0 opentelemetry-util-http == 0.18.dev0 [options.entry_points] diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py index 7c6429ba32..2936da1875 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py @@ -15,9 +15,9 @@ import fastapi from starlette.routing import Match +from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.util.http import get_excluded_urls -from opentelemetry.util.http.asgi import OpenTelemetryMiddleware _excluded_urls = get_excluded_urls("FASTAPI") diff --git a/instrumentation/opentelemetry-instrumentation-flask/setup.cfg b/instrumentation/opentelemetry-instrumentation-flask/setup.cfg index f99dbe81fb..6950b75b17 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-flask/setup.cfg @@ -42,6 +42,7 @@ install_requires = flask ~= 1.0 opentelemetry-util-http == 0.18.dev0 opentelemetry-instrumentation == 0.18.dev0 + opentelemetry-instrumentation-wsgi == 0.18.dev0 opentelemetry-api == 0.18.dev0 [options.extras_require] diff --git a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py index 1f8adb3d00..6f94781843 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -51,7 +51,7 @@ def hello(): import flask -import opentelemetry.util.http.wsgi as otel_wsgi +import opentelemetry.instrumentation.wsgi as otel_wsgi from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.flask.version import __version__ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg b/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg index 240ebf8054..09c1646e56 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-pyramid/setup.cfg @@ -42,6 +42,7 @@ install_requires = pyramid >= 1.7 opentelemetry-instrumentation == 0.18.dev0 opentelemetry-api == 0.18.dev0 + opentelemetry-instrumentation-wsgi == 0.18.dev0 opentelemetry-util-http == 0.18.dev0 wrapt >= 1.0.0, < 2.0.0 diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py index 0aa8a02371..66c3acd8cb 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py @@ -5,7 +5,7 @@ from pyramid.settings import asbool from pyramid.tweens import EXCVIEW -import opentelemetry.util.http.wsgi as otel_wsgi +import opentelemetry.instrumentation.wsgi as otel_wsgi from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.pyramid.version import __version__ from opentelemetry.util import time_ns diff --git a/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg b/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg index 4977126ce9..8f52b4741d 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg +++ b/instrumentation/opentelemetry-instrumentation-starlette/setup.cfg @@ -39,6 +39,7 @@ package_dir= packages=find_namespace: install_requires = opentelemetry-api == 0.18.dev0 + opentelemetry-instrumentation-asgi == 0.18.dev0 opentelemetry-util-http == 0.18.dev0 [options.entry_points] diff --git a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py index f222225e76..d595beadcf 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py @@ -15,9 +15,9 @@ from starlette import applications from starlette.routing import Match +from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware from opentelemetry.instrumentation.instrumentor import BaseInstrumentor from opentelemetry.util.http import get_excluded_urls -from opentelemetry.util.http.asgi import OpenTelemetryMiddleware _excluded_urls = get_excluded_urls("STARLETTE") diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/LICENSE b/instrumentation/opentelemetry-instrumentation-wsgi/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-wsgi/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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/instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in b/instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in new file mode 100644 index 0000000000..aed3e33273 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-wsgi/MANIFEST.in @@ -0,0 +1,9 @@ +graft src +graft tests +global-exclude *.pyc +global-exclude *.pyo +global-exclude __pycache__/* +include CHANGELOG.md +include MANIFEST.in +include README.rst +include LICENSE diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/README.rst b/instrumentation/opentelemetry-instrumentation-wsgi/README.rst new file mode 100644 index 0000000000..c3f06bfedb --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-wsgi/README.rst @@ -0,0 +1,26 @@ +OpenTelemetry WSGI Middleware +============================= + +|pypi| + +.. |pypi| image:: https://badge.fury.io/py/opentelemetry-instrumentation-wsgi.svg + :target: https://pypi.org/project/opentelemetry-instrumentation-wsgi/ + + +This library provides a WSGI middleware that can be used on any WSGI framework +(such as Django / Flask) to track requests timing through OpenTelemetry. + +Installation +------------ + +:: + + pip install opentelemetry-instrumentation-wsgi + + +References +---------- + +* `OpenTelemetry WSGI Middleware `_ +* `OpenTelemetry Project `_ +* `WSGI `_ diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg b/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg new file mode 100644 index 0000000000..8085f59187 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-wsgi/setup.cfg @@ -0,0 +1,50 @@ +# Copyright The 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. +# +[metadata] +name = opentelemetry-instrumentation-wsgi +description = WSGI Middleware for OpenTelemetry +long_description = file: README.rst +long_description_content_type = text/x-rst +author = OpenTelemetry Authors +author_email = cncf-opentelemetry-contributors@lists.cncf.io +url = https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-wsgi +platforms = any +license = Apache-2.0 +classifiers = + Development Status :: 4 - Beta + Intended Audience :: Developers + License :: OSI Approved :: Apache Software License + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + +[options] +python_requires = >=3.5 +package_dir= + =src +packages=find_namespace: +install_requires = + opentelemetry-api == 0.18.dev0 + opentelemetry-instrumentation == 0.18.dev0 + +[options.extras_require] +test = + opentelemetry-test == 0.18.dev0 + +[options.packages.find] +where = src diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/setup.py b/instrumentation/opentelemetry-instrumentation-wsgi/setup.py new file mode 100644 index 0000000000..fb4ffa7437 --- /dev/null +++ b/instrumentation/opentelemetry-instrumentation-wsgi/setup.py @@ -0,0 +1,26 @@ +# Copyright The 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 os + +import setuptools + +BASE_DIR = os.path.dirname(__file__) +VERSION_FILENAME = os.path.join( + BASE_DIR, "src", "opentelemetry", "instrumentation", "wsgi", "version.py" +) +PACKAGE_INFO = {} +with open(VERSION_FILENAME) as f: + exec(f.read(), PACKAGE_INFO) + +setuptools.setup(version=PACKAGE_INFO["__version__"]) diff --git a/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py similarity index 95% rename from util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/__init__.py rename to instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py index 9b7308b64d..c336a1320b 100644 --- a/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py @@ -21,7 +21,7 @@ .. code-block:: python from flask import Flask - from opentelemetry.util.http.wsgi import OpenTelemetryMiddleware + from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware app = Flask(__name__) app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app) @@ -42,7 +42,7 @@ def hello(): .. code-block:: python import os - from opentelemetry.util.http.wsgi import OpenTelemetryMiddleware + from opentelemetry.instrumentation.wsgi import OpenTelemetryMiddleware from django.core.wsgi import get_wsgi_application os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings') @@ -60,9 +60,9 @@ def hello(): from opentelemetry import context, propagators, trace from opentelemetry.instrumentation.utils import http_status_to_status_code +from opentelemetry.instrumentation.wsgi.version import __version__ from opentelemetry.trace.propagation.textmap import DictGetter from opentelemetry.trace.status import Status, StatusCode -from opentelemetry.util.http.wsgi.version import __version__ _HTTP_VERSION_PREFIX = "HTTP/" @@ -233,9 +233,9 @@ def __call__(self, environ, start_response): raise -# FIXME Put this in a subfunction to not delay the call to the wrapped WSGI -# application (instrumentation should change the application behavior as little -# as possible). +# Put this in a subfunction to not delay the call to the wrapped +# WSGI application (instrumentation should change the application +# behavior as little as possible). def _end_span_after_iterating(iterable, span, tracer, token): try: with tracer.use_span(span): diff --git a/util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/version.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/version.py similarity index 100% rename from util/opentelemetry-util-http/src/opentelemetry/util/http/wsgi/version.py rename to instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/version.py diff --git a/util/opentelemetry-util-http/tests/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/tests/__init__.py similarity index 100% rename from util/opentelemetry-util-http/tests/wsgi/__init__.py rename to instrumentation/opentelemetry-instrumentation-wsgi/tests/__init__.py diff --git a/util/opentelemetry-util-http/tests/wsgi/test_getter.py b/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_getter.py similarity index 94% rename from util/opentelemetry-util-http/tests/wsgi/test_getter.py rename to instrumentation/opentelemetry-instrumentation-wsgi/tests/test_getter.py index 937f01b629..80cf6b1ecd 100644 --- a/util/opentelemetry-util-http/tests/wsgi/test_getter.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_getter.py @@ -14,7 +14,7 @@ from unittest import TestCase -from opentelemetry.util.http.wsgi import CarrierGetter +from opentelemetry.instrumentation.wsgi import CarrierGetter class TestCarrierGetter(TestCase): diff --git a/util/opentelemetry-util-http/tests/wsgi/test_wsgi_middleware.py b/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py similarity index 99% rename from util/opentelemetry-util-http/tests/wsgi/test_wsgi_middleware.py rename to instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py index b058a86727..d5168e3280 100644 --- a/util/opentelemetry-util-http/tests/wsgi/test_wsgi_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py @@ -18,7 +18,7 @@ import wsgiref.util as wsgiref_util from urllib.parse import urlsplit -import opentelemetry.util.http.wsgi as otel_wsgi +import opentelemetry.instrumentation.wsgi as otel_wsgi from opentelemetry import trace as trace_api from opentelemetry.test.wsgitestutil import WsgiTestBase from opentelemetry.trace.status import StatusCode diff --git a/scripts/coverage.sh b/scripts/coverage.sh index 15960a3108..8055adb0de 100755 --- a/scripts/coverage.sh +++ b/scripts/coverage.sh @@ -20,6 +20,7 @@ coverage erase cov exporter/opentelemetry-exporter-datadog cov instrumentation/opentelemetry-instrumentation-flask cov instrumentation/opentelemetry-instrumentation-requests +cov instrumentation/opentelemetry-instrumentation-wsgi # aiohttp is only supported on Python 3.5+. if [ ${PYTHON_VERSION_INFO[1]} -gt 4 ]; then diff --git a/tox.ini b/tox.ini index d9feb0801f..c4ea92b463 100644 --- a/tox.ini +++ b/tox.ini @@ -94,6 +94,10 @@ envlist = py3{5,6,7,8}-test-instrumentation-pyramid pypy3-test-instrumentation-pyramid + ; opentelemetry-instrumentation-asgi + py3{5,6,7,8}-test-instrumentation-asgi + pypy3-test-instrumentation-asgi + ; opentelemetry-instrumentation-asyncpg py3{5,6,7,8}-test-instrumentation-asyncpg ; ext-asyncpg intentionally excluded from pypy3 @@ -102,6 +106,10 @@ envlist = py3{5,6,7,8}-test-instrumentation-sqlite3 pypy3-test-instrumentation-sqlite3 + ; opentelemetry-instrumentation-wsgi + py3{5,6,7,8}-test-instrumentation-wsgi + pypy3-test-instrumentation-wsgi + ; opentelemetry-instrumentation-grpc py3{5,6,7,8}-test-instrumentation-grpc @@ -160,6 +168,7 @@ deps = changedir = test-instrumentation-aiohttp-client: instrumentation/opentelemetry-instrumentation-aiohttp-client/tests test-instrumentation-aiopg: instrumentation/opentelemetry-instrumentation-aiopg/tests + test-instrumentation-asgi: instrumentation/opentelemetry-instrumentation-asgi/tests test-instrumentation-asyncpg: instrumentation/opentelemetry-instrumentation-asyncpg/tests test-instrumentation-boto: instrumentation/opentelemetry-instrumentation-boto/tests test-instrumentation-botocore: instrumentation/opentelemetry-instrumentation-botocore/tests @@ -187,6 +196,7 @@ changedir = test-instrumentation-starlette: instrumentation/opentelemetry-instrumentation-starlette/tests test-instrumentation-system-metrics: instrumentation/opentelemetry-instrumentation-system-metrics/tests test-instrumentation-tornado: instrumentation/opentelemetry-instrumentation-tornado/tests + test-instrumentation-wsgi: instrumentation/opentelemetry-instrumentation-wsgi/tests test-util-http: util/opentelemetry-util-http/tests test-sdkextension-aws: sdk-extension/opentelemetry-sdk-extension-aws/tests @@ -206,7 +216,9 @@ commands_pre = grpc: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-grpc[test] - falcon,flask,django,pyramid,starlette,fastapi,tornado: pip install {toxinidir}/util/opentelemetry-util-http + falcon,flask,django,pyramid,tornado,starlette,fastapi: pip install {toxinidir}/util/opentelemetry-util-http + wsgi,falcon,flask,django,pyramid: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-wsgi + asgi,starlette,fastapi: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-asgi asyncpg: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-asyncpg @@ -228,6 +240,7 @@ commands_pre = fastapi: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-fastapi[test] mysql: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi {toxinidir}/instrumentation/opentelemetry-instrumentation-mysql[test] + pymemcache: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymemcache[test] pymongo: pip install {toxinidir}/instrumentation/opentelemetry-instrumentation-pymongo[test] @@ -264,10 +277,10 @@ commands_pre = elasticsearch{2,5,6,7}: pip install {toxinidir}/opentelemetry-python-core/opentelemetry-instrumentation {toxinidir}/instrumentation/opentelemetry-instrumentation-elasticsearch[test] + aws: pip install requests {toxinidir}/sdk-extension/opentelemetry-sdk-extension-aws http: pip install {toxinidir}/util/opentelemetry-util-http - ; In order to get a health coverage report, ; we have to install packages in editable mode. coverage: python {toxinidir}/scripts/eachdist.py install --editable @@ -315,7 +328,9 @@ commands_pre = python -m pip install {toxinidir}/opentelemetry-python-core/opentelemetry-sdk python -m pip install {toxinidir}/opentelemetry-python-core/tests/util python -m pip install {toxinidir}/util/opentelemetry-util-http + python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-wsgi[test] python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi[test] + python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-asgi[test] python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-botocore[test] python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-django[test] python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-starlette[test] diff --git a/util/opentelemetry-util-http/README.rst b/util/opentelemetry-util-http/README.rst index 3ec70435d9..c7b58b5b42 100644 --- a/util/opentelemetry-util-http/README.rst +++ b/util/opentelemetry-util-http/README.rst @@ -25,7 +25,7 @@ Usage (Quart) .. code-block:: python from quart import Quart - from opentelemetry.util.http.asgi import OpenTelemetryMiddleware + from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware app = Quart(__name__) app.asgi_app = OpenTelemetryMiddleware(app.asgi_app) @@ -47,7 +47,7 @@ Modify the application's ``asgi.py`` file as shown below. import os from django.core.asgi import get_asgi_application - from opentelemetry.util.http.asgi import OpenTelemetryMiddleware + from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'asgi_example.settings') @@ -60,7 +60,7 @@ Usage (Raw ASGI) .. code-block:: python - from opentelemetry.util.http.asgi import OpenTelemetryMiddleware + from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware app = ... # An ASGI application. app = OpenTelemetryMiddleware(app)