From 9695c86d464ecab60f9aa38de40a7b7b51481b27 Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Mon, 17 Feb 2020 22:21:56 -0800 Subject: [PATCH 1/7] Adding trace.get_tracer convenience function It's fairly common to need to retrieve tracers, and as such adding the additional tracer_source() call to every retrieval of a tracer can add to a lot of extra boilerplate at minimal semantic value. It would be uncommon for one to use multiple trace_source objects, as typically one would want all tracers to be created and behave in a similar way (e.g. passed to the same span processor). --- README.md | 2 +- examples/basic_tracer/tracer.py | 2 +- examples/http/server.py | 2 +- .../opentelemetry_example_app/flask_example.py | 2 +- examples/opentracing/main.py | 2 +- ext/opentelemetry-ext-dbapi/README.rst | 2 +- .../src/opentelemetry/ext/flask/__init__.py | 2 +- ext/opentelemetry-ext-jaeger/README.rst | 2 +- .../examples/jaeger_exporter_example.py | 2 +- .../ext/opentracing_shim/__init__.py | 2 +- ext/opentelemetry-ext-psycopg2/README.rst | 2 +- .../src/opentelemetry/ext/wsgi/__init__.py | 2 +- ext/opentelemetry-ext-zipkin/README.rst | 2 +- .../src/opentelemetry/trace/__init__.py | 15 ++++++++++++++- 14 files changed, 27 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 97a76e1f0c7..b7cda2ddb06 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ trace.set_preferred_tracer_source_implementation(lambda T: TracerSource()) trace.tracer_source().add_span_processor( SimpleExportSpanProcessor(ConsoleSpanExporter()) ) -tracer = trace.tracer_source().get_tracer(__name__) +tracer = trace.get_tracer(__name__) with tracer.start_as_current_span('foo'): with tracer.start_as_current_span('bar'): with tracer.start_as_current_span('baz'): diff --git a/examples/basic_tracer/tracer.py b/examples/basic_tracer/tracer.py index 5093280a5a6..a6b33a01b37 100755 --- a/examples/basic_tracer/tracer.py +++ b/examples/basic_tracer/tracer.py @@ -41,7 +41,7 @@ # We tell OpenTelemetry who it is that is creating spans. In this case, we have # no real name (no setup.py), so we make one up. If we had a version, we would # also specify it here. -tracer = trace.tracer_source().get_tracer(__name__) +tracer = trace.get_tracer(__name__) # SpanExporter receives the spans and send them to the target location. span_processor = BatchExportSpanProcessor(exporter) diff --git a/examples/http/server.py b/examples/http/server.py index 68e3d952b0d..8d1aea1e06a 100755 --- a/examples/http/server.py +++ b/examples/http/server.py @@ -42,7 +42,7 @@ # The preferred tracer implementation must be set, as the opentelemetry-api # defines the interface with a no-op implementation. trace.set_preferred_tracer_source_implementation(lambda T: TracerSource()) -tracer = trace.tracer_source().get_tracer(__name__) +tracer = trace.get_tracer(__name__) # SpanExporter receives the spans and send them to the target location. span_processor = BatchExportSpanProcessor(exporter) diff --git a/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py b/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py index f7a9872b6b6..62795751d3b 100644 --- a/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py +++ b/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py @@ -67,7 +67,7 @@ def hello(): version = pkg_resources.get_distribution( "opentelemetry-example-app" ).version - tracer = trace.tracer_source().get_tracer(__name__, version) + tracer = trace.get_tracer(__name__, version) with tracer.start_as_current_span("example-request"): requests.get("http://www.example.com") return "hello" diff --git a/examples/opentracing/main.py b/examples/opentracing/main.py index 81d23f10e46..922e1263b50 100755 --- a/examples/opentracing/main.py +++ b/examples/opentracing/main.py @@ -28,7 +28,7 @@ redis_cache = RedisCache(opentracing_tracer) # Appication code uses an OpenTelemetry Tracer as usual. -tracer = trace.tracer_source().get_tracer(__name__) +tracer = trace.get_tracer(__name__) @redis_cache diff --git a/ext/opentelemetry-ext-dbapi/README.rst b/ext/opentelemetry-ext-dbapi/README.rst index 3618453823d..b0bdbdd3126 100644 --- a/ext/opentelemetry-ext-dbapi/README.rst +++ b/ext/opentelemetry-ext-dbapi/README.rst @@ -15,7 +15,7 @@ Usage from opentelemetry.ext.dbapi import trace_integration trace.set_preferred_tracer_source_implementation(lambda T: TracerSource()) - tracer = trace.tracer_source().get_tracer(__name__) + tracer = trace.get_tracer(__name__) # Ex: mysql.connector trace_integration(tracer_source(), mysql.connector, "connect", "mysql") diff --git a/ext/opentelemetry-ext-flask/src/opentelemetry/ext/flask/__init__.py b/ext/opentelemetry-ext-flask/src/opentelemetry/ext/flask/__init__.py index 4bf0cc8c681..aa9217c00ea 100644 --- a/ext/opentelemetry-ext-flask/src/opentelemetry/ext/flask/__init__.py +++ b/ext/opentelemetry-ext-flask/src/opentelemetry/ext/flask/__init__.py @@ -61,7 +61,7 @@ def _before_flask_request(): otel_wsgi.get_header_from_environ, environ ) - tracer = trace.tracer_source().get_tracer(__name__, __version__) + tracer = trace.get_tracer(__name__, __version__) attributes = otel_wsgi.collect_request_attributes(environ) if flask_request.url_rule: diff --git a/ext/opentelemetry-ext-jaeger/README.rst b/ext/opentelemetry-ext-jaeger/README.rst index 80306aa59bf..00339cb37f8 100644 --- a/ext/opentelemetry-ext-jaeger/README.rst +++ b/ext/opentelemetry-ext-jaeger/README.rst @@ -36,7 +36,7 @@ gRPC is still not supported by this implementation. from opentelemetry.sdk.trace.export import BatchExportSpanProcessor trace.set_preferred_tracer_source_implementation(lambda T: TracerSource()) - tracer = trace.tracer_source().get_tracer(__name__) + tracer = trace.get_tracer(__name__) # create a JaegerSpanExporter jaeger_exporter = jaeger.JaegerSpanExporter( diff --git a/ext/opentelemetry-ext-jaeger/examples/jaeger_exporter_example.py b/ext/opentelemetry-ext-jaeger/examples/jaeger_exporter_example.py index 9eec28dc75e..6b0646bb99d 100644 --- a/ext/opentelemetry-ext-jaeger/examples/jaeger_exporter_example.py +++ b/ext/opentelemetry-ext-jaeger/examples/jaeger_exporter_example.py @@ -6,7 +6,7 @@ from opentelemetry.sdk.trace.export import BatchExportSpanProcessor trace.set_preferred_tracer_source_implementation(lambda T: TracerSource()) -tracer = trace.tracer_source().get_tracer(__name__) +tracer = trace.get_tracer(__name__) # create a JaegerSpanExporter jaeger_exporter = jaeger.JaegerSpanExporter( diff --git a/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/__init__.py b/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/__init__.py index b7753754db0..11ef52ec796 100644 --- a/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/__init__.py +++ b/ext/opentelemetry-ext-opentracing-shim/src/opentelemetry/ext/opentracing_shim/__init__.py @@ -36,7 +36,7 @@ trace.set_preferred_tracer_source_implementation(lambda T: TracerSource()) # Create an OpenTelemetry Tracer. - otel_tracer = trace.tracer_source().get_tracer(__name__) + otel_tracer = trace.get_tracer(__name__) # Create an OpenTracing shim. shim = create_tracer(otel_tracer) diff --git a/ext/opentelemetry-ext-psycopg2/README.rst b/ext/opentelemetry-ext-psycopg2/README.rst index d7599492ac4..9399c80facc 100644 --- a/ext/opentelemetry-ext-psycopg2/README.rst +++ b/ext/opentelemetry-ext-psycopg2/README.rst @@ -16,7 +16,7 @@ Usage from opentelemetry.trace.ext.psycopg2 import trace_integration trace.set_preferred_tracer_source_implementation(lambda T: TracerSource()) - tracer = trace.tracer_source().get_tracer(__name__) + tracer = trace.get_tracer(__name__) trace_integration(tracer) cnx = psycopg2.connect(database='Database') cursor = cnx.cursor() diff --git a/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py b/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py index e6751f34ced..37a3a0e9e0d 100644 --- a/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py +++ b/ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py @@ -162,7 +162,7 @@ class OpenTelemetryMiddleware: def __init__(self, wsgi): self.wsgi = wsgi - self.tracer = trace.tracer_source().get_tracer(__name__, __version__) + self.tracer = trace.get_tracer(__name__, __version__) @staticmethod def _create_start_response(span, start_response): diff --git a/ext/opentelemetry-ext-zipkin/README.rst b/ext/opentelemetry-ext-zipkin/README.rst index f91d0c2c6a7..57dd4b7faa1 100644 --- a/ext/opentelemetry-ext-zipkin/README.rst +++ b/ext/opentelemetry-ext-zipkin/README.rst @@ -34,7 +34,7 @@ This exporter always send traces to the configured Zipkin collector using HTTP. from opentelemetry.sdk.trace.export import BatchExportSpanProcessor trace.set_preferred_tracer_source_implementation(lambda T: TracerSource()) - tracer = trace.tracer_source().get_tracer(__name__) + tracer = trace.get_tracer(__name__) # create a ZipkinSpanExporter zipkin_exporter = zipkin.ZipkinSpanExporter( diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 014e82b3bc2..d3ba400d046 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -36,7 +36,7 @@ from opentelemetry import trace - tracer = trace.tracer_source().get_tracer(__name__) + tracer = trace.get_tracer(__name__) # Create a new root span, set it as the current span in context with tracer.start_as_current_span("parent"): @@ -647,6 +647,19 @@ def use_span( _TRACER_SOURCE_FACTORY = None # type: typing.Optional[ImplementationFactory] +def get_tracer( + instrumenting_module_name: str, instrumenting_library_version: str = "" +) -> "Tracer": + """Returns a `Tracer` for use by the given instrumentation library. + + This function is a convenience wrapper for + `opentelemetry.trace.tracer_source().get_tracer` + """ + return tracer_source().get_tracer( + instrumenting_module_name, instrumenting_library_version + ) + + def tracer_source() -> TracerSource: """Gets the current global :class:`~.TracerSource` object. From 5f2b4d7ad7b34493b84ef91ba493fee91d6c8be7 Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Tue, 18 Feb 2020 10:28:35 -0800 Subject: [PATCH 2/7] Adding tests for trace.get_tracer --- .../src/opentelemetry/trace/__init__.py | 7 +++ opentelemetry-api/tests/trace/test_globals.py | 43 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 opentelemetry-api/tests/trace/test_globals.py diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index d3ba400d046..51ac572cd0f 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -68,6 +68,7 @@ import abc import enum +import logging import types as python_types import typing from contextlib import contextmanager @@ -75,6 +76,8 @@ from opentelemetry.trace.status import Status from opentelemetry.util import loader, types +logger = logging.getLogger(__name__) + # TODO: quarantine ParentSpan = typing.Optional[typing.Union["Span", "SpanContext"]] @@ -676,6 +679,10 @@ def tracer_source() -> TracerSource: except TypeError: # if we raised an exception trying to instantiate an # abstract class, default to no-op tracer impl + logger.warning( + "Unable to instantiate TracerSource from tracer source factory.", + exc_info=True, + ) _TRACER_SOURCE = DefaultTracerSource() del _TRACER_SOURCE_FACTORY diff --git a/opentelemetry-api/tests/trace/test_globals.py b/opentelemetry-api/tests/trace/test_globals.py new file mode 100644 index 00000000000..ac56e88d8e4 --- /dev/null +++ b/opentelemetry-api/tests/trace/test_globals.py @@ -0,0 +1,43 @@ +import importlib +import unittest + +from opentelemetry import trace + + +class TestGlobals(unittest.TestCase): + def setUp(self): + importlib.reload(trace) + + # this class has to be declared after the importlib + # reload, or else it will inherit from an old + # TracerSource, rather than the new TraceSource ABC. + # created from reload. + + static_tracer = trace.DefaultTracer() + + class DummyTracerSource(trace.TracerSource): + """TraceSource used for testing""" + + def get_tracer( + self, + instrumenting_module_name: str, + instrumenting_library_version: str = "", + ) -> trace.Tracer: + # pylint:disable=no-self-use,unused-argument + return static_tracer + + trace.set_preferred_tracer_source_implementation( + lambda _: DummyTracerSource() + ) + + @staticmethod + def teardown(): + importlib.reload(trace) + + def test_get_tracer(self): + """trace.get_tracer should proxy to the + global tracer sourceA + """ + from_global_api = trace.get_tracer("foo") + from_tracer_api = trace.tracer_source().get_tracer("foo") + self.assertEqual(from_global_api, from_tracer_api) From 26a7fc117dd8bd78084b52fed37eeedd6a29a06b Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Tue, 18 Feb 2020 19:03:46 -0800 Subject: [PATCH 3/7] Update opentelemetry-api/tests/trace/test_globals.py Co-Authored-By: Chris Kleinknecht --- opentelemetry-api/tests/trace/test_globals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/tests/trace/test_globals.py b/opentelemetry-api/tests/trace/test_globals.py index ac56e88d8e4..eb3189f0999 100644 --- a/opentelemetry-api/tests/trace/test_globals.py +++ b/opentelemetry-api/tests/trace/test_globals.py @@ -35,7 +35,7 @@ def teardown(): importlib.reload(trace) def test_get_tracer(self): - """trace.get_tracer should proxy to the + """trace.get_tracer should proxy to the global tracer source.""" global tracer sourceA """ from_global_api = trace.get_tracer("foo") From 634426a0f0f14798e052ac8b4a79146edccbc291 Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Tue, 18 Feb 2020 19:03:54 -0800 Subject: [PATCH 4/7] Update opentelemetry-api/tests/trace/test_globals.py Co-Authored-By: Chris Kleinknecht --- opentelemetry-api/tests/trace/test_globals.py | 1 - 1 file changed, 1 deletion(-) diff --git a/opentelemetry-api/tests/trace/test_globals.py b/opentelemetry-api/tests/trace/test_globals.py index eb3189f0999..06d96974fe7 100644 --- a/opentelemetry-api/tests/trace/test_globals.py +++ b/opentelemetry-api/tests/trace/test_globals.py @@ -36,7 +36,6 @@ def teardown(): def test_get_tracer(self): """trace.get_tracer should proxy to the global tracer source.""" - global tracer sourceA """ from_global_api = trace.get_tracer("foo") from_tracer_api = trace.tracer_source().get_tracer("foo") From 182f241490881d1f6a5f1e2f252461d7516b8742 Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Tue, 18 Feb 2020 19:38:31 -0800 Subject: [PATCH 5/7] fixing syntax after taking suggestions --- opentelemetry-api/src/opentelemetry/trace/__init__.py | 2 +- opentelemetry-api/tests/trace/test_globals.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 51ac572cd0f..f0b1fda1b33 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -656,7 +656,7 @@ def get_tracer( """Returns a `Tracer` for use by the given instrumentation library. This function is a convenience wrapper for - `opentelemetry.trace.tracer_source().get_tracer` + opentelemetry.trace.tracer_source().get_tracer """ return tracer_source().get_tracer( instrumenting_module_name, instrumenting_library_version diff --git a/opentelemetry-api/tests/trace/test_globals.py b/opentelemetry-api/tests/trace/test_globals.py index 06d96974fe7..eed744468a9 100644 --- a/opentelemetry-api/tests/trace/test_globals.py +++ b/opentelemetry-api/tests/trace/test_globals.py @@ -31,12 +31,11 @@ def get_tracer( ) @staticmethod - def teardown(): + def tearDown(): importlib.reload(trace) def test_get_tracer(self): """trace.get_tracer should proxy to the global tracer source.""" - """ from_global_api = trace.get_tracer("foo") from_tracer_api = trace.tracer_source().get_tracer("foo") self.assertEqual(from_global_api, from_tracer_api) From b4ec34eb4ed30a3bc97777c9ad80fea22e27618b Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Tue, 18 Feb 2020 19:55:02 -0800 Subject: [PATCH 6/7] fixing lint errors --- opentelemetry-api/tests/trace/test_globals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/tests/trace/test_globals.py b/opentelemetry-api/tests/trace/test_globals.py index eed744468a9..be969a5ef7a 100644 --- a/opentelemetry-api/tests/trace/test_globals.py +++ b/opentelemetry-api/tests/trace/test_globals.py @@ -31,7 +31,7 @@ def get_tracer( ) @staticmethod - def tearDown(): + def tearDown() -> None: importlib.reload(trace) def test_get_tracer(self): From 252892fa347694fda83735420b521706b844e1fa Mon Sep 17 00:00:00 2001 From: Yusuke Tsutsumi Date: Wed, 19 Feb 2020 09:35:56 -0800 Subject: [PATCH 7/7] switching assertEquals to assertIs --- opentelemetry-api/tests/trace/test_globals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/tests/trace/test_globals.py b/opentelemetry-api/tests/trace/test_globals.py index be969a5ef7a..2ad74fb2ab3 100644 --- a/opentelemetry-api/tests/trace/test_globals.py +++ b/opentelemetry-api/tests/trace/test_globals.py @@ -38,4 +38,4 @@ def test_get_tracer(self): """trace.get_tracer should proxy to the global tracer source.""" from_global_api = trace.get_tracer("foo") from_tracer_api = trace.tracer_source().get_tracer("foo") - self.assertEqual(from_global_api, from_tracer_api) + self.assertIs(from_global_api, from_tracer_api)