From bb5570c782eed861f93ae4a3fc5472f82e3fb530 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sun, 4 Apr 2021 13:40:51 +0530 Subject: [PATCH 01/32] Update instrumentations to use tracer_provider for creating tracer if given, otherwise use global tracer provider --- .../opentelemetry/instrumentation/asgi/__init__.py | 4 ++-- .../instrumentation/asyncpg/__init__.py | 6 ++---- .../opentelemetry/instrumentation/django/__init__.py | 2 ++ .../instrumentation/django/middleware.py | 3 ++- .../opentelemetry/instrumentation/falcon/__init__.py | 6 +++++- .../instrumentation/fastapi/__init__.py | 6 +++++- .../opentelemetry/instrumentation/flask/__init__.py | 12 +++++++----- .../opentelemetry/instrumentation/grpc/__init__.py | 5 +++-- .../opentelemetry/instrumentation/redis/__init__.py | 5 +---- .../instrumentation/sqlalchemy/engine.py | 6 ++---- .../instrumentation/starlette/__init__.py | 6 +++++- .../opentelemetry/instrumentation/wsgi/__init__.py | 4 ++-- 12 files changed, 38 insertions(+), 27 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index 7122ae63ba..a06a5ebe40 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -163,9 +163,9 @@ class OpenTelemetryMiddleware: Optional: Defaults to get_default_span_details. """ - def __init__(self, app, excluded_urls=None, span_details_callback=None): + def __init__(self, app, excluded_urls=None, span_details_callback=None, tracer_provider=None): self.app = guarantee_single_callable(app) - self.tracer = trace.get_tracer(__name__, __version__) + self.tracer = trace.get_tracer(__name__, __version__, tracer_provider) self.span_details_callback = ( span_details_callback or get_default_span_details ) diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py index e78224a9ef..df9ba2a5c2 100644 --- a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py @@ -89,13 +89,11 @@ def __init__(self, capture_parameters=False): self.capture_parameters = capture_parameters def _instrument(self, **kwargs): - tracer_provider = kwargs.get( - "tracer_provider", trace.get_tracer_provider() - ) + tracer_provider = kwargs.get("tracer_provider") setattr( asyncpg, _APPLIED, - tracer_provider.get_tracer("asyncpg", __version__), + trace.get_tracer(__name__, __version__, tracer_provider), ) for method in [ 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 87b0ae2816..06277b2a50 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py @@ -44,6 +44,8 @@ def _instrument(self, **kwargs): if environ.get(OTEL_PYTHON_DJANGO_INSTRUMENT) == "False": return + _DjangoMiddleware._tracer_provider = kwargs.get("tracer_provider") + # This can not be solved, but is an inherent problem of this approach: # the order of middleware entries matters, and here you have no control # on that: 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 b32b77e04a..4a6a8916d3 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -61,6 +61,7 @@ class _DjangoMiddleware(MiddlewareMixin): _traced_request_attrs = get_traced_request_attrs("DJANGO") _excluded_urls = get_excluded_urls("DJANGO") + _tracer_provider = None @staticmethod def _get_span_name(request): @@ -99,7 +100,7 @@ def process_request(self, request): token = attach(extract(carrier_getter, request_meta)) - tracer = get_tracer(__name__, __version__) + tracer = get_tracer(__name__, __version__, tracer_provider=_DjangoMiddleware._tracer_provider) span = tracer.start_span( self._get_span_name(request), 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 211df573cc..3a5ab3cb12 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py @@ -83,6 +83,7 @@ class FalconInstrumentor(BaseInstrumentor): def _instrument(self, **kwargs): self._original_falcon_api = falcon.API + _InstrumentedFalconAPI.tracer_provider = kwargs.get("tracer_provider") falcon.API = _InstrumentedFalconAPI def _uninstrument(self, **kwargs): @@ -90,12 +91,15 @@ def _uninstrument(self, **kwargs): class _InstrumentedFalconAPI(falcon.API): + tracer_provider = None def __init__(self, *args, **kwargs): middlewares = kwargs.pop("middleware", []) if not isinstance(middlewares, (list, tuple)): middlewares = [middlewares] - self._tracer = trace.get_tracer(__name__, __version__) + self._tracer = trace.get_tracer( + __name__, __version__, tracer_provider=_InstrumentedFalconAPI.tracer_provider + ) trace_middleware = _TraceMiddleware( self._tracer, kwargs.get("traced_request_attributes") ) 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 2936da1875..402978e2c2 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py @@ -31,7 +31,7 @@ class FastAPIInstrumentor(BaseInstrumentor): _original_fastapi = None @staticmethod - def instrument_app(app: fastapi.FastAPI): + def instrument_app(app: fastapi.FastAPI, tracer_provider=None): """Instrument an uninstrumented FastAPI application. """ if not getattr(app, "is_instrumented_by_opentelemetry", False): @@ -39,11 +39,13 @@ def instrument_app(app: fastapi.FastAPI): OpenTelemetryMiddleware, excluded_urls=_excluded_urls, span_details_callback=_get_route_details, + tracer_provider=tracer_provider ) app.is_instrumented_by_opentelemetry = True def _instrument(self, **kwargs): self._original_fastapi = fastapi.FastAPI + _InstrumentedFastAPI.tracer_provider = kwargs.get("tracer_provider") fastapi.FastAPI = _InstrumentedFastAPI def _uninstrument(self, **kwargs): @@ -51,12 +53,14 @@ def _uninstrument(self, **kwargs): class _InstrumentedFastAPI(fastapi.FastAPI): + tracer_provider = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.add_middleware( OpenTelemetryMiddleware, excluded_urls=_excluded_urls, span_details_callback=_get_route_details, + tracer_provider=_InstrumentedFastAPI.tracer_provider ) 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 cf332a301b..316880fa0f 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -109,7 +109,7 @@ def _start_response(status, response_headers, *args, **kwargs): return _wrapped_app -def _wrapped_before_request(name_callback): +def _wrapped_before_request(name_callback, tracer_provider=None): def _before_request(): if _excluded_urls.url_disabled(flask.request.url): return @@ -120,7 +120,7 @@ def _before_request(): extract(otel_wsgi.carrier_getter, flask_request_environ) ) - tracer = trace.get_tracer(__name__, __version__) + tracer = trace.get_tracer(__name__, __version__, tracer_provider) span = tracer.start_span( span_name, @@ -171,6 +171,7 @@ def _teardown_request(exc): class _InstrumentedFlask(flask.Flask): name_callback = get_default_span_name + tracer_provider = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -179,7 +180,7 @@ def __init__(self, *args, **kwargs): self.wsgi_app = _rewrapped_app(self.wsgi_app) _before_request = _wrapped_before_request( - _InstrumentedFlask.name_callback + _InstrumentedFlask.name_callback, tracer_provider=_InstrumentedFlask.tracer_provider ) self._before_request = _before_request self.before_request(_before_request) @@ -198,10 +199,11 @@ def _instrument(self, **kwargs): name_callback = kwargs.get("name_callback") if callable(name_callback): _InstrumentedFlask.name_callback = name_callback + _InstrumentedFlask.tracer_provider = kwargs.get("tracer_provider") flask.Flask = _InstrumentedFlask def instrument_app( - self, app, name_callback=get_default_span_name + self, app, name_callback=get_default_span_name, tracer_provider=None ): # pylint: disable=no-self-use if not hasattr(app, "_is_instrumented"): app._is_instrumented = False @@ -210,7 +212,7 @@ def instrument_app( app._original_wsgi_app = app.wsgi_app app.wsgi_app = _rewrapped_app(app.wsgi_app) - _before_request = _wrapped_before_request(name_callback) + _before_request = _wrapped_before_request(name_callback, tracer_provider=tracer_provider) app._before_request = _before_request app.before_request(_before_request) app.teardown_request(_teardown_request) diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py index 43c6b8ba74..e1e38c012a 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py @@ -147,13 +147,14 @@ class GrpcInstrumentorServer(BaseInstrumentor): def _instrument(self, **kwargs): self._original_func = grpc.server + tracer_provider = kwargs.get("tracer_provider") def server(*args, **kwargs): if "interceptors" in kwargs: # add our interceptor as the first - kwargs["interceptors"].insert(0, server_interceptor()) + kwargs["interceptors"].insert(0, server_interceptor(tracer_provider=tracer_provider)) else: - kwargs["interceptors"] = [server_interceptor()] + kwargs["interceptors"] = [server_interceptor(tracer_provider=tracer_provider)] return self._original_func(*args, **kwargs) grpc.server = server diff --git a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py index 5bf83242ce..51563bbb4c 100644 --- a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py @@ -113,13 +113,10 @@ class RedisInstrumentor(BaseInstrumentor): """ def _instrument(self, **kwargs): - tracer_provider = kwargs.get( - "tracer_provider", trace.get_tracer_provider() - ) setattr( redis, "_opentelemetry_tracer", - tracer_provider.get_tracer(_DEFAULT_SERVICE, __version__), + trace.get_tracer(__name__, __version__, tracer_provider=kwargs.get("tracer_provider")), ) if redis.VERSION < (3, 0, 0): diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py index 032de562b0..6dde123fc5 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py +++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py @@ -44,10 +44,8 @@ def _normalize_vendor(vendor): def _get_tracer(engine, tracer_provider=None): - if tracer_provider is None: - tracer_provider = trace.get_tracer_provider() - return tracer_provider.get_tracer( - _normalize_vendor(engine.name), __version__ + return trace.get_tracer( + _normalize_vendor(engine.name), __version__, tracer_provider=tracer_provider ) 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 d595beadcf..88686a2367 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py @@ -31,7 +31,7 @@ class StarletteInstrumentor(BaseInstrumentor): _original_starlette = None @staticmethod - def instrument_app(app: applications.Starlette): + def instrument_app(app: applications.Starlette, tracer_provider=None): """Instrument an uninstrumented Starlette application. """ if not getattr(app, "is_instrumented_by_opentelemetry", False): @@ -39,11 +39,13 @@ def instrument_app(app: applications.Starlette): OpenTelemetryMiddleware, excluded_urls=_excluded_urls, span_details_callback=_get_route_details, + tracer_provider=tracer_provider, ) app.is_instrumented_by_opentelemetry = True def _instrument(self, **kwargs): self._original_starlette = applications.Starlette + _InstrumentedStarlette.tracer_provider = kwargs.get("tracer_provider") applications.Starlette = _InstrumentedStarlette def _uninstrument(self, **kwargs): @@ -51,12 +53,14 @@ def _uninstrument(self, **kwargs): class _InstrumentedStarlette(applications.Starlette): + tracer_provider = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.add_middleware( OpenTelemetryMiddleware, excluded_urls=_excluded_urls, span_details_callback=_get_route_details, + tracer_provider=_InstrumentedStarlette.tracer_provider ) diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py index ec2fc162f0..7da4af8175 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py @@ -186,9 +186,9 @@ class OpenTelemetryMiddleware: Optional: Defaults to get_default_span_name. """ - def __init__(self, wsgi, name_callback=get_default_span_name): + def __init__(self, wsgi, name_callback=get_default_span_name, tracer_provider=None): self.wsgi = wsgi - self.tracer = trace.get_tracer(__name__, __version__) + self.tracer = trace.get_tracer(__name__, __version__, tracer_provider) self.name_callback = name_callback @staticmethod From ba977dd018534a6fbccb13e6b6b54cf1a27e7c69 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sun, 4 Apr 2021 19:46:43 +0530 Subject: [PATCH 02/32] Update instrumentations; fix lint --- .../opentelemetry/instrumentation/asgi/__init__.py | 8 +++++++- .../instrumentation/django/middleware.py | 6 +++++- .../opentelemetry/instrumentation/falcon/__init__.py | 9 ++++++--- .../instrumentation/fastapi/__init__.py | 9 +++++---- .../opentelemetry/instrumentation/flask/__init__.py | 12 ++++++++---- .../opentelemetry/instrumentation/grpc/__init__.py | 8 ++++++-- .../opentelemetry/instrumentation/redis/__init__.py | 5 ++++- .../instrumentation/sqlalchemy/engine.py | 4 +++- .../instrumentation/starlette/__init__.py | 7 ++++--- .../opentelemetry/instrumentation/wsgi/__init__.py | 4 +++- 10 files changed, 51 insertions(+), 21 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index a06a5ebe40..882957271c 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -163,7 +163,13 @@ class OpenTelemetryMiddleware: Optional: Defaults to get_default_span_details. """ - def __init__(self, app, excluded_urls=None, span_details_callback=None, tracer_provider=None): + def __init__( + self, + app, + excluded_urls=None, + span_details_callback=None, + tracer_provider=None, + ): self.app = guarantee_single_callable(app) self.tracer = trace.get_tracer(__name__, __version__, tracer_provider) self.span_details_callback = ( 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 4a6a8916d3..acc05b755e 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -100,7 +100,11 @@ def process_request(self, request): token = attach(extract(carrier_getter, request_meta)) - tracer = get_tracer(__name__, __version__, tracer_provider=_DjangoMiddleware._tracer_provider) + tracer = get_tracer( + __name__, + __version__, + tracer_provider=_DjangoMiddleware._tracer_provider, + ) span = tracer.start_span( self._get_span_name(request), 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 3a5ab3cb12..7ca8792b48 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py @@ -83,7 +83,7 @@ class FalconInstrumentor(BaseInstrumentor): def _instrument(self, **kwargs): self._original_falcon_api = falcon.API - _InstrumentedFalconAPI.tracer_provider = kwargs.get("tracer_provider") + _InstrumentedFalconAPI._tracer_provider = kwargs.get("tracer_provider") falcon.API = _InstrumentedFalconAPI def _uninstrument(self, **kwargs): @@ -91,14 +91,17 @@ def _uninstrument(self, **kwargs): class _InstrumentedFalconAPI(falcon.API): - tracer_provider = None + _tracer_provider = None + def __init__(self, *args, **kwargs): middlewares = kwargs.pop("middleware", []) if not isinstance(middlewares, (list, tuple)): middlewares = [middlewares] self._tracer = trace.get_tracer( - __name__, __version__, tracer_provider=_InstrumentedFalconAPI.tracer_provider + __name__, + __version__, + tracer_provider=_InstrumentedFalconAPI._tracer_provider, ) trace_middleware = _TraceMiddleware( self._tracer, kwargs.get("traced_request_attributes") 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 402978e2c2..2d8bb85a09 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/src/opentelemetry/instrumentation/fastapi/__init__.py @@ -39,13 +39,13 @@ def instrument_app(app: fastapi.FastAPI, tracer_provider=None): OpenTelemetryMiddleware, excluded_urls=_excluded_urls, span_details_callback=_get_route_details, - tracer_provider=tracer_provider + tracer_provider=tracer_provider, ) app.is_instrumented_by_opentelemetry = True def _instrument(self, **kwargs): self._original_fastapi = fastapi.FastAPI - _InstrumentedFastAPI.tracer_provider = kwargs.get("tracer_provider") + _InstrumentedFastAPI._tracer_provider = kwargs.get("tracer_provider") fastapi.FastAPI = _InstrumentedFastAPI def _uninstrument(self, **kwargs): @@ -53,14 +53,15 @@ def _uninstrument(self, **kwargs): class _InstrumentedFastAPI(fastapi.FastAPI): - tracer_provider = None + _tracer_provider = None + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.add_middleware( OpenTelemetryMiddleware, excluded_urls=_excluded_urls, span_details_callback=_get_route_details, - tracer_provider=_InstrumentedFastAPI.tracer_provider + tracer_provider=_InstrumentedFastAPI._tracer_provider, ) 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 316880fa0f..6761baec24 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -171,7 +171,7 @@ def _teardown_request(exc): class _InstrumentedFlask(flask.Flask): name_callback = get_default_span_name - tracer_provider = None + _tracer_provider = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -180,7 +180,8 @@ def __init__(self, *args, **kwargs): self.wsgi_app = _rewrapped_app(self.wsgi_app) _before_request = _wrapped_before_request( - _InstrumentedFlask.name_callback, tracer_provider=_InstrumentedFlask.tracer_provider + _InstrumentedFlask.name_callback, + tracer_provider=_InstrumentedFlask._tracer_provider, ) self._before_request = _before_request self.before_request(_before_request) @@ -197,9 +198,10 @@ class FlaskInstrumentor(BaseInstrumentor): def _instrument(self, **kwargs): self._original_flask = flask.Flask name_callback = kwargs.get("name_callback") + tracer_provider = kwargs.get("tracer_provider") if callable(name_callback): _InstrumentedFlask.name_callback = name_callback - _InstrumentedFlask.tracer_provider = kwargs.get("tracer_provider") + _InstrumentedFlask._tracer_provider = tracer_provider flask.Flask = _InstrumentedFlask def instrument_app( @@ -212,7 +214,9 @@ def instrument_app( app._original_wsgi_app = app.wsgi_app app.wsgi_app = _rewrapped_app(app.wsgi_app) - _before_request = _wrapped_before_request(name_callback, tracer_provider=tracer_provider) + _before_request = _wrapped_before_request( + name_callback, tracer_provider=tracer_provider + ) app._before_request = _before_request app.before_request(_before_request) app.teardown_request(_teardown_request) diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py index e1e38c012a..087e147c3e 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py @@ -152,9 +152,13 @@ def _instrument(self, **kwargs): def server(*args, **kwargs): if "interceptors" in kwargs: # add our interceptor as the first - kwargs["interceptors"].insert(0, server_interceptor(tracer_provider=tracer_provider)) + kwargs["interceptors"].insert( + 0, server_interceptor(tracer_provider=tracer_provider) + ) else: - kwargs["interceptors"] = [server_interceptor(tracer_provider=tracer_provider)] + kwargs["interceptors"] = [ + server_interceptor(tracer_provider=tracer_provider) + ] return self._original_func(*args, **kwargs) grpc.server = server diff --git a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py index 51563bbb4c..e9beec17f5 100644 --- a/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-redis/src/opentelemetry/instrumentation/redis/__init__.py @@ -113,10 +113,13 @@ class RedisInstrumentor(BaseInstrumentor): """ def _instrument(self, **kwargs): + tracer_provider = kwargs.get("tracer_provider") setattr( redis, "_opentelemetry_tracer", - trace.get_tracer(__name__, __version__, tracer_provider=kwargs.get("tracer_provider")), + trace.get_tracer( + __name__, __version__, tracer_provider=tracer_provider, + ), ) if redis.VERSION < (3, 0, 0): diff --git a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py index 6dde123fc5..d683fbc7b0 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py +++ b/instrumentation/opentelemetry-instrumentation-sqlalchemy/src/opentelemetry/instrumentation/sqlalchemy/engine.py @@ -45,7 +45,9 @@ def _normalize_vendor(vendor): def _get_tracer(engine, tracer_provider=None): return trace.get_tracer( - _normalize_vendor(engine.name), __version__, tracer_provider=tracer_provider + _normalize_vendor(engine.name), + __version__, + tracer_provider=tracer_provider, ) 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 88686a2367..be05066ce8 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/src/opentelemetry/instrumentation/starlette/__init__.py @@ -45,7 +45,7 @@ def instrument_app(app: applications.Starlette, tracer_provider=None): def _instrument(self, **kwargs): self._original_starlette = applications.Starlette - _InstrumentedStarlette.tracer_provider = kwargs.get("tracer_provider") + _InstrumentedStarlette._tracer_provider = kwargs.get("tracer_provider") applications.Starlette = _InstrumentedStarlette def _uninstrument(self, **kwargs): @@ -53,14 +53,15 @@ def _uninstrument(self, **kwargs): class _InstrumentedStarlette(applications.Starlette): - tracer_provider = None + _tracer_provider = None + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.add_middleware( OpenTelemetryMiddleware, excluded_urls=_excluded_urls, span_details_callback=_get_route_details, - tracer_provider=_InstrumentedStarlette.tracer_provider + tracer_provider=_InstrumentedStarlette._tracer_provider, ) diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py index 7da4af8175..a92ea02956 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py @@ -186,7 +186,9 @@ class OpenTelemetryMiddleware: Optional: Defaults to get_default_span_name. """ - def __init__(self, wsgi, name_callback=get_default_span_name, tracer_provider=None): + def __init__( + self, wsgi, name_callback=get_default_span_name, tracer_provider=None + ): self.wsgi = wsgi self.tracer = trace.get_tracer(__name__, __version__, tracer_provider) self.name_callback = name_callback From f908c87a8e45d0d2a703e709c318e010fcb5e7b7 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Thu, 8 Apr 2021 19:38:51 +0530 Subject: [PATCH 03/32] Use same tracer for each call --- .../instrumentation/asyncpg/__init__.py | 13 +++++-------- .../instrumentation/dbapi/__init__.py | 15 ++++++--------- .../instrumentation/django/__init__.py | 8 +++++++- .../instrumentation/django/middleware.py | 12 +++--------- .../instrumentation/flask/__init__.py | 17 +++++++++-------- .../instrumentation/requests/__init__.py | 12 +++++++----- .../instrumentation/sqlite3/__init__.py | 4 ++-- .../instrumentation/urllib/__init__.py | 13 +++++++------ .../instrumentation/urllib3/__init__.py | 10 +++++----- 9 files changed, 51 insertions(+), 53 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py index df9ba2a5c2..a0292691d0 100644 --- a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py @@ -87,14 +87,11 @@ class AsyncPGInstrumentor(BaseInstrumentor): def __init__(self, capture_parameters=False): super().__init__() self.capture_parameters = capture_parameters + self._tracer = None def _instrument(self, **kwargs): tracer_provider = kwargs.get("tracer_provider") - setattr( - asyncpg, - _APPLIED, - trace.get_tracer(__name__, __version__, tracer_provider), - ) + self._tracer = trace.get_tracer(__name__, __version__, tracer_provider) for method in [ "Connection.execute", @@ -108,7 +105,6 @@ def _instrument(self, **kwargs): ) def _uninstrument(self, **__): - delattr(asyncpg, _APPLIED) for method in [ "execute", "executemany", @@ -119,13 +115,14 @@ def _uninstrument(self, **__): unwrap(asyncpg.Connection, method) async def _do_execute(self, func, instance, args, kwargs): - tracer = getattr(asyncpg, _APPLIED) exception = None params = getattr(instance, "_params", {}) name = args[0] if args[0] else params.get("database", "postgresql") - with tracer.start_as_current_span(name, kind=SpanKind.CLIENT) as span: + with self._tracer.start_as_current_span( + name, kind=SpanKind.CLIENT + ) as span: if span.is_recording(): span_attributes = _hydrate_span_from_args( instance, diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py b/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py index 7a99fc793a..6a0fd39d63 100644 --- a/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-dbapi/src/opentelemetry/instrumentation/dbapi/__init__.py @@ -227,7 +227,11 @@ def __init__( } self._name = name self._version = version - self._tracer_provider = tracer_provider + self._tracer = get_tracer( + self._name, + instrumenting_library_version=self._version, + tracer_provider=tracer_provider, + ) self.capture_parameters = capture_parameters self.database_system = database_system self.connection_props = {} @@ -235,13 +239,6 @@ def __init__( self.name = "" self.database = "" - def get_tracer(self): - return get_tracer( - self._name, - instrumenting_library_version=self._version, - tracer_provider=self._tracer_provider, - ) - def wrapped_connection( self, connect_method: typing.Callable[..., typing.Any], @@ -367,7 +364,7 @@ def traced_execution( else self._db_api_integration.name ) - with self._db_api_integration.get_tracer().start_as_current_span( + with self._db_api_integration._tracer.start_as_current_span( name, kind=SpanKind.CLIENT ) as span: self._populate_span(span, cursor, *args) 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 06277b2a50..ecc1c9ce0a 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py @@ -17,6 +17,7 @@ from django.conf import settings +from opentelemetry.trace import get_tracer from opentelemetry.instrumentation.django.environment_variables import ( OTEL_PYTHON_DJANGO_INSTRUMENT, ) @@ -44,7 +45,12 @@ def _instrument(self, **kwargs): if environ.get(OTEL_PYTHON_DJANGO_INSTRUMENT) == "False": return - _DjangoMiddleware._tracer_provider = kwargs.get("tracer_provider") + tracer_provider = kwargs.get("tracer_provider") + tracer = get_tracer( + __name__, __version__, tracer_provider=tracer_provider, + ) + + _DjangoMiddleware._tracer = tracer # This can not be solved, but is an inherent problem of this approach: # the order of middleware entries matters, and here you have no control 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 13f982dd94..16f6c14fd9 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -24,7 +24,7 @@ wsgi_getter, ) from opentelemetry.propagate import extract -from opentelemetry.trace import SpanKind, get_tracer, use_span +from opentelemetry.trace import SpanKind, use_span from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs try: @@ -61,7 +61,7 @@ class _DjangoMiddleware(MiddlewareMixin): _traced_request_attrs = get_traced_request_attrs("DJANGO") _excluded_urls = get_excluded_urls("DJANGO") - _tracer_provider = None + _tracer = None @staticmethod def _get_span_name(request): @@ -100,13 +100,7 @@ def process_request(self, request): token = attach(extract(request_meta, getter=wsgi_getter)) - tracer = get_tracer( - __name__, - __version__, - tracer_provider=_DjangoMiddleware._tracer_provider, - ) - - span = tracer.start_span( + span = self._tracer.start_span( self._get_span_name(request), kind=SpanKind.SERVER, start_time=request_meta.get( 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 6416211622..8b49d32309 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-flask/src/opentelemetry/instrumentation/flask/__init__.py @@ -109,7 +109,7 @@ def _start_response(status, response_headers, *args, **kwargs): return _wrapped_app -def _wrapped_before_request(name_callback, tracer_provider=None): +def _wrapped_before_request(name_callback, tracer): def _before_request(): if _excluded_urls.url_disabled(flask.request.url): return @@ -120,8 +120,6 @@ def _before_request(): extract(flask_request_environ, getter=otel_wsgi.wsgi_getter) ) - tracer = trace.get_tracer(__name__, __version__, tracer_provider) - span = tracer.start_span( span_name, kind=trace.SpanKind.SERVER, @@ -179,9 +177,12 @@ def __init__(self, *args, **kwargs): self._original_wsgi_ = self.wsgi_app self.wsgi_app = _rewrapped_app(self.wsgi_app) + tracer = trace.get_tracer( + __name__, __version__, _InstrumentedFlask._tracer_provider + ) + _before_request = _wrapped_before_request( - _InstrumentedFlask.name_callback, - tracer_provider=_InstrumentedFlask._tracer_provider, + _InstrumentedFlask.name_callback, tracer, ) self._before_request = _before_request self.before_request(_before_request) @@ -214,9 +215,9 @@ def instrument_app( app._original_wsgi_app = app.wsgi_app app.wsgi_app = _rewrapped_app(app.wsgi_app) - _before_request = _wrapped_before_request( - name_callback, tracer_provider=tracer_provider - ) + tracer = trace.get_tracer(__name__, __version__, tracer_provider) + + _before_request = _wrapped_before_request(name_callback, tracer) app._before_request = _before_request app.before_request(_before_request) app.teardown_request(_teardown_request) diff --git a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py b/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py index 0735eba622..bab4461513 100644 --- a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py @@ -55,7 +55,7 @@ # pylint: disable=unused-argument # pylint: disable=R0915 -def _instrument(tracer_provider=None, span_callback=None, name_callback=None): +def _instrument(tracer, span_callback=None, name_callback=None): """Enables tracing of all requests calls that go through :code:`requests.session.Session.request` (this includes :code:`requests.get`, etc.).""" @@ -125,9 +125,9 @@ def _instrumented_requests_call( labels["http.method"] = method labels["http.url"] = url - with get_tracer( - __name__, __version__, tracer_provider - ).start_as_current_span(span_name, kind=SpanKind.CLIENT) as span: + with tracer.start_as_current_span( + span_name, kind=SpanKind.CLIENT + ) as span: exception = None if span.is_recording(): span.set_attribute("http.method", method) @@ -220,8 +220,10 @@ def _instrument(self, **kwargs): outgoing HTTP request based on the method and url. Optional: Defaults to get_default_span_name. """ + tracer_provider = kwargs.get("tracer_provider") + tracer = get_tracer(__name__, __version__, tracer_provider) _instrument( - tracer_provider=kwargs.get("tracer_provider"), + tracer, span_callback=kwargs.get("span_callback"), name_callback=kwargs.get("name_callback"), ) diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py index 7ba76968af..1bece6d800 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py @@ -74,7 +74,7 @@ def _uninstrument(self, **kwargs): dbapi.unwrap_connect(sqlite3, "connect") # pylint:disable=no-self-use - def instrument_connection(self, connection): + def instrument_connection(self, connection, tracer_provider=None): """Enable instrumentation in a SQLite connection. Args: @@ -83,7 +83,7 @@ def instrument_connection(self, connection): Returns: An instrumented connection. """ - tracer = get_tracer(__name__, __version__) + tracer = get_tracer(__name__, __version__, tracer_provider) return dbapi.instrument_connection( tracer, diff --git a/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py b/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py index 1ef29012af..0db91dbc79 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py @@ -74,9 +74,10 @@ def _instrument(self, **kwargs): outgoing HTTP request based on the method and url. Optional: Defaults to get_default_span_name. """ - + tracer_provider = kwargs.get("tracer_provider") + tracer = get_tracer(__name__, __version__, tracer_provider) _instrument( - tracer_provider=kwargs.get("tracer_provider"), + tracer, span_callback=kwargs.get("span_callback"), name_callback=kwargs.get("name_callback"), ) @@ -96,7 +97,7 @@ def get_default_span_name(method): return "HTTP {}".format(method).strip() -def _instrument(tracer_provider=None, span_callback=None, name_callback=None): +def _instrument(tracer, span_callback=None, name_callback=None): """Enables tracing of all requests calls that go through :code:`urllib.Client._make_request`""" @@ -142,9 +143,9 @@ def _instrumented_open_call( "http.url": url, } - with get_tracer( - __name__, __version__, tracer_provider - ).start_as_current_span(span_name, kind=SpanKind.CLIENT) as span: + with tracer.start_as_current_span( + span_name, kind=SpanKind.CLIENT + ) as span: exception = None if span.is_recording(): span.set_attribute("http.method", method) diff --git a/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py b/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py index 8c24854207..fdd9a73040 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py @@ -85,8 +85,10 @@ def _instrument(self, **kwargs): ``url_filter``: A callback to process the requested URL prior to adding it as a span attribute. """ + tracer_provider = kwargs.get("tracer_provider") + tracer = get_tracer(__name__, __version__, tracer_provider) _instrument( - tracer_provider=kwargs.get("tracer_provider"), + tracer, span_name_or_callback=kwargs.get("span_name"), url_filter=kwargs.get("url_filter"), ) @@ -96,7 +98,7 @@ def _uninstrument(self, **kwargs): def _instrument( - tracer_provider: TracerProvider = None, + tracer, span_name_or_callback: _SpanNameT = None, url_filter: _UrlFilterT = None, ): @@ -114,9 +116,7 @@ def instrumented_urlopen(wrapped, instance, args, kwargs): "http.url": url, } - with get_tracer( - __name__, __version__, tracer_provider - ).start_as_current_span( + with tracer.start_as_current_span( span_name, kind=SpanKind.CLIENT, attributes=span_attributes ) as span: inject(headers) From c0daf281f5c6edb67974e9b2f8c3fe95f11f276e Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Thu, 8 Apr 2021 19:43:09 +0530 Subject: [PATCH 04/32] Update aiopg --- .../opentelemetry/instrumentation/aiopg/aiopg_integration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py index f69c1f5dde..d140c18838 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py @@ -114,7 +114,7 @@ async def traced_execution( else self._db_api_integration.name ) - with self._db_api_integration.get_tracer().start_as_current_span( + with self._db_api_integration._tracer.start_as_current_span( name, kind=SpanKind.CLIENT ) as span: self._populate_span(span, cursor, *args) From 004e5c5957e55960ca1a8d90e60686997ef09627 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 00:29:23 +0530 Subject: [PATCH 05/32] Fix lint --- .../src/opentelemetry/instrumentation/django/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ecc1c9ce0a..76c1c9b45a 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py @@ -17,13 +17,13 @@ from django.conf import settings -from opentelemetry.trace import get_tracer from opentelemetry.instrumentation.django.environment_variables import ( 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.trace import get_tracer _logger = getLogger(__name__) From d4bd7fd5b622ba8d10b7d6e0766d3aab10b8d33f Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 00:44:40 +0530 Subject: [PATCH 06/32] Remove old test --- .../tests/test_asyncpg_wrapper.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py b/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py index 33b121ce53..2dbb6a3d7d 100644 --- a/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py +++ b/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py @@ -6,12 +6,6 @@ class TestAsyncPGInstrumentation(TestBase): - def test_instrumentation_flags(self): - AsyncPGInstrumentor().instrument() - self.assertTrue(hasattr(asyncpg, "_opentelemetry_tracer")) - AsyncPGInstrumentor().uninstrument() - self.assertFalse(hasattr(asyncpg, "_opentelemetry_tracer")) - def test_duplicated_instrumentation(self): AsyncPGInstrumentor().instrument() AsyncPGInstrumentor().instrument() From 89bd65c3dbc8a4f478a1214e31b80490183765d0 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 01:38:19 +0530 Subject: [PATCH 07/32] Add test for aiopg inregration --- .../instrumentation/aiopg/__init__.py | 7 ++++++- .../tests/test_aiopg_integration.py | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py index ffae8df5cc..8a8ce26b69 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py @@ -83,17 +83,20 @@ def _instrument(self, **kwargs): tracer_provider=tracer_provider, ) + # pylint:disable=no-self-use def _uninstrument(self, **kwargs): """"Disable aiopg instrumentation""" wrappers.unwrap_connect() wrappers.unwrap_create_pool() # pylint:disable=no-self-use - def instrument_connection(self, connection): + def instrument_connection(self, connection, tracer_provider=None): """Enable instrumentation in a aiopg connection. Args: connection: The connection to instrument. + tracer_provider: The optional :class:`opentelemetry.trace.TracerProvider` to + use. If omitted the current globally configured one is used. Returns: An instrumented connection. @@ -103,6 +106,8 @@ def instrument_connection(self, connection): connection, self._DATABASE_SYSTEM, self._CONNECTION_ATTRIBUTES, + version=__version__, + tracer_provider=tracer_provider ) def uninstrument_connection(self, connection): diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py index 50766aee6e..4f4b3205b1 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py @@ -203,6 +203,26 @@ def test_instrument_connection(self): spans_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans_list), 1) + def test_custom_tracer_provider_instrument_connection(self): + resource = resources.Resource.create({"service.name": "db-test-service"}) + result = self.create_tracer_provider(resource=resource) + tracer_provider, exporter = result + + cnx = async_call(aiopg.connect(database="test")) + + cnx = AiopgInstrumentor().instrument_connection(cnx, tracer_provider=tracer_provider) + + cursor = async_call(cnx.cursor()) + query = "SELECT * FROM test" + async_call(cursor.execute(query)) + + spans_list = exporter.get_finished_spans() + self.assertEqual(len(spans_list), 1) + span = spans_list[0] + + self.assertEqual(span.resource.attributes["service.name"], "db-test-service") + self.assertIs(span.resource, resource) + def test_uninstrument_connection(self): AiopgInstrumentor().instrument() cnx = async_call(aiopg.connect(database="test")) From baa70ecc9c2f2b8ca7555b78b7dd0e2bed71c55e Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 02:03:50 +0530 Subject: [PATCH 08/32] Add tracer provider test --- .../instrumentation/asgi/__init__.py | 4 ++++ .../tests/test_asgi_middleware.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index a6a6754545..3d4a7acff7 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -160,10 +160,14 @@ class OpenTelemetryMiddleware: Args: app: The ASGI application callable to forward requests to. + excluded_urls: The :class:`opentelemetry.util.http.ExcludeList` to use. + Set to None to disable excluding urls. span_details_callback: Callback which should return a string and a tuple, representing the desired span name and a dictionary with any additional span attributes to set. Optional: Defaults to get_default_span_details. + tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to + use. If omitted the current globally configured one is used. """ def __init__( diff --git a/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py b/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py index 7c4ae20a77..dd3a82cd91 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py @@ -18,10 +18,12 @@ import opentelemetry.instrumentation.asgi as otel_asgi from opentelemetry import trace as trace_api +from opentelemetry.sdk import resources from opentelemetry.test.asgitestutil import ( AsgiTestBase, setup_testing_defaults, ) +from opentelemetry.test.test_base import TestBase async def http_app(scope, receive, send): @@ -210,6 +212,22 @@ def update_expected_span_name(expected): outputs = self.get_all_output() self.validate_outputs(outputs, modifiers=[update_expected_span_name]) + def test_custom_tracer_provider_otel_asgi(self): + resource = resources.Resource.create({"service-test-key": "value"}) + result = TestBase.create_tracer_provider(resource=resource) + tracer_provider, exporter = result + + app = otel_asgi.OpenTelemetryMiddleware( + simple_asgi, tracer_provider=tracer_provider + ) + self.seed_app(app) + self.send_default_request() + span_list = exporter.get_finished_spans() + for span in span_list: + self.assertEqual( + span.resource.attributes["service-test-key"], "value" + ) + def test_behavior_with_scope_server_as_none(self): """Test that middleware is ok when server is none in scope.""" From e47cdbb92736f33ae4903d08052bb4ccc4318723 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 02:04:13 +0530 Subject: [PATCH 09/32] Black format --- .../opentelemetry/instrumentation/aiopg/__init__.py | 2 +- .../tests/test_aiopg_integration.py | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py index 8a8ce26b69..fd50e0510c 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py @@ -107,7 +107,7 @@ def instrument_connection(self, connection, tracer_provider=None): self._DATABASE_SYSTEM, self._CONNECTION_ATTRIBUTES, version=__version__, - tracer_provider=tracer_provider + tracer_provider=tracer_provider, ) def uninstrument_connection(self, connection): diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py index 4f4b3205b1..e605b93bb3 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/tests/test_aiopg_integration.py @@ -204,13 +204,17 @@ def test_instrument_connection(self): self.assertEqual(len(spans_list), 1) def test_custom_tracer_provider_instrument_connection(self): - resource = resources.Resource.create({"service.name": "db-test-service"}) + resource = resources.Resource.create( + {"service.name": "db-test-service"} + ) result = self.create_tracer_provider(resource=resource) tracer_provider, exporter = result cnx = async_call(aiopg.connect(database="test")) - cnx = AiopgInstrumentor().instrument_connection(cnx, tracer_provider=tracer_provider) + cnx = AiopgInstrumentor().instrument_connection( + cnx, tracer_provider=tracer_provider + ) cursor = async_call(cnx.cursor()) query = "SELECT * FROM test" @@ -220,7 +224,9 @@ def test_custom_tracer_provider_instrument_connection(self): self.assertEqual(len(spans_list), 1) span = spans_list[0] - self.assertEqual(span.resource.attributes["service.name"], "db-test-service") + self.assertEqual( + span.resource.attributes["service.name"], "db-test-service" + ) self.assertIs(span.resource, resource) def test_uninstrument_connection(self): From 7c121dffffcf9e5102de12d363bd60b92b575b6e Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 02:07:48 +0530 Subject: [PATCH 10/32] Remove unused code --- .../src/opentelemetry/instrumentation/asyncpg/__init__.py | 2 -- .../tests/test_asyncpg_wrapper.py | 1 - 2 files changed, 3 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py index a0292691d0..f378d50389 100644 --- a/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asyncpg/src/opentelemetry/instrumentation/asyncpg/__init__.py @@ -45,8 +45,6 @@ from opentelemetry.trace import SpanKind from opentelemetry.trace.status import Status, StatusCode -_APPLIED = "_opentelemetry_tracer" - def _hydrate_span_from_args(connection, query, parameters) -> dict: """Get network and database attributes from connection.""" diff --git a/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py b/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py index 2dbb6a3d7d..a3cbbfcecb 100644 --- a/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py +++ b/instrumentation/opentelemetry-instrumentation-asyncpg/tests/test_asyncpg_wrapper.py @@ -1,4 +1,3 @@ -import asyncpg from asyncpg import Connection from opentelemetry.instrumentation.asyncpg import AsyncPGInstrumentor From 43dc35732f913473f007160a71507820a9a9052a Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 02:26:44 +0530 Subject: [PATCH 11/32] Update dbapi tests --- .../tests/test_dbapi_integration.py | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py b/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py index 6ff25881dc..8a40faefc1 100644 --- a/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py +++ b/instrumentation/opentelemetry-instrumentation-dbapi/tests/test_dbapi_integration.py @@ -18,6 +18,7 @@ from opentelemetry import trace as trace_api from opentelemetry.instrumentation import dbapi +from opentelemetry.sdk import resources from opentelemetry.test.test_base import TestBase @@ -40,7 +41,7 @@ def test_span_succeeded(self): "user": "user", } db_integration = dbapi.DatabaseApiIntegration( - self.tracer, "testcomponent", connection_attributes + "testname", "testcomponent", connection_attributes ) mock_connection = db_integration.wrapped_connection( mock_connect, {}, connection_props @@ -64,7 +65,7 @@ def test_span_succeeded(self): def test_span_name(self): db_integration = dbapi.DatabaseApiIntegration( - self.tracer, "testcomponent", {} + "testname", "testcomponent", {} ) mock_connection = db_integration.wrapped_connection( mock_connect, {}, {} @@ -97,7 +98,7 @@ def test_span_succeeded_with_capture_of_statement_parameters(self): "user": "user", } db_integration = dbapi.DatabaseApiIntegration( - self.tracer, + "testname", "testcomponent", connection_attributes, capture_parameters=True, @@ -138,12 +139,10 @@ def test_span_not_recording(self): "host": "server_host", "user": "user", } - mock_tracer = mock.Mock() mock_span = mock.Mock() mock_span.is_recording.return_value = False - mock_tracer.start_span.return_value = mock_span db_integration = dbapi.DatabaseApiIntegration( - mock_tracer, "testcomponent", connection_attributes + "testname", "testcomponent", connection_attributes ) mock_connection = db_integration.wrapped_connection( mock_connect, {}, connection_props @@ -173,9 +172,30 @@ def test_span_failed(self): self.assertIs(span.status.status_code, trace_api.StatusCode.ERROR) self.assertEqual(span.status.description, "Exception: Test Exception") + def test_custom_tracer_provider_dbapi(self): + resource = resources.Resource.create({"db-resource-key": "value"}) + result = self.create_tracer_provider(resource=resource) + tracer_provider, exporter = result + + db_integration = dbapi.DatabaseApiIntegration( + self.tracer, "testcomponent", tracer_provider=tracer_provider + ) + mock_connection = db_integration.wrapped_connection( + mock_connect, {}, {} + ) + cursor = mock_connection.cursor() + with self.assertRaises(Exception): + cursor.execute("Test query", throw_exception=True) + + spans_list = exporter.get_finished_spans() + self.assertEqual(len(spans_list), 1) + span = spans_list[0] + self.assertEqual(span.resource.attributes["db-resource-key"], "value") + self.assertIs(span.status.status_code, trace_api.StatusCode.ERROR) + def test_executemany(self): db_integration = dbapi.DatabaseApiIntegration( - self.tracer, "testcomponent" + "testname", "testcomponent" ) mock_connection = db_integration.wrapped_connection( mock_connect, {}, {} @@ -189,7 +209,7 @@ def test_executemany(self): def test_callproc(self): db_integration = dbapi.DatabaseApiIntegration( - self.tracer, "testcomponent" + "testname", "testcomponent" ) mock_connection = db_integration.wrapped_connection( mock_connect, {}, {} From 0980c5f169df05cc7acf822a3f2f0f664727793b Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 02:44:05 +0530 Subject: [PATCH 12/32] Add django test --- .../tests/test_middleware.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py index fb12dd24f4..2d42e6ef21 100644 --- a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py @@ -26,6 +26,7 @@ DjangoInstrumentor, _DjangoMiddleware, ) +from opentelemetry.sdk import resources from opentelemetry.sdk.trace import Span from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase @@ -309,3 +310,34 @@ def response_hook(span, request, response): self.assertIsInstance(response_hook_args[1], HttpRequest) self.assertIsInstance(response_hook_args[2], HttpResponse) self.assertEqual(response_hook_args[2], response) + +class TestMiddlewareWithTracerProvider(TestBase, WsgiTestBase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + def setUp(self): + super().setUp() + setup_test_environment() + resource = resources.Resource.create({"resource-key": "resource-value"}) + result = self.create_tracer_provider(resource=resource) + tracer_provider, exporter = result + self.exporter = exporter + _django_instrumentor.instrument(tracer_provider=tracer_provider) + + def tearDown(self): + super().tearDown() + teardown_test_environment() + _django_instrumentor.uninstrument() + + def test_tracer_provider_traced(self): + Client().post("/traced/") + + spans = self.exporter.get_finished_spans() + self.assertEqual(len(spans), 1) + + span = spans[0] + + self.assertEqual( + span.resource.attributes["resource-key"], "resource-value" + ) From 415ba229a952fa86ec7b39b3ac516504ce8bc6e9 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 03:29:38 +0530 Subject: [PATCH 13/32] Update instrumentations --- .../tests/test_middleware.py | 5 +- .../tests/test_falcon.py | 31 +++++++++ .../tests/test_fastapi_instrumentation.py | 16 ++++- .../tests/test_programmatic.py | 67 +++++++++++++++++++ 4 files changed, 117 insertions(+), 2 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py index 2d42e6ef21..d2d6e01930 100644 --- a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py @@ -311,6 +311,7 @@ def response_hook(span, request, response): self.assertIsInstance(response_hook_args[2], HttpResponse) self.assertEqual(response_hook_args[2], response) + class TestMiddlewareWithTracerProvider(TestBase, WsgiTestBase): @classmethod def setUpClass(cls): @@ -319,7 +320,9 @@ def setUpClass(cls): def setUp(self): super().setUp() setup_test_environment() - resource = resources.Resource.create({"resource-key": "resource-value"}) + resource = resources.Resource.create( + {"resource-key": "resource-value"} + ) result = self.create_tracer_provider(resource=resource) tracer_provider, exporter = result self.exporter = exporter diff --git a/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py b/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py index 74882fd681..a8c352da32 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/tests/test_falcon.py @@ -17,6 +17,7 @@ from falcon import testing from opentelemetry.instrumentation.falcon import FalconInstrumentor +from opentelemetry.sdk.resources import Resource from opentelemetry.test.test_base import TestBase from opentelemetry.trace import StatusCode from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs @@ -204,3 +205,33 @@ def test_traced_not_recording(self): self.assertTrue(mock_span.is_recording.called) self.assertFalse(mock_span.set_attribute.called) self.assertFalse(mock_span.set_status.called) + + +class TestFalconInstrumentationWithTracerProvider(TestBase): + def setUp(self): + super().setUp() + resource = Resource.create({"resource-key": "resource-value"}) + result = self.create_tracer_provider(resource=resource) + tracer_provider, exporter = result + self.exporter = exporter + + FalconInstrumentor().instrument(tracer_provider=tracer_provider) + self.app = make_app() + + def client(self): + return testing.TestClient(self.app) + + def tearDown(self): + super().tearDown() + with self.disable_logging(): + FalconInstrumentor().uninstrument() + + def test_traced_request(self): + self.client().simulate_request(method="GET", path="/hello") + spans = self.exporter.get_finished_spans() + self.assertEqual(len(spans), 1) + span = spans[0] + self.assertEqual( + span.resource.attributes["resource-key"], "resource-value" + ) + self.exporter.clear() diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py index fe6c27928a..ac7551420a 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py @@ -19,6 +19,7 @@ from fastapi.testclient import TestClient import opentelemetry.instrumentation.fastapi as otel_fastapi +from opentelemetry.sdk.resources import Resource from opentelemetry.test.test_base import TestBase from opentelemetry.util.http import get_excluded_urls @@ -112,9 +113,22 @@ class TestAutoInstrumentation(TestFastAPIManualInstrumentation): def _create_app(self): # instrumentation is handled by the instrument call - self._instrumentor.instrument() + resource = Resource.create({"key1": "value1", "key2": "value2"}) + result = self.create_tracer_provider(resource=resource) + tracer_provider, exporter = result + self.memory_exporter = exporter + + self._instrumentor.instrument(tracer_provider=tracer_provider) return self._create_fastapi_app() + def test_request(self): + self._client.get("/foobar") + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 3) + for span in spans: + self.assertEqual(span.resource.attributes["key1"], "value1") + self.assertEqual(span.resource.attributes["key2"], "value2") + def tearDown(self): self._instrumentor.uninstrument() super().tearDown() diff --git a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py index 3c62dd751d..183757d0e0 100644 --- a/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py +++ b/instrumentation/opentelemetry-instrumentation-flask/tests/test_programmatic.py @@ -18,6 +18,7 @@ from opentelemetry import trace from opentelemetry.instrumentation.flask import FlaskInstrumentor +from opentelemetry.sdk.resources import Resource from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase from opentelemetry.util.http import get_excluded_urls @@ -243,3 +244,69 @@ def test_custom_span_name(self): span_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(span_list), 1) self.assertEqual(span_list[0].name, "instrument-without-app") + + +class TestProgrammaticCustomTracerProvider( + InstrumentationTest, TestBase, WsgiTestBase +): + def setUp(self): + super().setUp() + resource = Resource.create({"service.name": "flask-api"}) + result = self.create_tracer_provider(resource=resource) + tracer_provider, exporter = result + self.memory_exporter = exporter + + self.app = Flask(__name__) + + FlaskInstrumentor().instrument_app( + self.app, tracer_provider=tracer_provider + ) + self._common_initialization() + + def tearDown(self): + super().tearDown() + with self.disable_logging(): + FlaskInstrumentor().uninstrument_app(self.app) + + def test_custom_span_name(self): + self.client.get("/hello/123") + + span_list = self.memory_exporter.get_finished_spans() + self.assertEqual(len(span_list), 1) + self.assertEqual( + span_list[0].resource.attributes["service.name"], "flask-api" + ) + + +class TestProgrammaticCustomTracerProviderWithoutApp( + InstrumentationTest, TestBase, WsgiTestBase +): + def setUp(self): + super().setUp() + resource = Resource.create({"service.name": "flask-api-no-app"}) + result = self.create_tracer_provider(resource=resource) + tracer_provider, exporter = result + self.memory_exporter = exporter + + FlaskInstrumentor().instrument(tracer_provider=tracer_provider) + # pylint: disable=import-outside-toplevel,reimported,redefined-outer-name + from flask import Flask + + self.app = Flask(__name__) + + self._common_initialization() + + def tearDown(self): + super().tearDown() + with self.disable_logging(): + FlaskInstrumentor().uninstrument() + + def test_custom_span_name(self): + self.client.get("/hello/123") + + span_list = self.memory_exporter.get_finished_spans() + self.assertEqual(len(span_list), 1) + self.assertEqual( + span_list[0].resource.attributes["service.name"], + "flask-api-no-app", + ) From 3073cf9d5406e969f19357a803136f772ba3f45e Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 03:38:41 +0530 Subject: [PATCH 14/32] Add missing params --- .../opentelemetry/instrumentation/mysql/__init__.py | 10 ++++++---- .../instrumentation/psycopg2/__init__.py | 11 ++++++++--- .../opentelemetry/instrumentation/pymysql/__init__.py | 5 ++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py b/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py index 9fdf594c56..81f002ceef 100644 --- a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py @@ -77,22 +77,24 @@ def _uninstrument(self, **kwargs): dbapi.unwrap_connect(mysql.connector, "connect") # pylint:disable=no-self-use - def instrument_connection(self, connection): + def instrument_connection(self, connection, tracer_provider=None): """Enable instrumentation in a MySQL connection. Args: connection: The connection to instrument. + tracer_provider: The optional :class:`opentelemetry.trace.TracerProvider` to + use. If omitted the current globally configured one is used. Returns: An instrumented connection. """ - tracer = get_tracer(__name__, __version__) - return dbapi.instrument_connection( - tracer, + __name__, connection, self._DATABASE_SYSTEM, self._CONNECTION_ATTRIBUTES, + version=__version__, + tracer_provider=tracer_provider, ) def uninstrument_connection(self, connection): diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py b/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py index 1190d1c083..6582ff5e77 100644 --- a/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py @@ -86,11 +86,15 @@ def _uninstrument(self, **kwargs): dbapi.unwrap_connect(psycopg2, "connect") # TODO(owais): check if core dbapi can do this for all dbapi implementations e.g, pymysql and mysql - def instrument_connection(self, connection): # pylint: disable=no-self-use + def instrument_connection( + self, connection, tracer_provider=None + ): # pylint: disable=no-self-use setattr( connection, _OTEL_CURSOR_FACTORY_KEY, connection.cursor_factory ) - connection.cursor_factory = _new_cursor_factory() + connection.cursor_factory = _new_cursor_factory( + tracer_provider=tracer_provider + ) return connection # TODO(owais): check if core dbapi can do this for all dbapi implementations e.g, pymysql and mysql @@ -146,13 +150,14 @@ def get_statement(self, cursor, args): return statement -def _new_cursor_factory(db_api=None, base_factory=None): +def _new_cursor_factory(db_api=None, base_factory=None, tracer_provider=None): if not db_api: db_api = DatabaseApiIntegration( __name__, Psycopg2Instrumentor._DATABASE_SYSTEM, connection_attributes=Psycopg2Instrumentor._CONNECTION_ATTRIBUTES, version=__version__, + tracer_provider=tracer_provider, ) base_factory = base_factory or pg_cursor diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py index 5e9952bc47..1be41747a1 100644 --- a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py @@ -78,11 +78,13 @@ def _uninstrument(self, **kwargs): dbapi.unwrap_connect(pymysql, "connect") # pylint:disable=no-self-use - def instrument_connection(self, connection): + def instrument_connection(self, connection, tracer_provider=None): """Enable instrumentation in a PyMySQL connection. Args: connection: The connection to instrument. + tracer_provider: The optional :class:`opentelemetry.trace.TracerProvider` to + use. If omitted the current globally configured one is used. Returns: An instrumented connection. @@ -94,6 +96,7 @@ def instrument_connection(self, connection): self._DATABASE_SYSTEM, self._CONNECTION_ATTRIBUTES, version=__version__, + tracer_provider=tracer_provider, ) def uninstrument_connection(self, connection): From 5bf13f995d18a97d8a2c4ed7afd14260ce490856 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 05:37:57 +0530 Subject: [PATCH 15/32] update instrumentations --- .../instrumentation/asgi/__init__.py | 4 +- .../instrumentation/sqlite3/__init__.py | 7 +++- .../tests/test_starlette_instrumentation.py | 17 ++++++++- .../tests/test_wsgi_middleware.py | 38 +++++++++++++++++++ 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index 3d4a7acff7..222c9b6821 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -160,13 +160,13 @@ class OpenTelemetryMiddleware: Args: app: The ASGI application callable to forward requests to. - excluded_urls: The :class:`opentelemetry.util.http.ExcludeList` to use. + excluded_urls: The optional :class:`opentelemetry.util.http.ExcludeList` to use. Set to None to disable excluding urls. span_details_callback: Callback which should return a string and a tuple, representing the desired span name and a dictionary with any additional span attributes to set. Optional: Defaults to get_default_span_details. - tracer_provider: The :class:`opentelemetry.trace.TracerProvider` to + tracer_provider: The optional :class:`opentelemetry.trace.TracerProvider` to use. If omitted the current globally configured one is used. """ diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py index 1bece6d800..0f2c4dcd05 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py @@ -79,17 +79,20 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. + tracer_provider: The optional :class:`opentelemetry.trace.TracerProvider` to + use. If omitted the current globally configured one is used. Returns: An instrumented connection. """ - tracer = get_tracer(__name__, __version__, tracer_provider) return dbapi.instrument_connection( - tracer, + __name__, connection, self._DATABASE_SYSTEM, self._CONNECTION_ATTRIBUTES, + version=__version__, + tracer_provider=tracer_provider, ) def uninstrument_connection(self, connection): diff --git a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py index 56116c5a06..62faa4e188 100644 --- a/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-starlette/tests/test_starlette_instrumentation.py @@ -21,6 +21,7 @@ from starlette.testclient import TestClient import opentelemetry.instrumentation.starlette as otel_starlette +from opentelemetry.sdk.resources import Resource from opentelemetry.test.test_base import TestBase from opentelemetry.util.http import get_excluded_urls @@ -106,13 +107,27 @@ class TestAutoInstrumentation(TestStarletteManualInstrumentation): def _create_app(self): # instrumentation is handled by the instrument call - self._instrumentor.instrument() + resource = Resource.create({"key1": "value1", "key2": "value2"}) + result = self.create_tracer_provider(resource=resource) + tracer_provider, exporter = result + self.memory_exporter = exporter + + self._instrumentor.instrument(tracer_provider=tracer_provider) + return self._create_starlette_app() def tearDown(self): self._instrumentor.uninstrument() super().tearDown() + def test_request(self): + self._client.get("/foobar") + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 3) + for span in spans: + self.assertEqual(span.resource.attributes["key1"], "value1") + self.assertEqual(span.resource.attributes["key2"], "value2") + class TestAutoInstrumentationLogic(unittest.TestCase): def test_instrumentation(self): diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py b/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py index 1f52a7d7f3..847abdabc5 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/tests/test_wsgi_middleware.py @@ -20,6 +20,8 @@ import opentelemetry.instrumentation.wsgi as otel_wsgi from opentelemetry import trace as trace_api +from opentelemetry.sdk.resources import Resource +from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase from opentelemetry.trace import StatusCode @@ -341,5 +343,41 @@ def test_response_attributes(self): self.span.set_attribute.assert_has_calls(expected, any_order=True) +class TestWsgiMiddlewareWithTracerProvider(WsgiTestBase): + def validate_response( + self, + response, + exporter, + error=None, + span_name="HTTP GET", + http_method="GET", + ): + while True: + try: + value = next(response) + self.assertEqual(value, b"*") + except StopIteration: + break + + span_list = exporter.get_finished_spans() + self.assertEqual(len(span_list), 1) + self.assertEqual(span_list[0].name, span_name) + self.assertEqual(span_list[0].kind, trace_api.SpanKind.SERVER) + self.assertEqual( + span_list[0].resource.attributes["service-key"], "service-value" + ) + + def test_basic_wsgi_call(self): + resource = Resource.create({"service-key": "service-value"}) + result = TestBase.create_tracer_provider(resource=resource) + tracer_provider, exporter = result + + app = otel_wsgi.OpenTelemetryMiddleware( + simple_wsgi, tracer_provider=tracer_provider + ) + response = app(self.environ, self.start_response) + self.validate_response(response, exporter) + + if __name__ == "__main__": unittest.main() From 8e5a6dff98cb40eeff58d9c6789f676855f46fa9 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 05:54:00 +0530 Subject: [PATCH 16/32] Update docstring --- .../src/opentelemetry/instrumentation/aiopg/__init__.py | 4 ++-- .../src/opentelemetry/instrumentation/mysql/__init__.py | 4 ++-- .../src/opentelemetry/instrumentation/pymysql/__init__.py | 4 ++-- .../src/opentelemetry/instrumentation/sqlite3/__init__.py | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py index fd50e0510c..1807d51d31 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py @@ -95,8 +95,8 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. - tracer_provider: The optional :class:`opentelemetry.trace.TracerProvider` to - use. If omitted the current globally configured one is used. + tracer_provider: The optional TracerProvider to use. If omitted + the current globally configured one is used. Returns: An instrumented connection. diff --git a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py b/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py index 81f002ceef..924522f90f 100644 --- a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py @@ -82,8 +82,8 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. - tracer_provider: The optional :class:`opentelemetry.trace.TracerProvider` to - use. If omitted the current globally configured one is used. + tracer_provider: The optional TracerProvider to use. If omitted + the current globally configured one is used. Returns: An instrumented connection. diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py index 1be41747a1..d4f5e36925 100644 --- a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py @@ -83,8 +83,8 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. - tracer_provider: The optional :class:`opentelemetry.trace.TracerProvider` to - use. If omitted the current globally configured one is used. + tracer_provider: The optional TracerProvider to use. If omitted + the current globally configured one is used. Returns: An instrumented connection. diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py index 0f2c4dcd05..123a16f513 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py @@ -79,8 +79,8 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. - tracer_provider: The optional :class:`opentelemetry.trace.TracerProvider` to - use. If omitted the current globally configured one is used. + tracer_provider: The optional TracerProvider to use. If omitted + the current globally configured one is used. Returns: An instrumented connection. From 6df43ab36ba936c9335aa680df4423752848d4b0 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 05:57:51 +0530 Subject: [PATCH 17/32] Fix lint --- .../src/opentelemetry/instrumentation/asgi/__init__.py | 4 ++-- tox.ini | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index 222c9b6821..f91d65b8f4 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -166,8 +166,8 @@ class OpenTelemetryMiddleware: and a tuple, representing the desired span name and a dictionary with any additional span attributes to set. Optional: Defaults to get_default_span_details. - tracer_provider: The optional :class:`opentelemetry.trace.TracerProvider` to - use. If omitted the current globally configured one is used. + tracer_provider: The optional TracerProvider to use. If omitted + the current globally configured one is used. """ def __init__( diff --git a/tox.ini b/tox.ini index 54bd2abc41..bd712f69fd 100644 --- a/tox.ini +++ b/tox.ini @@ -319,7 +319,7 @@ commands = [testenv:lint] basepython: python3.8 -recreate = False +recreate = True deps = -c dev-requirements.txt flaky From 0f3fa3f53c1ae074d96f5b0d823d1b946210282b Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Sat, 10 Apr 2021 15:03:42 +0530 Subject: [PATCH 18/32] Update asgi --- .../src/opentelemetry/instrumentation/asgi/__init__.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index f91d65b8f4..9afcf1be79 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -160,14 +160,12 @@ class OpenTelemetryMiddleware: Args: app: The ASGI application callable to forward requests to. - excluded_urls: The optional :class:`opentelemetry.util.http.ExcludeList` to use. - Set to None to disable excluding urls. span_details_callback: Callback which should return a string and a tuple, representing the desired span name and a dictionary with any additional span attributes to set. Optional: Defaults to get_default_span_details. - tracer_provider: The optional TracerProvider to use. If omitted - the current globally configured one is used. + tracer_provider: The optional TracerProvider to use. If omitted + the current globally configured one is used. """ def __init__( From 8c27e166f52318cee63d8d29c6253d1925ececb5 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Tue, 13 Apr 2021 18:15:07 +0530 Subject: [PATCH 19/32] Fix sphnix docs --- .../src/opentelemetry/instrumentation/aiopg/__init__.py | 2 +- .../src/opentelemetry/instrumentation/asgi/__init__.py | 2 +- .../src/opentelemetry/instrumentation/mysql/__init__.py | 2 +- .../src/opentelemetry/instrumentation/pymysql/__init__.py | 2 +- .../src/opentelemetry/instrumentation/sqlite3/__init__.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py index 1807d51d31..31a2c32535 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py @@ -95,7 +95,7 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. - tracer_provider: The optional TracerProvider to use. If omitted + tracer_provider: The optional tracer provider to use. If omitted the current globally configured one is used. Returns: diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index 9afcf1be79..2eaf4c644a 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -164,7 +164,7 @@ class OpenTelemetryMiddleware: and a tuple, representing the desired span name and a dictionary with any additional span attributes to set. Optional: Defaults to get_default_span_details. - tracer_provider: The optional TracerProvider to use. If omitted + tracer_provider: The optional tracer provider to use. If omitted the current globally configured one is used. """ diff --git a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py b/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py index 924522f90f..4d7a321d1d 100644 --- a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py @@ -82,7 +82,7 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. - tracer_provider: The optional TracerProvider to use. If omitted + tracer_provider: The optional tracer provider to use. If omitted the current globally configured one is used. Returns: diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py index d4f5e36925..6db3334ab9 100644 --- a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py @@ -83,7 +83,7 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. - tracer_provider: The optional TracerProvider to use. If omitted + tracer_provider: The optional tracer provider to use. If omitted the current globally configured one is used. Returns: diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py index 123a16f513..8fdcfc82c2 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py @@ -79,7 +79,7 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. - tracer_provider: The optional TracerProvider to use. If omitted + tracer_provider: The optional tracer provider to use. If omitted the current globally configured one is used. Returns: From 791a23ce5dbe021a3381c389c87ea2dddfee4b91 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Tue, 13 Apr 2021 18:16:20 +0530 Subject: [PATCH 20/32] Add CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e398cd8d9d..d3f47045fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#387](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/387)) - Update redis instrumentation to follow semantic conventions ([#403](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/403)) +- Update instrumentations to use tracer_provider for creating tracer if given, otherwise use global tracer provider + ([#402](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/402)) ### Added - `opentelemetry-instrumentation-urllib3` Add urllib3 instrumentation From ea5a8a79dfbca2c7d438adb22521ef7d4f30380c Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Tue, 13 Apr 2021 18:17:45 +0530 Subject: [PATCH 21/32] Revert tox.ini change --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index bd712f69fd..d2244b48ef 100644 --- a/tox.ini +++ b/tox.ini @@ -319,7 +319,7 @@ commands = [testenv:lint] basepython: python3.8 -recreate = True +recreate = False deps = -c dev-requirements.txt flaky From bf33f17dee73c574ad7d3745aa86817d0976a266 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Tue, 13 Apr 2021 18:24:50 +0530 Subject: [PATCH 22/32] Invalidate old cache --- .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 9b5e1e5438..835c6875bd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,7 +44,7 @@ jobs: uses: actions/cache@v2 with: path: .tox - key: tox-cache-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} + key: tox-cache-v2-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} - name: run tox run: tox -f ${{ matrix.python-version }}-${{ matrix.package }} -- --benchmark-json=${{ env.RUN_MATRIX_COMBINATION }}-benchmark.json - name: Find and merge benchmarks From 5df680a0c18bdd484a5d9394c74086957ce87c94 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Tue, 13 Apr 2021 18:27:13 +0530 Subject: [PATCH 23/32] Revert "Invalidate old cache" This reverts commit bf33f17dee73c574ad7d3745aa86817d0976a266. --- .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 835c6875bd..9b5e1e5438 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,7 +44,7 @@ jobs: uses: actions/cache@v2 with: path: .tox - key: tox-cache-v2-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} + key: tox-cache-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} - name: run tox run: tox -f ${{ matrix.python-version }}-${{ matrix.package }} -- --benchmark-json=${{ env.RUN_MATRIX_COMBINATION }}-benchmark.json - name: Find and merge benchmarks From f3ebf2c507d908dc79c2c9f08d0882e184ae68d2 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Wed, 14 Apr 2021 00:13:50 +0530 Subject: [PATCH 24/32] Address review comments --- .../instrumentation/falcon/__init__.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 5dd510172d..0fd0bf30c3 100644 --- a/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-falcon/src/opentelemetry/instrumentation/falcon/__init__.py @@ -83,7 +83,12 @@ class FalconInstrumentor(BaseInstrumentor): def _instrument(self, **kwargs): self._original_falcon_api = falcon.API - _InstrumentedFalconAPI._tracer_provider = kwargs.get("tracer_provider") + tracer_provider = kwargs.get("tracer_provider") + _InstrumentedFalconAPI._tracer = trace.get_tracer( + __name__, + __version__, + tracer_provider=tracer_provider, + ) falcon.API = _InstrumentedFalconAPI def _uninstrument(self, **kwargs): @@ -91,18 +96,13 @@ def _uninstrument(self, **kwargs): class _InstrumentedFalconAPI(falcon.API): - _tracer_provider = None + _tracer = None def __init__(self, *args, **kwargs): middlewares = kwargs.pop("middleware", []) if not isinstance(middlewares, (list, tuple)): middlewares = [middlewares] - self._tracer = trace.get_tracer( - __name__, - __version__, - tracer_provider=_InstrumentedFalconAPI._tracer_provider, - ) trace_middleware = _TraceMiddleware( self._tracer, kwargs.get("traced_request_attributes") ) From 7ee6846093816ad929dcc6d67ee03bea41352755 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Wed, 14 Apr 2021 00:40:59 +0530 Subject: [PATCH 25/32] Recreate tox env --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index d2244b48ef..bd712f69fd 100644 --- a/tox.ini +++ b/tox.ini @@ -319,7 +319,7 @@ commands = [testenv:lint] basepython: python3.8 -recreate = False +recreate = True deps = -c dev-requirements.txt flaky From c5376192e7f9cef70cd018cda0af853658e30ae4 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Thu, 15 Apr 2021 20:13:17 +0530 Subject: [PATCH 26/32] Fix lint --- .../src/opentelemetry/instrumentation/wsgi/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py index 0d8322bde4..2281694d1f 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py @@ -195,7 +195,9 @@ class OpenTelemetryMiddleware: globally configured one is used. """ - def __init__(self, wsgi, request_hook=None, response_hook=None, tracer_provider=None): + def __init__( + self, wsgi, request_hook=None, response_hook=None, tracer_provider=None + ): self.wsgi = wsgi self.tracer = trace.get_tracer(__name__, __version__, tracer_provider) self.request_hook = request_hook From eb23f946b4b295b15c8aff1981792a7430baf868 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Thu, 15 Apr 2021 23:21:42 +0530 Subject: [PATCH 27/32] Fix CI --- .github/workflows/test.yml | 4 ++-- .../src/opentelemetry/instrumentation/wsgi/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e9c5e3eeda..ba06aaab57 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,7 +44,7 @@ jobs: uses: actions/cache@v2 with: path: .tox - key: tox-cache-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} + key: tox-cache-v2-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} - name: run tox run: tox -f ${{ matrix.python-version }}-${{ matrix.package }} -- --benchmark-json=${{ env.RUN_MATRIX_COMBINATION }}-benchmark.json - name: Find and merge benchmarks @@ -98,6 +98,6 @@ jobs: uses: actions/cache@v2 with: path: .tox - key: tox-cache-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt', 'docs-requirements.txt') }} + key: tox-cache-v2-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt', 'docs-requirements.txt') }} - name: run tox run: tox -e ${{ matrix.tox-environment }} diff --git a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py index 2281694d1f..2bfd93ce50 100644 --- a/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-wsgi/src/opentelemetry/instrumentation/wsgi/__init__.py @@ -191,7 +191,7 @@ class OpenTelemetryMiddleware: response_hook: Optional callback which is called with the server span, WSGI environ, status_code and response_headers for every incoming request. - tracer_provider: Optional tracer provider to use. If omitted the current + tracer_provider: Optional tracer provider to use. If omitted the current globally configured one is used. """ From 8e3deccec6c5bda0a10436844659215089fec2b4 Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Thu, 15 Apr 2021 23:25:35 +0530 Subject: [PATCH 28/32] Remove docstring --- .../src/opentelemetry/instrumentation/aiopg/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py index 31a2c32535..c5b405d37f 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py @@ -95,8 +95,6 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. - tracer_provider: The optional tracer provider to use. If omitted - the current globally configured one is used. Returns: An instrumented connection. From 90b62ca28c120e0d016a96a6dfdc61dba4b3044b Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Thu, 15 Apr 2021 23:29:57 +0530 Subject: [PATCH 29/32] Update docstring --- .../src/opentelemetry/instrumentation/aiopg/__init__.py | 2 ++ .../src/opentelemetry/instrumentation/asgi/__init__.py | 2 +- .../src/opentelemetry/instrumentation/mysql/__init__.py | 2 +- .../src/opentelemetry/instrumentation/pymysql/__init__.py | 2 +- .../src/opentelemetry/instrumentation/sqlite3/__init__.py | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py index c5b405d37f..2cbcbbbcbe 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/__init__.py @@ -95,6 +95,8 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. + tracer_provider: The optional tracer provider to use. If omitted + the current globally configured one is used. Returns: An instrumented connection. diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index 2eaf4c644a..ce34aeaef8 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -165,7 +165,7 @@ class OpenTelemetryMiddleware: dictionary with any additional span attributes to set. Optional: Defaults to get_default_span_details. tracer_provider: The optional tracer provider to use. If omitted - the current globally configured one is used. + the current globally configured one is used. """ def __init__( diff --git a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py b/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py index 4d7a321d1d..97be537632 100644 --- a/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-mysql/src/opentelemetry/instrumentation/mysql/__init__.py @@ -83,7 +83,7 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. tracer_provider: The optional tracer provider to use. If omitted - the current globally configured one is used. + the current globally configured one is used. Returns: An instrumented connection. diff --git a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py index 6db3334ab9..967586ca18 100644 --- a/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-pymysql/src/opentelemetry/instrumentation/pymysql/__init__.py @@ -84,7 +84,7 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. tracer_provider: The optional tracer provider to use. If omitted - the current globally configured one is used. + the current globally configured one is used. Returns: An instrumented connection. diff --git a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py index 8fdcfc82c2..1dea7375f1 100644 --- a/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-sqlite3/src/opentelemetry/instrumentation/sqlite3/__init__.py @@ -80,7 +80,7 @@ def instrument_connection(self, connection, tracer_provider=None): Args: connection: The connection to instrument. tracer_provider: The optional tracer provider to use. If omitted - the current globally configured one is used. + the current globally configured one is used. Returns: An instrumented connection. From fc0fb70a1044043505f54534ec0507dc3e7f669f Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Thu, 15 Apr 2021 23:33:25 +0530 Subject: [PATCH 30/32] Revert test.yml --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ba06aaab57..e9c5e3eeda 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,7 +44,7 @@ jobs: uses: actions/cache@v2 with: path: .tox - key: tox-cache-v2-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} + key: tox-cache-${{ env.RUN_MATRIX_COMBINATION }}-${{ hashFiles('tox.ini', 'dev-requirements.txt') }} - name: run tox run: tox -f ${{ matrix.python-version }}-${{ matrix.package }} -- --benchmark-json=${{ env.RUN_MATRIX_COMBINATION }}-benchmark.json - name: Find and merge benchmarks @@ -98,6 +98,6 @@ jobs: uses: actions/cache@v2 with: path: .tox - key: tox-cache-v2-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt', 'docs-requirements.txt') }} + key: tox-cache-${{ matrix.tox-environment }}-${{ hashFiles('tox.ini', 'dev-requirements.txt', 'docs-requirements.txt') }} - name: run tox run: tox -e ${{ matrix.tox-environment }} From 04eb555b3fca77f6ed67840cec65eeda24451fbf Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Thu, 15 Apr 2021 23:40:33 +0530 Subject: [PATCH 31/32] Revert tox.ini --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index bd712f69fd..54bd2abc41 100644 --- a/tox.ini +++ b/tox.ini @@ -319,7 +319,7 @@ commands = [testenv:lint] basepython: python3.8 -recreate = True +recreate = False deps = -c dev-requirements.txt flaky From 42d83513d7dfd8ddaf22fbe9f56800209136849e Mon Sep 17 00:00:00 2001 From: Srikanth Chekuri Date: Tue, 27 Apr 2021 20:21:12 +0530 Subject: [PATCH 32/32] Fix lint --- .../instrumentation/django/middleware.py | 2 +- opentelemetry-instrumentation/setup.py | 4 +--- .../instrumentation/propagators.py | 4 +--- .../tests/test_bootstrap.py | 5 +---- .../tests/test_utils.py | 20 ++++--------------- 5 files changed, 8 insertions(+), 27 deletions(-) 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 1ab38eb8ff..f37372d721 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -31,7 +31,7 @@ ) from opentelemetry.propagate import extract from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace import Span, SpanKind, get_tracer, use_span +from opentelemetry.trace import Span, SpanKind, use_span from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs try: diff --git a/opentelemetry-instrumentation/setup.py b/opentelemetry-instrumentation/setup.py index d4f84f738b..fb3c8ff9f1 100644 --- a/opentelemetry-instrumentation/setup.py +++ b/opentelemetry-instrumentation/setup.py @@ -24,6 +24,4 @@ with open(VERSION_FILENAME) as f: exec(f.read(), PACKAGE_INFO) -setuptools.setup( - version=PACKAGE_INFO["__version__"], -) +setuptools.setup(version=PACKAGE_INFO["__version__"],) diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/propagators.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/propagators.py index 2fb246c9d9..8fe6b45d90 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/propagators.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/propagators.py @@ -122,7 +122,5 @@ def inject( ), ) setter.set( - carrier, - _HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS, - header_name, + carrier, _HTTP_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS, header_name, ) diff --git a/opentelemetry-instrumentation/tests/test_bootstrap.py b/opentelemetry-instrumentation/tests/test_bootstrap.py index de978eb6d5..e5a1a86dda 100644 --- a/opentelemetry-instrumentation/tests/test_bootstrap.py +++ b/opentelemetry-instrumentation/tests/test_bootstrap.py @@ -23,10 +23,7 @@ def sample_packages(packages, rate): - sampled = sample( - list(packages), - int(len(packages) * rate), - ) + sampled = sample(list(packages), int(len(packages) * rate),) return {k: v for k, v in packages.items() if k in sampled} diff --git a/opentelemetry-instrumentation/tests/test_utils.py b/opentelemetry-instrumentation/tests/test_utils.py index e5246335c9..273c6f085c 100644 --- a/opentelemetry-instrumentation/tests/test_utils.py +++ b/opentelemetry-instrumentation/tests/test_utils.py @@ -31,24 +31,12 @@ def test_http_status_to_status_code(self): (HTTPStatus.UNAUTHORIZED, StatusCode.ERROR), (HTTPStatus.FORBIDDEN, StatusCode.ERROR), (HTTPStatus.NOT_FOUND, StatusCode.ERROR), - ( - HTTPStatus.UNPROCESSABLE_ENTITY, - StatusCode.ERROR, - ), - ( - HTTPStatus.TOO_MANY_REQUESTS, - StatusCode.ERROR, - ), + (HTTPStatus.UNPROCESSABLE_ENTITY, StatusCode.ERROR,), + (HTTPStatus.TOO_MANY_REQUESTS, StatusCode.ERROR,), (HTTPStatus.NOT_IMPLEMENTED, StatusCode.ERROR), (HTTPStatus.SERVICE_UNAVAILABLE, StatusCode.ERROR), - ( - HTTPStatus.GATEWAY_TIMEOUT, - StatusCode.ERROR, - ), - ( - HTTPStatus.HTTP_VERSION_NOT_SUPPORTED, - StatusCode.ERROR, - ), + (HTTPStatus.GATEWAY_TIMEOUT, StatusCode.ERROR,), + (HTTPStatus.HTTP_VERSION_NOT_SUPPORTED, StatusCode.ERROR,), (600, StatusCode.ERROR), (99, StatusCode.ERROR), ):