From 3a0a966b11e3588ecdc34c7d3586d10060ef9f59 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Mon, 9 Mar 2020 18:50:50 -0600 Subject: [PATCH 01/28] Add configuration manager --- docs/api/api.rst | 1 - docs/api/util.loader.rst | 4 - docs/examples/basic_tracer/tracer.py | 7 +- docs/examples/http/server.py | 8 +- docs/examples/http/tests/test_http.py | 10 +- docs/examples/http/tracer_client.py | 6 +- docs/examples/metrics/observer_example.py | 3 +- docs/examples/metrics/prometheus.py | 3 +- docs/examples/metrics/record.py | 5 +- docs/examples/metrics/simple_example.py | 3 +- .../flask_example.py | 9 +- docs/examples/opentracing/main.py | 5 +- examples/basic_tracer/tests/conftest.py | 25 +++ examples/http/tests/conftest.py | 25 +++ .../tests/conftest.py | 25 +++ ext/opentelemetry-ext-dbapi/README.rst | 1 - ext/opentelemetry-ext-flask/tests/conftest.py | 25 +++ ext/opentelemetry-ext-jaeger/README.rst | 2 - .../examples/jaeger_exporter_example.py | 4 +- .../ext/opentracing_shim/__init__.py | 4 - .../tests/conftest.py | 25 +++ .../tests/test_shim.py | 11 +- ext/opentelemetry-ext-prometheus/README.rst | 3 +- .../tests/conftest.py | 25 +++ .../tests/test_prometheus_exporter.py | 8 +- ext/opentelemetry-ext-psycopg2/README.rst | 2 - .../ext/testutil/wsgitestutil.py | 7 +- ext/opentelemetry-ext-wsgi/tests/conftest.py | 25 +++ ext/opentelemetry-ext-zipkin/README.rst | 2 - opentelemetry-api/setup.py | 44 ++++- .../opentelemetry/configuration/__init__.py | 78 ++++++++ .../configuration/opentelemetry_python.json | 4 + .../src/opentelemetry/configuration/py.typed | 0 .../src/opentelemetry/metrics/__init__.py | 77 +++----- .../src/opentelemetry/trace/__init__.py | 83 +++----- .../src/opentelemetry/util/loader.py | 182 ------------------ .../tests/configuration/__init__.py | 0 .../tests/configuration/test_configuration.py | 85 ++++++++ opentelemetry-api/tests/mypysmoke.py | 2 +- opentelemetry-api/tests/test_loader.py | 112 ----------- opentelemetry-api/tests/trace/test_globals.py | 36 +--- opentelemetry-sdk/setup.py | 8 + tests/w3c_tracecontext_validation_server.py | 9 +- 43 files changed, 477 insertions(+), 526 deletions(-) delete mode 100644 docs/api/util.loader.rst create mode 100644 examples/basic_tracer/tests/conftest.py create mode 100644 examples/http/tests/conftest.py create mode 100644 examples/opentelemetry-example-app/tests/conftest.py create mode 100644 ext/opentelemetry-ext-flask/tests/conftest.py create mode 100644 ext/opentelemetry-ext-opentracing-shim/tests/conftest.py create mode 100644 ext/opentelemetry-ext-prometheus/tests/conftest.py create mode 100644 ext/opentelemetry-ext-wsgi/tests/conftest.py create mode 100644 opentelemetry-api/src/opentelemetry/configuration/__init__.py create mode 100644 opentelemetry-api/src/opentelemetry/configuration/opentelemetry_python.json create mode 100644 opentelemetry-api/src/opentelemetry/configuration/py.typed delete mode 100644 opentelemetry-api/src/opentelemetry/util/loader.py create mode 100644 opentelemetry-api/tests/configuration/__init__.py create mode 100644 opentelemetry-api/tests/configuration/test_configuration.py delete mode 100644 opentelemetry-api/tests/test_loader.py diff --git a/docs/api/api.rst b/docs/api/api.rst index 3b15cd0d36b..6ae631147a2 100644 --- a/docs/api/api.rst +++ b/docs/api/api.rst @@ -9,4 +9,3 @@ OpenTelemetry Python API context metrics trace - util.loader \ No newline at end of file diff --git a/docs/api/util.loader.rst b/docs/api/util.loader.rst deleted file mode 100644 index 079d2e4a38d..00000000000 --- a/docs/api/util.loader.rst +++ /dev/null @@ -1,4 +0,0 @@ -opentelemetry.util.loader module -================================ - -.. automodule:: opentelemetry.util.loader diff --git a/docs/examples/basic_tracer/tracer.py b/docs/examples/basic_tracer/tracer.py index a454eab7a96..a8ba537cc9c 100755 --- a/docs/examples/basic_tracer/tracer.py +++ b/docs/examples/basic_tracer/tracer.py @@ -17,7 +17,6 @@ import os from opentelemetry import trace -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ( BatchExportSpanProcessor, ConsoleSpanExporter, @@ -45,10 +44,6 @@ print("Using ConsoleSpanExporter") exporter = ConsoleSpanExporter() -# The preferred tracer implementation must be set, as the opentelemetry-api -# defines the interface with a no-op implementation. -trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) - # 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. @@ -57,7 +52,7 @@ # SpanExporter receives the spans and send them to the target location. span_processor = BatchExportSpanProcessor(exporter) -trace.tracer_provider().add_span_processor(span_processor) +trace.get_tracer_provider().add_span_processor(span_processor) with tracer.start_as_current_span("foo"): with tracer.start_as_current_span("bar"): with tracer.start_as_current_span("baz"): diff --git a/docs/examples/http/server.py b/docs/examples/http/server.py index 50bc566b77c..d706a269606 100755 --- a/docs/examples/http/server.py +++ b/docs/examples/http/server.py @@ -22,7 +22,6 @@ from opentelemetry import trace from opentelemetry.ext import http_requests from opentelemetry.ext.wsgi import OpenTelemetryMiddleware -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ( BatchExportSpanProcessor, ConsoleSpanExporter, @@ -39,19 +38,16 @@ else: exporter = ConsoleSpanExporter() -# The preferred tracer implementation must be set, as the opentelemetry-api -# defines the interface with a no-op implementation. -trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) tracer = trace.get_tracer(__name__) # SpanExporter receives the spans and send them to the target location. span_processor = BatchExportSpanProcessor(exporter) -trace.tracer_provider().add_span_processor(span_processor) +trace.get_tracer_provider().add_span_processor(span_processor) # Integrations are the glue that binds the OpenTelemetry API and the # frameworks and libraries that are used together, automatically creating # Spans and propagating context as appropriate. -http_requests.enable(trace.tracer_provider()) +http_requests.enable(trace.get_tracer_provider()) app = flask.Flask(__name__) app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app) diff --git a/docs/examples/http/tests/test_http.py b/docs/examples/http/tests/test_http.py index 0ae81fe7de7..0444e8d67d6 100644 --- a/docs/examples/http/tests/test_http.py +++ b/docs/examples/http/tests/test_http.py @@ -19,11 +19,10 @@ class TestHttpExample(unittest.TestCase): - @classmethod - def setup_class(cls): + def setUp(self): dirpath = os.path.dirname(os.path.realpath(__file__)) server_script = "{}/../server.py".format(dirpath) - cls.server = subprocess.Popen([sys.executable, server_script]) + self.server = subprocess.Popen([sys.executable, server_script]) sleep(1) def test_http(self): @@ -34,6 +33,5 @@ def test_http(self): ).decode() self.assertIn('name="/"', output) - @classmethod - def teardown_class(cls): - cls.server.terminate() + def tearDown(self): + self.server.terminate() diff --git a/docs/examples/http/tracer_client.py b/docs/examples/http/tracer_client.py index 6fd0a726a42..3ae6dc9ffed 100755 --- a/docs/examples/http/tracer_client.py +++ b/docs/examples/http/tracer_client.py @@ -20,7 +20,6 @@ from opentelemetry import trace from opentelemetry.ext import http_requests -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ( BatchExportSpanProcessor, ConsoleSpanExporter, @@ -37,10 +36,7 @@ else: exporter = ConsoleSpanExporter() -# The preferred tracer implementation must be set, as the opentelemetry-api -# defines the interface with a no-op implementation. -trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) -tracer_provider = trace.tracer_provider() +tracer_provider = trace.get_tracer_provider() # SpanExporter receives the spans and send them to the target location. span_processor = BatchExportSpanProcessor(exporter) diff --git a/docs/examples/metrics/observer_example.py b/docs/examples/metrics/observer_example.py index aff25ee476c..7f5614d058e 100644 --- a/docs/examples/metrics/observer_example.py +++ b/docs/examples/metrics/observer_example.py @@ -19,7 +19,7 @@ import psutil from opentelemetry import metrics -from opentelemetry.sdk.metrics import LabelSet, MeterProvider +from opentelemetry.sdk.metrics import LabelSet from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter from opentelemetry.sdk.metrics.export.batcher import UngroupedBatcher from opentelemetry.sdk.metrics.export.controller import PushController @@ -27,7 +27,6 @@ # Configure a stateful batcher batcher = UngroupedBatcher(stateful=True) -metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) meter = metrics.get_meter(__name__) # Exporter to export metrics to the console diff --git a/docs/examples/metrics/prometheus.py b/docs/examples/metrics/prometheus.py index 4d30f8abcca..3c9a33f32a3 100644 --- a/docs/examples/metrics/prometheus.py +++ b/docs/examples/metrics/prometheus.py @@ -21,14 +21,13 @@ from opentelemetry import metrics from opentelemetry.ext.prometheus import PrometheusMetricsExporter -from opentelemetry.sdk.metrics import Counter, MeterProvider +from opentelemetry.sdk.metrics import Counter from opentelemetry.sdk.metrics.export.controller import PushController # Start Prometheus client start_http_server(port=8000, addr="localhost") # Meter is responsible for creating and recording metrics -metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) meter = metrics.get_meter(__name__) # exporter to export metrics to Prometheus prefix = "MyAppPrefix" diff --git a/docs/examples/metrics/record.py b/docs/examples/metrics/record.py index d4c3d03d824..948fdf10913 100644 --- a/docs/examples/metrics/record.py +++ b/docs/examples/metrics/record.py @@ -19,13 +19,10 @@ import time from opentelemetry import metrics -from opentelemetry.sdk.metrics import Counter, MeterProvider +from opentelemetry.sdk.metrics import Counter from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter from opentelemetry.sdk.metrics.export.controller import PushController -# The preferred tracer implementation must be set, as the opentelemetry-api -# defines the interface with a no-op implementation. -metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) # Meter is responsible for creating and recording metrics meter = metrics.get_meter(__name__) # exporter to export metrics to the console diff --git a/docs/examples/metrics/simple_example.py b/docs/examples/metrics/simple_example.py index 2b8f5cfac8b..0108d1620b8 100644 --- a/docs/examples/metrics/simple_example.py +++ b/docs/examples/metrics/simple_example.py @@ -23,7 +23,7 @@ import time from opentelemetry import metrics -from opentelemetry.sdk.metrics import Counter, Measure, MeterProvider +from opentelemetry.sdk.metrics import Counter, Measure from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter from opentelemetry.sdk.metrics.export.controller import PushController @@ -44,7 +44,6 @@ def usage(argv): sys.exit(1) # Meter is responsible for creating and recording metrics -metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) # Meter's namespace corresponds to the string passed as the first argument Pass # in True/False to indicate whether the batcher is stateful. True indicates the diff --git a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py index a33b3b58f4c..12d3eed204a 100644 --- a/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py +++ b/docs/examples/opentelemetry-example-app/src/opentelemetry_example_app/flask_example.py @@ -23,7 +23,6 @@ import opentelemetry.ext.http_requests from opentelemetry import trace from opentelemetry.ext.flask import instrument_app -from opentelemetry.sdk.trace import TracerProvider def configure_opentelemetry(flask_app: flask.Flask): @@ -42,12 +41,6 @@ def configure_opentelemetry(flask_app: flask.Flask): """ # Start by configuring all objects required to ensure # a complete end to end workflow. - # The preferred implementation of these objects must be set, - # as the opentelemetry-api defines the interface with a no-op - # implementation. - trace.set_preferred_tracer_provider_implementation( - lambda _: TracerProvider() - ) # Next, we need to configure how the values that are used by # traces and metrics are propagated (such as what specific headers @@ -55,7 +48,7 @@ def configure_opentelemetry(flask_app: flask.Flask): # Integrations are the glue that binds the OpenTelemetry API # and the frameworks and libraries that are used together, automatically # creating Spans and propagating context as appropriate. - opentelemetry.ext.http_requests.enable(trace.tracer_provider()) + opentelemetry.ext.http_requests.enable(trace.get_tracer_provider()) instrument_app(flask_app) diff --git a/docs/examples/opentracing/main.py b/docs/examples/opentracing/main.py index 665099aeeef..0c331ddee35 100755 --- a/docs/examples/opentracing/main.py +++ b/docs/examples/opentracing/main.py @@ -3,13 +3,10 @@ from opentelemetry import trace from opentelemetry.ext import opentracing_shim from opentelemetry.ext.jaeger import JaegerSpanExporter -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import SimpleExportSpanProcessor from rediscache import RedisCache -# Configure the tracer using the default implementation -trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) -tracer_provider = trace.tracer_provider() +tracer_provider = trace.get_tracer_provider() # Configure the tracer to export traces to Jaeger jaeger_exporter = JaegerSpanExporter( diff --git a/examples/basic_tracer/tests/conftest.py b/examples/basic_tracer/tests/conftest.py new file mode 100644 index 00000000000..ff9e5ea43bb --- /dev/null +++ b/examples/basic_tracer/tests/conftest.py @@ -0,0 +1,25 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from os import environ + + +def pytest_sessionstart(session): # pylint: disable=unused-argument + environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" + environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" + + +def pytest_sessionfinish(session): # pylint: disable=unused-argument + environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") + environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/examples/http/tests/conftest.py b/examples/http/tests/conftest.py new file mode 100644 index 00000000000..ff9e5ea43bb --- /dev/null +++ b/examples/http/tests/conftest.py @@ -0,0 +1,25 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from os import environ + + +def pytest_sessionstart(session): # pylint: disable=unused-argument + environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" + environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" + + +def pytest_sessionfinish(session): # pylint: disable=unused-argument + environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") + environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/examples/opentelemetry-example-app/tests/conftest.py b/examples/opentelemetry-example-app/tests/conftest.py new file mode 100644 index 00000000000..ff9e5ea43bb --- /dev/null +++ b/examples/opentelemetry-example-app/tests/conftest.py @@ -0,0 +1,25 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from os import environ + + +def pytest_sessionstart(session): # pylint: disable=unused-argument + environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" + environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" + + +def pytest_sessionfinish(session): # pylint: disable=unused-argument + environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") + environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/ext/opentelemetry-ext-dbapi/README.rst b/ext/opentelemetry-ext-dbapi/README.rst index 33ec8de6f6e..24d4577306f 100644 --- a/ext/opentelemetry-ext-dbapi/README.rst +++ b/ext/opentelemetry-ext-dbapi/README.rst @@ -15,7 +15,6 @@ Usage from opentelemetry.trace import tracer_provider from opentelemetry.ext.dbapi import trace_integration - trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) tracer = trace.get_tracer(__name__) # Ex: mysql.connector trace_integration(tracer_provider(), mysql.connector, "connect", "mysql", "sql") diff --git a/ext/opentelemetry-ext-flask/tests/conftest.py b/ext/opentelemetry-ext-flask/tests/conftest.py new file mode 100644 index 00000000000..ff9e5ea43bb --- /dev/null +++ b/ext/opentelemetry-ext-flask/tests/conftest.py @@ -0,0 +1,25 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from os import environ + + +def pytest_sessionstart(session): # pylint: disable=unused-argument + environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" + environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" + + +def pytest_sessionfinish(session): # pylint: disable=unused-argument + environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") + environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/ext/opentelemetry-ext-jaeger/README.rst b/ext/opentelemetry-ext-jaeger/README.rst index 6813fbdeee8..47549992dba 100644 --- a/ext/opentelemetry-ext-jaeger/README.rst +++ b/ext/opentelemetry-ext-jaeger/README.rst @@ -32,10 +32,8 @@ gRPC is still not supported by this implementation. from opentelemetry import trace from opentelemetry.ext import jaeger - from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchExportSpanProcessor - trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) tracer = trace.get_tracer(__name__) # create a JaegerSpanExporter diff --git a/ext/opentelemetry-ext-jaeger/examples/jaeger_exporter_example.py b/ext/opentelemetry-ext-jaeger/examples/jaeger_exporter_example.py index 81815da935c..1f0c303e065 100644 --- a/ext/opentelemetry-ext-jaeger/examples/jaeger_exporter_example.py +++ b/ext/opentelemetry-ext-jaeger/examples/jaeger_exporter_example.py @@ -2,10 +2,8 @@ from opentelemetry import trace from opentelemetry.ext import jaeger -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchExportSpanProcessor -trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) tracer = trace.get_tracer(__name__) # create a JaegerSpanExporter @@ -26,7 +24,7 @@ span_processor = BatchExportSpanProcessor(jaeger_exporter) # add to the tracer factory -trace.tracer_provider().add_span_processor(span_processor) +trace.get_tracer_provider().add_span_processor(span_processor) # create some spans for testing with tracer.start_as_current_span("foo") as foo: 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 bd9d22678ed..331ed10baf1 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 @@ -29,12 +29,8 @@ import time from opentelemetry import trace - from opentelemetry.sdk.trace import TracerProvider from opentelemetry.ext.opentracing_shim import create_tracer - # Tell OpenTelemetry which Tracer implementation to use. - trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) - # Create an OpenTelemetry Tracer. otel_tracer = trace.get_tracer(__name__) diff --git a/ext/opentelemetry-ext-opentracing-shim/tests/conftest.py b/ext/opentelemetry-ext-opentracing-shim/tests/conftest.py new file mode 100644 index 00000000000..ff9e5ea43bb --- /dev/null +++ b/ext/opentelemetry-ext-opentracing-shim/tests/conftest.py @@ -0,0 +1,25 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from os import environ + + +def pytest_sessionstart(session): # pylint: disable=unused-argument + environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" + environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" + + +def pytest_sessionfinish(session): # pylint: disable=unused-argument + environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") + environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py b/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py index 2a3fe819c9b..8a025be0368 100644 --- a/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py +++ b/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py @@ -25,7 +25,6 @@ from opentelemetry import propagators, trace from opentelemetry.context import Context from opentelemetry.ext.opentracing_shim import util -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.trace.propagation import ( get_span_from_context, set_span_in_context, @@ -44,18 +43,10 @@ class TestShim(TestCase): def setUp(self): """Create an OpenTelemetry tracer and a shim before every test case.""" - self.shim = opentracingshim.create_tracer(trace.tracer_provider()) + self.shim = opentracingshim.create_tracer(trace.get_tracer_provider()) @classmethod def setUpClass(cls): - """Set preferred tracer implementation only once rather than before - every test method. - """ - - trace.set_preferred_tracer_provider_implementation( - lambda T: TracerProvider() - ) - # Save current propagator to be restored on teardown. cls._previous_propagator = propagators.get_global_httptextformat() diff --git a/ext/opentelemetry-ext-prometheus/README.rst b/ext/opentelemetry-ext-prometheus/README.rst index e70332556e2..f7049194a2e 100644 --- a/ext/opentelemetry-ext-prometheus/README.rst +++ b/ext/opentelemetry-ext-prometheus/README.rst @@ -29,7 +29,7 @@ The **OpenTelemetry Prometheus Exporter** allows to export `OpenTelemetry`_ metr from opentelemetry import metrics from opentelemetry.ext.prometheus import PrometheusMetricsExporter - from opentelemetry.sdk.metrics import Counter, Meter + from opentelemetry.sdk.metrics import Counter from opentelemetry.sdk.metrics.export.controller import PushController from prometheus_client import start_http_server @@ -37,7 +37,6 @@ The **OpenTelemetry Prometheus Exporter** allows to export `OpenTelemetry`_ metr start_http_server(port=8000, addr="localhost") # Meter is responsible for creating and recording metrics - metrics.set_preferred_meter_implementation(lambda _: Meter()) meter = metrics.meter() # exporter to export metrics to Prometheus prefix = "MyAppPrefix" diff --git a/ext/opentelemetry-ext-prometheus/tests/conftest.py b/ext/opentelemetry-ext-prometheus/tests/conftest.py new file mode 100644 index 00000000000..ff9e5ea43bb --- /dev/null +++ b/ext/opentelemetry-ext-prometheus/tests/conftest.py @@ -0,0 +1,25 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from os import environ + + +def pytest_sessionstart(session): # pylint: disable=unused-argument + environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" + environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" + + +def pytest_sessionfinish(session): # pylint: disable=unused-argument + environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") + environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py index f6883475386..a0079b1fee1 100644 --- a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py +++ b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py @@ -21,6 +21,7 @@ CustomCollector, PrometheusMetricsExporter, ) +from opentelemetry.metrics import get_meter_provider from opentelemetry.sdk import metrics from opentelemetry.sdk.metrics.export import MetricRecord, MetricsExportResult from opentelemetry.sdk.metrics.export.aggregate import CounterAggregator @@ -28,7 +29,7 @@ class TestPrometheusMetricExporter(unittest.TestCase): def setUp(self): - self._meter = metrics.MeterProvider().get_meter(__name__) + self._meter = get_meter_provider().get_meter(__name__) self._test_metric = self._meter.create_metric( "testname", "testdesc", @@ -74,7 +75,7 @@ def test_export(self): self.assertIs(result, MetricsExportResult.SUCCESS) def test_counter_to_prometheus(self): - meter = metrics.MeterProvider().get_meter(__name__) + meter = get_meter_provider().get_meter(__name__) metric = meter.create_metric( "test@name", "testdesc", @@ -110,8 +111,7 @@ def test_counter_to_prometheus(self): # TODO: Add unit test once Measure Aggregators are available def test_invalid_metric(self): - - meter = metrics.MeterProvider().get_meter(__name__) + meter = get_meter_provider().get_meter(__name__) metric = meter.create_metric( "tesname", "testdesc", "unit", int, TestMetric ) diff --git a/ext/opentelemetry-ext-psycopg2/README.rst b/ext/opentelemetry-ext-psycopg2/README.rst index 127b74f0c79..3cf4cf110b3 100644 --- a/ext/opentelemetry-ext-psycopg2/README.rst +++ b/ext/opentelemetry-ext-psycopg2/README.rst @@ -13,10 +13,8 @@ Usage import psycopg2 from opentelemetry import trace - from opentelemetry.sdk.trace import TracerProvider from opentelemetry.trace.ext.psycopg2 import trace_integration - trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) tracer = trace.get_tracer(__name__) trace_integration(tracer) cnx = psycopg2.connect(database='Database') diff --git a/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py b/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py index 18b64364db9..39c2be27f9e 100644 --- a/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py +++ b/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py @@ -4,7 +4,7 @@ from importlib import reload from opentelemetry import trace as trace_api -from opentelemetry.sdk.trace import TracerProvider, export +from opentelemetry.sdk.trace import export from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( InMemorySpanExporter, ) @@ -16,10 +16,7 @@ class WsgiTestBase(unittest.TestCase): @classmethod def setUpClass(cls): global _MEMORY_EXPORTER # pylint:disable=global-statement - trace_api.set_preferred_tracer_provider_implementation( - lambda T: TracerProvider() - ) - tracer_provider = trace_api.tracer_provider() + tracer_provider = trace_api.get_tracer_provider() _MEMORY_EXPORTER = InMemorySpanExporter() span_processor = export.SimpleExportSpanProcessor(_MEMORY_EXPORTER) tracer_provider.add_span_processor(span_processor) diff --git a/ext/opentelemetry-ext-wsgi/tests/conftest.py b/ext/opentelemetry-ext-wsgi/tests/conftest.py new file mode 100644 index 00000000000..ff9e5ea43bb --- /dev/null +++ b/ext/opentelemetry-ext-wsgi/tests/conftest.py @@ -0,0 +1,25 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from os import environ + + +def pytest_sessionstart(session): # pylint: disable=unused-argument + environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" + environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" + + +def pytest_sessionfinish(session): # pylint: disable=unused-argument + environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") + environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/ext/opentelemetry-ext-zipkin/README.rst b/ext/opentelemetry-ext-zipkin/README.rst index f933ba4a685..9c88e450603 100644 --- a/ext/opentelemetry-ext-zipkin/README.rst +++ b/ext/opentelemetry-ext-zipkin/README.rst @@ -30,10 +30,8 @@ This exporter always send traces to the configured Zipkin collector using HTTP. from opentelemetry import trace from opentelemetry.ext import zipkin - from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchExportSpanProcessor - trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) tracer = trace.get_tracer(__name__) # create a ZipkinSpanExporter diff --git a/opentelemetry-api/setup.py b/opentelemetry-api/setup.py index 20e7f581435..eb10d24b94f 100644 --- a/opentelemetry-api/setup.py +++ b/opentelemetry-api/setup.py @@ -12,18 +12,40 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os +from os.path import dirname, exists, join +from pathlib import Path import setuptools -BASE_DIR = os.path.dirname(__file__) -VERSION_FILENAME = os.path.join( - BASE_DIR, "src", "opentelemetry", "util", "version.py" -) +BASE_DIR = dirname(__file__) +VERSION_FILENAME = join(BASE_DIR, "src", "opentelemetry", "util", "version.py") PACKAGE_INFO = {} with open(VERSION_FILENAME) as f: exec(f.read(), PACKAGE_INFO) +# FIXME Make this script install the configuration file in +# ~/.config/opentelemetry_python.json +configuration_file_path = join( + Path.home(), ".config", "opentelemetry_python.json" +) + +data_files = [] + +if not exists(configuration_file_path): + data_files.append( + ( + dirname(configuration_file_path), + [ + join( + "src", + "opentelemetry", + "configuration", + "opentelemetry_python.json", + ) + ], + ) + ) + setuptools.setup( name="opentelemetry-api", version=PACKAGE_INFO["__version__"], @@ -61,12 +83,22 @@ zip_safe=False, entry_points={ "opentelemetry_context": [ + "default_context = opentelemetry.context:DefaultContext", "contextvars_context = " "opentelemetry.context.contextvars_context:" "ContextVarsRuntimeContext", "threadlocal_context = " "opentelemetry.context.threadlocal_context:" "ThreadLocalRuntimeContext", - ] + ], + "opentelemetry_meter_provider": [ + "default_meter_provider = " + "opentelemetry.metrics:DefaultMeterProvider" + ], + "opentelemetry_tracer_provider": [ + "default_tracer_provider = " + "opentelemetry.trace:DefaultTracerProvider" + ], }, + data_files=data_files, ) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py new file mode 100644 index 00000000000..3e89f5f7d3a --- /dev/null +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -0,0 +1,78 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Simple configuration manager + +This configuration manager reads configuration values from a JSON file, the +values read there can be overriden by environment variables. + +It would probably be better to replace this configuration manager with a more +powerful one, Dynaconf, for example. +""" + +from json import load +from os import environ +from os.path import exists, join +from pathlib import Path + + +class Configuration: + _instance = None + + __slots__ = ["tracer_provider", "meter_provider"] + + def __new__(cls): + if Configuration._instance is None: + + configuration = { + key: "default_{}".format(key) for key in cls.__slots__ + } + + configuration_file_path = join( + Path.home(), ".config", "opentelemetry_python.json" + ) + + if exists(configuration_file_path): + + with open(configuration_file_path) as configuration_file: + file_configuration = load(configuration_file) + + for key, value in configuration.items(): + configuration[key] = file_configuration.get(key, value) + + for key, value in configuration.items(): + configuration[key] = environ.get( + "OPENTELEMETRY_PYTHON_{}".format(key.upper()), value + ) + + for key, value in configuration.items(): + underscored_key = "_{}".format(key) + + setattr(Configuration, underscored_key, value) + setattr( + Configuration, + key, + property( + ( + lambda underscored_key: lambda self: getattr( + self, underscored_key + ) + )(underscored_key) + ), + ) + + Configuration._instance = object.__new__(cls) + + return cls._instance diff --git a/opentelemetry-api/src/opentelemetry/configuration/opentelemetry_python.json b/opentelemetry-api/src/opentelemetry/configuration/opentelemetry_python.json new file mode 100644 index 00000000000..c0ac3f4ff93 --- /dev/null +++ b/opentelemetry-api/src/opentelemetry/configuration/opentelemetry_python.json @@ -0,0 +1,4 @@ +{ + "tracer_provider": "default_tracer_provider", + "meter_provider": "default_meter_provider" +} diff --git a/opentelemetry-api/src/opentelemetry/configuration/py.typed b/opentelemetry-api/src/opentelemetry/configuration/py.typed new file mode 100644 index 00000000000..e69de29bb2d diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index e521b2654c3..911fab1b79d 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -27,13 +27,14 @@ """ import abc -import logging -from typing import Callable, Dict, Optional, Sequence, Tuple, Type, TypeVar +from logging import getLogger +from typing import Callable, Dict, Sequence, Tuple, Type, TypeVar -from opentelemetry.util import loader +from pkg_resources import iter_entry_points -logger = logging.getLogger(__name__) +from opentelemetry.configuration import Configuration +_LOGGER = getLogger(__name__) ValueT = TypeVar("ValueT", int, float) @@ -398,15 +399,7 @@ def get_label_set(self, labels: Dict[str, str]) -> "LabelSet": return DefaultLabelSet() -# Once https://github.com/python/mypy/issues/7092 is resolved, -# the following type definition should be replaced with -# from opentelemetry.util.loader import ImplementationFactory -ImplementationFactory = Callable[ - [Type[MeterProvider]], Optional[MeterProvider] -] - _METER_PROVIDER = None -_METER_PROVIDER_FACTORY = None def get_meter( @@ -418,52 +411,34 @@ def get_meter( This function is a convenience wrapper for opentelemetry.metrics.meter_provider().get_meter """ - return meter_provider().get_meter( + return get_meter_provider().get_meter( instrumenting_module_name, stateful, instrumenting_library_version ) -def meter_provider() -> MeterProvider: - """Gets the current global :class:`~.MeterProvider` object. - - If there isn't one set yet, a default will be loaded. - """ - global _METER_PROVIDER, _METER_PROVIDER_FACTORY # pylint:disable=global-statement +def get_meter_provider() -> MeterProvider: + """Gets the current global :class:`~.MeterProvider` object.""" + global _METER_PROVIDER # pylint: disable=global-statement if _METER_PROVIDER is None: - # pylint:disable=protected-access + configured_meter_provider = ( + Configuration().meter_provider # pylint: disable=no-member + ) + try: - _METER_PROVIDER = loader._load_impl( - MeterProvider, _METER_PROVIDER_FACTORY # type: ignore + _METER_PROVIDER = next( + iter_entry_points( + "opentelemetry_meter_provider", configured_meter_provider + ) + ).load()() + except Exception: # pylint: disable=broad-except + # FIXME Decide on how to handle this. Should an exception be + # raised here, or only a message should be logged and should + # we fall back to the default meter provider? + _LOGGER.error( + "Failed to load configured meter provider %s", + configured_meter_provider, ) - except TypeError: - # if we raised an exception trying to instantiate an - # abstract class, default to no-op meter impl - logger.warning( - "Unable to instantiate MeterProvider from meter provider factory.", - exc_info=True, - ) - _METER_PROVIDER = DefaultMeterProvider() - _METER_PROVIDER_FACTORY = None + raise return _METER_PROVIDER - - -def set_preferred_meter_provider_implementation( - factory: ImplementationFactory, -) -> None: - """Set the factory to be used to create the meter provider. - - See :mod:`opentelemetry.util.loader` for details. - - This function may not be called after a meter is already loaded. - - Args: - factory: Callback that should create a new :class:`MeterProvider` instance. - """ - global _METER_PROVIDER_FACTORY # pylint:disable=global-statement - - if _METER_PROVIDER: - raise RuntimeError("MeterProvider already loaded.") - - _METER_PROVIDER_FACTORY = factory diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index a6633e434a0..05c6b962237 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -63,20 +63,23 @@ .. versionadded:: 0.1.0 .. versionchanged:: 0.3.0 `TracerProvider` was introduced and the global ``tracer`` getter was replaced - by `tracer_provider`. + by `get_tracer_provider`. """ import abc import enum -import logging import types as python_types import typing from contextlib import contextmanager +from logging import getLogger +from pkg_resources import iter_entry_points + +from opentelemetry.configuration import Configuration from opentelemetry.trace.status import Status -from opentelemetry.util import loader, types +from opentelemetry.util import types -logger = logging.getLogger(__name__) +_LOGGER = getLogger(__name__) # TODO: quarantine ParentSpan = typing.Optional[typing.Union["Span", "SpanContext"]] @@ -639,15 +642,7 @@ def use_span( yield -# Once https://github.com/python/mypy/issues/7092 is resolved, -# the following type definition should be replaced with -# from opentelemetry.util.loader import ImplementationFactory -ImplementationFactory = typing.Callable[ - [typing.Type[TracerProvider]], typing.Optional[TracerProvider] -] - -_TRACER_PROVIDER = None # type: typing.Optional[TracerProvider] -_TRACER_PROVIDER_FACTORY = None # type: typing.Optional[ImplementationFactory] +_TRACER_PROVIDER = None def get_tracer( @@ -658,53 +653,35 @@ def get_tracer( This function is a convenience wrapper for opentelemetry.trace.tracer_provider().get_tracer """ - return tracer_provider().get_tracer( + return get_tracer_provider().get_tracer( instrumenting_module_name, instrumenting_library_version ) -def tracer_provider() -> TracerProvider: - """Gets the current global :class:`~.TracerProvider` object. - - If there isn't one set yet, a default will be loaded. - """ - global _TRACER_PROVIDER, _TRACER_PROVIDER_FACTORY # pylint:disable=global-statement +def get_tracer_provider() -> TracerProvider: + """Gets the current global :class:`~.TracerProvider` object.""" + global _TRACER_PROVIDER # pylint: disable=global-statement if _TRACER_PROVIDER is None: - # pylint:disable=protected-access + configured_tracer_provider = ( + Configuration().tracer_provider # pylint: disable=no-member + ) + try: - _TRACER_PROVIDER = loader._load_impl( - TracerProvider, _TRACER_PROVIDER_FACTORY # type: ignore + _TRACER_PROVIDER = next( + iter_entry_points( + "opentelemetry_tracer_provider", + name=configured_tracer_provider, + ) + ).load()() + except Exception: # pylint: disable=broad-except + # FIXME Decide on how to handle this. Should an exception be + # raised here, or only a message should be logged and should + # we fall back to the default tracer provider? + _LOGGER.error( + "Failed to load tracer implementation: %s", + configured_tracer_provider, ) - except TypeError: - # if we raised an exception trying to instantiate an - # abstract class, default to no-op tracer impl - logger.warning( - "Unable to instantiate TracerProvider from factory.", - exc_info=True, - ) - _TRACER_PROVIDER = DefaultTracerProvider() - del _TRACER_PROVIDER_FACTORY + raise return _TRACER_PROVIDER - - -def set_preferred_tracer_provider_implementation( - factory: ImplementationFactory, -) -> None: - """Set the factory to be used to create the global TracerProvider. - - See :mod:`opentelemetry.util.loader` for details. - - This function may not be called after a tracer is already loaded. - - Args: - factory: Callback that should create a new :class:`TracerProvider` - instance. - """ - global _TRACER_PROVIDER_FACTORY # pylint:disable=global-statement - - if _TRACER_PROVIDER: - raise RuntimeError("TracerProvider already loaded.") - - _TRACER_PROVIDER_FACTORY = factory diff --git a/opentelemetry-api/src/opentelemetry/util/loader.py b/opentelemetry-api/src/opentelemetry/util/loader.py deleted file mode 100644 index eeda2b3e7f7..00000000000 --- a/opentelemetry-api/src/opentelemetry/util/loader.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -""" -The OpenTelemetry loader module is mainly used internally to load the -implementation for global objects like -:func:`opentelemetry.trace.tracer_provider`. - -.. _loader-factory: - -An instance of a global object of type ``T`` is always created with a factory -function with the following signature:: - - def my_factory_for_t(api_type: typing.Type[T]) -> typing.Optional[T]: - # ... - -That function is called with e.g., the type of the global object it should -create as an argument (e.g. the type object -:class:`opentelemetry.trace.TracerProvider`) and should return an instance of that type -(such that ``instanceof(my_factory_for_t(T), T)`` is true). Alternatively, it -may return ``None`` to indicate that the no-op default should be used. - -When loading an implementation, the following algorithm is used to find a -factory function or other means to create the global object: - - 1. If the environment variable - :samp:`OPENTELEMETRY_PYTHON_IMPLEMENTATION_{getter-name}` (e.g., - ``OPENTELEMETRY_PYTHON_IMPLEMENTATION_TRACERPROVIDER``) is set to an - nonempty value, an attempt is made to import a module with that name and - use a factory function named ``get_opentelemetry_implementation`` in it. - 2. Otherwise, the same is tried with the environment variable - ``OPENTELEMETRY_PYTHON_IMPLEMENTATION_DEFAULT``. - 3. Otherwise, if a :samp:`set_preferred_{}_implementation` was - called (e.g. - :func:`opentelemetry.trace.set_preferred_tracer_provider_implementation`), - the callback set there is used (that is, the environment variables - override the callback set in code). - 4. Otherwise, if :func:`set_preferred_default_implementation` was called, - the callback set there is used. - 5. Otherwise, an attempt is made to import and use the OpenTelemetry SDK. - 6. Otherwise the default implementation that ships with the API - distribution (a fast no-op implementation) is used. - -If any of the above steps fails (e.g., a module is loaded but does not define -the required function or a module name is set but the module fails to load), -the search immediatelly skips to the last step. - -Note that the first two steps (those that query environment variables) are -skipped if :data:`sys.flags` has ``ignore_environment`` set (which usually -means that the Python interpreter was invoked with the ``-E`` or ``-I`` flag). -""" - -import importlib -import os -import sys -from typing import Callable, Optional, Type, TypeVar - -_T = TypeVar("_T") - -# "Untrusted" because this is usually user-provided and we don't trust the user -# to really return a _T: by using object, mypy forces us to check/cast -# explicitly. -_UntrustedImplFactory = Callable[[Type[_T]], Optional[object]] - - -# This would be the normal ImplementationFactory which would be used to -# annotate setters, were it not for https://github.com/python/mypy/issues/7092 -# Once that bug is resolved, setters should use this instead of duplicating the -# code. -# ImplementationFactory = Callable[[Type[_T]], Optional[_T]] - -_DEFAULT_FACTORY = None # type: Optional[_UntrustedImplFactory[object]] - - -def _try_load_impl_from_modname( - implementation_modname: str, api_type: Type[_T] -) -> Optional[_T]: - try: - implementation_mod = importlib.import_module(implementation_modname) - except (ImportError, SyntaxError): - # TODO Log/warn - return None - - return _try_load_impl_from_mod(implementation_mod, api_type) - - -def _try_load_impl_from_mod( - implementation_mod: object, api_type: Type[_T] -) -> Optional[_T]: - - try: - # Note: We use such a long name to avoid calling a function that is not - # intended for this API. - - implementation_fn = getattr( - implementation_mod, "get_opentelemetry_implementation" - ) # type: _UntrustedImplFactory[_T] - except AttributeError: - # TODO Log/warn - return None - - return _try_load_impl_from_callback(implementation_fn, api_type) - - -def _try_load_impl_from_callback( - implementation_fn: _UntrustedImplFactory[_T], api_type: Type[_T] -) -> Optional[_T]: - result = implementation_fn(api_type) - if result is None: - return None - if not isinstance(result, api_type): - # TODO Warn if wrong type is returned - return None - - # TODO: Warn if implementation_fn returns api_type(): It should return None - # to indicate using the default. - - return result - - -def _try_load_configured_impl( - api_type: Type[_T], factory: Optional[_UntrustedImplFactory[_T]] -) -> Optional[_T]: - """Attempts to find any specially configured implementation. If none is - configured, or a load error occurs, returns `None` - """ - implementation_modname = None - if not sys.flags.ignore_environment: - implementation_modname = os.getenv( - "OPENTELEMETRY_PYTHON_IMPLEMENTATION_" + api_type.__name__.upper() - ) - if implementation_modname: - return _try_load_impl_from_modname( - implementation_modname, api_type - ) - implementation_modname = os.getenv( - "OPENTELEMETRY_PYTHON_IMPLEMENTATION_DEFAULT" - ) - if implementation_modname: - return _try_load_impl_from_modname( - implementation_modname, api_type - ) - if factory is not None: - return _try_load_impl_from_callback(factory, api_type) - if _DEFAULT_FACTORY is not None: - return _try_load_impl_from_callback(_DEFAULT_FACTORY, api_type) - return None - - -# Public to other opentelemetry-api modules -def _load_impl( - api_type: Type[_T], factory: Optional[Callable[[Type[_T]], Optional[_T]]] -) -> _T: - """Tries to load a configured implementation, if unsuccessful, returns a - fast no-op implemenation that is always available. - """ - - result = _try_load_configured_impl(api_type, factory) - if result is None: - return api_type() - return result - - -def set_preferred_default_implementation( - implementation_factory: _UntrustedImplFactory[_T], -) -> None: - """Sets a factory function that may be called for any implementation - object. See the :ref:`module docs ` for more details.""" - global _DEFAULT_FACTORY # pylint:disable=global-statement - _DEFAULT_FACTORY = implementation_factory diff --git a/opentelemetry-api/tests/configuration/__init__.py b/opentelemetry-api/tests/configuration/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/opentelemetry-api/tests/configuration/test_configuration.py b/opentelemetry-api/tests/configuration/test_configuration.py new file mode 100644 index 00000000000..cd3b9aa3e0a --- /dev/null +++ b/opentelemetry-api/tests/configuration/test_configuration.py @@ -0,0 +1,85 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from json import dumps +from os import getcwd +from unittest import TestCase +from unittest.mock import patch + +from opentelemetry.configuration import Configuration +from pytest import fixture # pylint: disable=import-error + + +class TestConfiguration(TestCase): + @fixture(autouse=True) + def configdir(self, tmpdir): # pylint: disable=no-self-use + tmpdir.chdir() + tmpdir.mkdir(".config").join("opentelemetry_python.json").write( + dumps({"tracer_provider": "default_tracer_provider"}) + ) + + def setUp(self): + Configuration._instance = None # pylint: disable=protected-access + + def tearDown(self): + Configuration._instance = None # pylint: disable=protected-access + + def test_singleton(self): + self.assertIs(Configuration(), Configuration()) + + @patch("pathlib.Path.home") + def test_configuration_file(self, mock_home_path): + mock_home_path.return_value = getcwd() + + self.assertEqual( + Configuration().tracer_provider, "default_tracer_provider" + ) # pylint: disable=no-member + self.assertEqual( + Configuration().meter_provider, "default_meter_provider" + ) # pylint: disable=no-member + + @patch.dict( + "os.environ", + {"OPENTELEMETRY_PYTHON_METER_PROVIDER": "overridden_meter_provider"}, + ) + def test_environment_variables(self): + self.assertEqual( + Configuration().tracer_provider, "default_tracer_provider" + ) # pylint: disable=no-member + self.assertEqual( + Configuration().meter_provider, "overridden_meter_provider" + ) # pylint: disable=no-member + + @patch("pathlib.Path.home") + @patch.dict( + "os.environ", + {"OPENTELEMETRY_PYTHON_METER_PROVIDER": "reoverridden_meter_provider"}, + ) + def test_configuration_file_environment_variables(self, mock_home_path): + mock_home_path.return_value = getcwd() + + self.assertEqual( + Configuration().tracer_provider, "default_tracer_provider" + ) + self.assertEqual( + Configuration().meter_provider, "reoverridden_meter_provider" + ) + + def test_property(self): + with self.assertRaises(AttributeError): + Configuration().tracer_provider = "new_tracer_provider" + + def test_slots(self): + with self.assertRaises(AttributeError): + Configuration().xyz = "xyz" # pylint: disable=assigning-non-slot diff --git a/opentelemetry-api/tests/mypysmoke.py b/opentelemetry-api/tests/mypysmoke.py index bbbda93ef29..2891f3ee624 100644 --- a/opentelemetry-api/tests/mypysmoke.py +++ b/opentelemetry-api/tests/mypysmoke.py @@ -16,4 +16,4 @@ def dummy_check_mypy_returntype() -> opentelemetry.trace.TracerProvider: - return opentelemetry.trace.tracer_provider() + return opentelemetry.trace.get_tracer_provider() diff --git a/opentelemetry-api/tests/test_loader.py b/opentelemetry-api/tests/test_loader.py deleted file mode 100644 index 76575df705a..00000000000 --- a/opentelemetry-api/tests/test_loader.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright 2019, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys -import unittest -from importlib import reload -from typing import Any, Callable - -from opentelemetry import trace -from opentelemetry.util import loader - -DUMMY_TRACER_PROVIDER = None - - -class DummyTracerProvider(trace.TracerProvider): - def get_tracer( - self, - instrumenting_module_name: str, - instrumenting_library_version: str = "", - ) -> "trace.Tracer": - return trace.DefaultTracer() - - -def get_opentelemetry_implementation(type_): - global DUMMY_TRACER_PROVIDER # pylint:disable=global-statement - assert type_ is trace.TracerProvider - DUMMY_TRACER_PROVIDER = DummyTracerProvider() - return DUMMY_TRACER_PROVIDER - - -# pylint:disable=redefined-outer-name,protected-access,unidiomatic-typecheck - - -class TestLoader(unittest.TestCase): - def setUp(self): - reload(loader) - reload(trace) - - # Need to reload self, otherwise DummyTracerProvider will have the wrong - # base class after reloading `trace`. - reload(sys.modules[__name__]) - - def test_get_default(self): - tracer_provider = trace.tracer_provider() - self.assertIs(type(tracer_provider), trace.DefaultTracerProvider) - - def test_preferred_impl(self): - trace.set_preferred_tracer_provider_implementation( - get_opentelemetry_implementation - ) - tracer_provider = trace.tracer_provider() - self.assertIs(tracer_provider, DUMMY_TRACER_PROVIDER) - - # NOTE: We use do_* + *_ methods because subtest wouldn't run setUp, - # which we require here. - def do_test_preferred_impl(self, setter: Callable[[Any], Any]) -> None: - setter(get_opentelemetry_implementation) - tracer_provider = trace.tracer_provider() - self.assertIs(tracer_provider, DUMMY_TRACER_PROVIDER) - - def test_preferred_impl_with_tracer(self): - self.do_test_preferred_impl( - trace.set_preferred_tracer_provider_implementation - ) - - def test_preferred_impl_with_default(self): - self.do_test_preferred_impl( - loader.set_preferred_default_implementation - ) - - def test_try_set_again(self): - self.assertTrue(trace.tracer_provider()) - # Try setting after the tracer_provider has already been created: - with self.assertRaises(RuntimeError) as einfo: - trace.set_preferred_tracer_provider_implementation( - get_opentelemetry_implementation - ) - self.assertIn("already loaded", str(einfo.exception)) - - def do_test_get_envvar(self, envvar_suffix: str) -> None: - global DUMMY_TRACER_PROVIDER # pylint:disable=global-statement - - # Test is not runnable with this! - self.assertFalse(sys.flags.ignore_environment) - - envname = "OPENTELEMETRY_PYTHON_IMPLEMENTATION_" + envvar_suffix - os.environ[envname] = __name__ - try: - tracer_provider = trace.tracer_provider() - self.assertIs(tracer_provider, DUMMY_TRACER_PROVIDER) - finally: - DUMMY_TRACER_PROVIDER = None - del os.environ[envname] - self.assertIs(type(tracer_provider), DummyTracerProvider) - - def test_get_envvar_tracer(self): - return self.do_test_get_envvar("TRACERPROVIDER") - - def test_get_envvar_default(self): - return self.do_test_get_envvar("DEFAULT") diff --git a/opentelemetry-api/tests/trace/test_globals.py b/opentelemetry-api/tests/trace/test_globals.py index 7c4d8e3549b..2e0339b99dd 100644 --- a/opentelemetry-api/tests/trace/test_globals.py +++ b/opentelemetry-api/tests/trace/test_globals.py @@ -1,40 +1,18 @@ -import importlib import unittest +from unittest.mock import patch from opentelemetry import trace class TestGlobals(unittest.TestCase): def setUp(self): - importlib.reload(trace) + self._patcher = patch("opentelemetry.trace._TRACER_PROVIDER") + self._mock_tracer_provider = self._patcher.start() - # This class has to be declared after the importlib reload, or else it - # will inherit from an old TracerProvider, rather than the new - # TracerProvider ABC created from reload. - - static_tracer = trace.DefaultTracer() - - class DummyTracerProvider(trace.TracerProvider): - """TracerProvider 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_provider_implementation( - lambda _: DummyTracerProvider() - ) - - @staticmethod - def tearDown() -> None: - importlib.reload(trace) + def tearDown(self) -> None: + self._patcher.stop() def test_get_tracer(self): """trace.get_tracer should proxy to the global tracer provider.""" - from_global_api = trace.get_tracer("foo") - from_tracer_api = trace.tracer_provider().get_tracer("foo") - self.assertIs(from_global_api, from_tracer_api) + trace.get_tracer("foo", "var") + self._mock_tracer_provider.get_tracer.assert_called_with("foo", "var") diff --git a/opentelemetry-sdk/setup.py b/opentelemetry-sdk/setup.py index 50fe925605c..c471ff02311 100644 --- a/opentelemetry-sdk/setup.py +++ b/opentelemetry-sdk/setup.py @@ -56,4 +56,12 @@ "/tree/master/opentelemetry-sdk" ), zip_safe=False, + entry_points={ + "opentelemetry_meter_provider": [ + "sdk_meter_provider = opentelemetry.sdk.metrics:MeterProvider" + ], + "opentelemetry_tracer_provider": [ + "sdk_tracer_provider = opentelemetry.sdk.trace:TracerProvider" + ], + }, ) diff --git a/tests/w3c_tracecontext_validation_server.py b/tests/w3c_tracecontext_validation_server.py index 4ec179c3545..40ac247f542 100644 --- a/tests/w3c_tracecontext_validation_server.py +++ b/tests/w3c_tracecontext_validation_server.py @@ -26,24 +26,19 @@ from opentelemetry import trace from opentelemetry.ext import http_requests from opentelemetry.ext.wsgi import OpenTelemetryMiddleware -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ( ConsoleSpanExporter, SimpleExportSpanProcessor, ) -# The preferred tracer implementation must be set, as the opentelemetry-api -# defines the interface with a no-op implementation. -trace.set_preferred_tracer_provider_implementation(lambda T: TracerProvider()) - # Integrations are the glue that binds the OpenTelemetry API and the # frameworks and libraries that are used together, automatically creating # Spans and propagating context as appropriate. -http_requests.enable(trace.tracer_provider()) +http_requests.enable(trace.get_tracer_provider()) # SpanExporter receives the spans and send them to the target location. span_processor = SimpleExportSpanProcessor(ConsoleSpanExporter()) -trace.tracer_provider().add_span_processor(span_processor) +trace.get_tracer_provider().add_span_processor(span_processor) app = flask.Flask(__name__) app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app) From fd6f4e55953c7ef8379c44353ab14f9b8f32361d Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Tue, 10 Mar 2020 13:20:02 -0600 Subject: [PATCH 02/28] Revert to logger --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 4 ++-- opentelemetry-api/src/opentelemetry/trace/__init__.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 911fab1b79d..7cc1d9bb96c 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -34,7 +34,7 @@ from opentelemetry.configuration import Configuration -_LOGGER = getLogger(__name__) +logger = getLogger(__name__) ValueT = TypeVar("ValueT", int, float) @@ -435,7 +435,7 @@ def get_meter_provider() -> MeterProvider: # FIXME Decide on how to handle this. Should an exception be # raised here, or only a message should be logged and should # we fall back to the default meter provider? - _LOGGER.error( + logger.error( "Failed to load configured meter provider %s", configured_meter_provider, ) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 05c6b962237..7c0165afb95 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -79,7 +79,7 @@ from opentelemetry.trace.status import Status from opentelemetry.util import types -_LOGGER = getLogger(__name__) +logger = getLogger(__name__) # TODO: quarantine ParentSpan = typing.Optional[typing.Union["Span", "SpanContext"]] @@ -678,7 +678,7 @@ def get_tracer_provider() -> TracerProvider: # FIXME Decide on how to handle this. Should an exception be # raised here, or only a message should be logged and should # we fall back to the default tracer provider? - _LOGGER.error( + logger.error( "Failed to load tracer implementation: %s", configured_tracer_provider, ) From 7009e686d075cf52821dec46077ce33a8238bf11 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Tue, 10 Mar 2020 23:51:43 -0600 Subject: [PATCH 03/28] Add missing conftest.py --- .../examples}/basic_tracer/tests/conftest.py | 0 .../examples}/http/tests/conftest.py | 0 .../tests/conftest.py | 25 ------------------- 3 files changed, 25 deletions(-) rename {examples => docs/examples}/basic_tracer/tests/conftest.py (100%) rename {examples => docs/examples}/http/tests/conftest.py (100%) delete mode 100644 examples/opentelemetry-example-app/tests/conftest.py diff --git a/examples/basic_tracer/tests/conftest.py b/docs/examples/basic_tracer/tests/conftest.py similarity index 100% rename from examples/basic_tracer/tests/conftest.py rename to docs/examples/basic_tracer/tests/conftest.py diff --git a/examples/http/tests/conftest.py b/docs/examples/http/tests/conftest.py similarity index 100% rename from examples/http/tests/conftest.py rename to docs/examples/http/tests/conftest.py diff --git a/examples/opentelemetry-example-app/tests/conftest.py b/examples/opentelemetry-example-app/tests/conftest.py deleted file mode 100644 index ff9e5ea43bb..00000000000 --- a/examples/opentelemetry-example-app/tests/conftest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from os import environ - - -def pytest_sessionstart(session): # pylint: disable=unused-argument - environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" - environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" - - -def pytest_sessionfinish(session): # pylint: disable=unused-argument - environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") - environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") From 10f04fb57c62dcad34f232ea0ab889d7f117ebdc Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 12:29:26 -0600 Subject: [PATCH 04/28] Work around mypy issues --- .../src/opentelemetry/configuration/__init__.py | 5 ++++- .../src/opentelemetry/metrics/__init__.py | 12 ++++++------ .../src/opentelemetry/trace/__init__.py | 12 ++++++------ .../tests/configuration/test_configuration.py | 12 ++++++------ 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index 3e89f5f7d3a..fcf7dc15e12 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -12,6 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +# FIXME find a better way to avoid all those "Expression has type "Any"" errors +# type: ignore + """ Simple configuration manager @@ -33,7 +36,7 @@ class Configuration: __slots__ = ["tracer_provider", "meter_provider"] - def __new__(cls): + def __new__(cls) -> "Configuration": if Configuration._instance is None: configuration = { diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 7cc1d9bb96c..e1f28089664 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -32,7 +32,7 @@ from pkg_resources import iter_entry_points -from opentelemetry.configuration import Configuration +from opentelemetry.configuration import Configuration # type: ignore logger = getLogger(__name__) ValueT = TypeVar("ValueT", int, float) @@ -422,13 +422,13 @@ def get_meter_provider() -> MeterProvider: if _METER_PROVIDER is None: configured_meter_provider = ( - Configuration().meter_provider # pylint: disable=no-member + Configuration().meter_provider # type: ignore # pylint: disable=no-member ) try: - _METER_PROVIDER = next( + _METER_PROVIDER = next( # type: ignore iter_entry_points( - "opentelemetry_meter_provider", configured_meter_provider + "opentelemetry_meter_provider", configured_meter_provider # type: ignore ) ).load()() except Exception: # pylint: disable=broad-except @@ -437,8 +437,8 @@ def get_meter_provider() -> MeterProvider: # we fall back to the default meter provider? logger.error( "Failed to load configured meter provider %s", - configured_meter_provider, + configured_meter_provider, # type: ignore ) raise - return _METER_PROVIDER + return _METER_PROVIDER # type: ignore diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 7c0165afb95..f1309ae7a34 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -75,7 +75,7 @@ from pkg_resources import iter_entry_points -from opentelemetry.configuration import Configuration +from opentelemetry.configuration import Configuration # type: ignore from opentelemetry.trace.status import Status from opentelemetry.util import types @@ -664,14 +664,14 @@ def get_tracer_provider() -> TracerProvider: if _TRACER_PROVIDER is None: configured_tracer_provider = ( - Configuration().tracer_provider # pylint: disable=no-member + Configuration().tracer_provider # type: ignore # pylint: disable=no-member ) try: - _TRACER_PROVIDER = next( + _TRACER_PROVIDER = next( # type: ignore iter_entry_points( "opentelemetry_tracer_provider", - name=configured_tracer_provider, + name=configured_tracer_provider, # type: ignore ) ).load()() except Exception: # pylint: disable=broad-except @@ -680,8 +680,8 @@ def get_tracer_provider() -> TracerProvider: # we fall back to the default tracer provider? logger.error( "Failed to load tracer implementation: %s", - configured_tracer_provider, + configured_tracer_provider, # type: ignore ) raise - return _TRACER_PROVIDER + return _TRACER_PROVIDER # type: ignore diff --git a/opentelemetry-api/tests/configuration/test_configuration.py b/opentelemetry-api/tests/configuration/test_configuration.py index cd3b9aa3e0a..bb71a1de246 100644 --- a/opentelemetry-api/tests/configuration/test_configuration.py +++ b/opentelemetry-api/tests/configuration/test_configuration.py @@ -17,13 +17,13 @@ from unittest import TestCase from unittest.mock import patch -from opentelemetry.configuration import Configuration -from pytest import fixture # pylint: disable=import-error +from opentelemetry.configuration import Configuration # type: ignore +from pytest import fixture # type: ignore # pylint: disable=import-error class TestConfiguration(TestCase): @fixture(autouse=True) - def configdir(self, tmpdir): # pylint: disable=no-self-use + def configdir(self, tmpdir): # type: ignore # pylint: disable=no-self-use tmpdir.chdir() tmpdir.mkdir(".config").join("opentelemetry_python.json").write( dumps({"tracer_provider": "default_tracer_provider"}) @@ -39,7 +39,7 @@ def test_singleton(self): self.assertIs(Configuration(), Configuration()) @patch("pathlib.Path.home") - def test_configuration_file(self, mock_home_path): + def test_configuration_file(self, mock_home_path): # type: ignore mock_home_path.return_value = getcwd() self.assertEqual( @@ -53,7 +53,7 @@ def test_configuration_file(self, mock_home_path): "os.environ", {"OPENTELEMETRY_PYTHON_METER_PROVIDER": "overridden_meter_provider"}, ) - def test_environment_variables(self): + def test_environment_variables(self): # type: ignore self.assertEqual( Configuration().tracer_provider, "default_tracer_provider" ) # pylint: disable=no-member @@ -66,7 +66,7 @@ def test_environment_variables(self): "os.environ", {"OPENTELEMETRY_PYTHON_METER_PROVIDER": "reoverridden_meter_provider"}, ) - def test_configuration_file_environment_variables(self, mock_home_path): + def test_configuration_file_environment_variables(self, mock_home_path): # type: ignore mock_home_path.return_value = getcwd() self.assertEqual( From 32bb9d2edc8cbb8dd53199e8b449a9d64be278f3 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 13:06:58 -0600 Subject: [PATCH 05/28] Add workaround for tracecontext --- tests/w3c_tracecontext_validation_server.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/w3c_tracecontext_validation_server.py b/tests/w3c_tracecontext_validation_server.py index 40ac247f542..d5169d46e8b 100644 --- a/tests/w3c_tracecontext_validation_server.py +++ b/tests/w3c_tracecontext_validation_server.py @@ -23,6 +23,14 @@ import flask import requests +from os import environ + +# FIXME This could likely be avoided by integrating this script into the +# standard test running mechanisms. + +environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" +environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] ="sdk_meter_provider" + from opentelemetry import trace from opentelemetry.ext import http_requests from opentelemetry.ext.wsgi import OpenTelemetryMiddleware From 7dd05bd480167424bc4d553d679f99948234bd8e Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 13:48:58 -0600 Subject: [PATCH 06/28] Fix lint --- tests/w3c_tracecontext_validation_server.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/w3c_tracecontext_validation_server.py b/tests/w3c_tracecontext_validation_server.py index d5169d46e8b..ddbbbd383f0 100644 --- a/tests/w3c_tracecontext_validation_server.py +++ b/tests/w3c_tracecontext_validation_server.py @@ -19,22 +19,25 @@ """ import json +from os import environ import flask import requests -from os import environ - # FIXME This could likely be avoided by integrating this script into the # standard test running mechanisms. -environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" -environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] ="sdk_meter_provider" +environ[ + "OPENTELEMETRY_PYTHON_TRACER_PROVIDER" +] = "sdk_tracer_provider" # isort:skip +environ[ + "OPENTELEMETRY_PYTHON_METER_PROVIDER" +] = "sdk_meter_provider" # isort:skip -from opentelemetry import trace -from opentelemetry.ext import http_requests -from opentelemetry.ext.wsgi import OpenTelemetryMiddleware -from opentelemetry.sdk.trace.export import ( +from opentelemetry import trace # noqa # isort:skip +from opentelemetry.ext import http_requests # noqa # isort:skip" +from opentelemetry.ext.wsgi import OpenTelemetryMiddleware # noqa # isort:skip +from opentelemetry.sdk.trace.export import ( # noqa # isort:skip ConsoleSpanExporter, SimpleExportSpanProcessor, ) From b05eaa66d504d8d3e8e2ae4fec29649bcc64f689 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 14:04:47 -0600 Subject: [PATCH 07/28] Remove configuration file writing --- opentelemetry-api/setup.py | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/opentelemetry-api/setup.py b/opentelemetry-api/setup.py index eb10d24b94f..b2266dd23b4 100644 --- a/opentelemetry-api/setup.py +++ b/opentelemetry-api/setup.py @@ -12,8 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from os.path import dirname, exists, join -from pathlib import Path +from os.path import dirname, join import setuptools @@ -23,29 +22,6 @@ with open(VERSION_FILENAME) as f: exec(f.read(), PACKAGE_INFO) -# FIXME Make this script install the configuration file in -# ~/.config/opentelemetry_python.json -configuration_file_path = join( - Path.home(), ".config", "opentelemetry_python.json" -) - -data_files = [] - -if not exists(configuration_file_path): - data_files.append( - ( - dirname(configuration_file_path), - [ - join( - "src", - "opentelemetry", - "configuration", - "opentelemetry_python.json", - ) - ], - ) - ) - setuptools.setup( name="opentelemetry-api", version=PACKAGE_INFO["__version__"], @@ -100,5 +76,4 @@ "opentelemetry.trace:DefaultTracerProvider" ], }, - data_files=data_files, ) From 41c21eb1294ad15506d6570116c786f1fffadf70 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 15:27:58 -0600 Subject: [PATCH 08/28] Use expanduser --- .../src/opentelemetry/configuration/__init__.py | 5 ++--- .../tests/configuration/test_configuration.py | 12 ++++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index fcf7dc15e12..237a98eb41e 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -27,8 +27,7 @@ from json import load from os import environ -from os.path import exists, join -from pathlib import Path +from os.path import exists, join, expanduser class Configuration: @@ -44,7 +43,7 @@ def __new__(cls) -> "Configuration": } configuration_file_path = join( - Path.home(), ".config", "opentelemetry_python.json" + expanduser("~"), ".config", "opentelemetry_python.json" ) if exists(configuration_file_path): diff --git a/opentelemetry-api/tests/configuration/test_configuration.py b/opentelemetry-api/tests/configuration/test_configuration.py index bb71a1de246..0c78a0123a2 100644 --- a/opentelemetry-api/tests/configuration/test_configuration.py +++ b/opentelemetry-api/tests/configuration/test_configuration.py @@ -38,9 +38,9 @@ def tearDown(self): def test_singleton(self): self.assertIs(Configuration(), Configuration()) - @patch("pathlib.Path.home") - def test_configuration_file(self, mock_home_path): # type: ignore - mock_home_path.return_value = getcwd() + @patch("os.path.expanduser") + def test_configuration_file(self, mock_expanduser): # type: ignore + mock_expanduser.return_value = getcwd() self.assertEqual( Configuration().tracer_provider, "default_tracer_provider" @@ -61,13 +61,13 @@ def test_environment_variables(self): # type: ignore Configuration().meter_provider, "overridden_meter_provider" ) # pylint: disable=no-member - @patch("pathlib.Path.home") + @patch("os.path.expanduser") @patch.dict( "os.environ", {"OPENTELEMETRY_PYTHON_METER_PROVIDER": "reoverridden_meter_provider"}, ) - def test_configuration_file_environment_variables(self, mock_home_path): # type: ignore - mock_home_path.return_value = getcwd() + def test_configuration_file_environment_variables(self, mock_expanduser): # type: ignore + mock_expanduser.return_value = getcwd() self.assertEqual( Configuration().tracer_provider, "default_tracer_provider" From e685cb714b93f37f20f49cdef723a63111fcab0c Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 15:54:26 -0600 Subject: [PATCH 09/28] Fix lint --- opentelemetry-api/src/opentelemetry/configuration/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index 237a98eb41e..026e060323d 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -27,7 +27,7 @@ from json import load from os import environ -from os.path import exists, join, expanduser +from os.path import exists, expanduser, join class Configuration: From 00cfd7e491e2c26e1d2442fc4f8310d11865a81d Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 17:09:18 -0600 Subject: [PATCH 10/28] Update otcollector --- .../tests/conftest.py | 25 +++++++++++++++++++ .../test_otcollector_metrics_exporter.py | 15 +++-------- 2 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 ext/opentelemetry-ext-otcollector/tests/conftest.py diff --git a/ext/opentelemetry-ext-otcollector/tests/conftest.py b/ext/opentelemetry-ext-otcollector/tests/conftest.py new file mode 100644 index 00000000000..ff9e5ea43bb --- /dev/null +++ b/ext/opentelemetry-ext-otcollector/tests/conftest.py @@ -0,0 +1,25 @@ +# Copyright 2020, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from os import environ + + +def pytest_sessionstart(session): # pylint: disable=unused-argument + environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" + environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" + + +def pytest_sessionfinish(session): # pylint: disable=unused-argument + environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") + environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py index f58f9768d60..04b3ef0c42e 100644 --- a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py +++ b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py @@ -21,7 +21,7 @@ from opentelemetry import metrics from opentelemetry.ext.otcollector import metrics_exporter -from opentelemetry.sdk.metrics import Counter, Measure, MeterProvider +from opentelemetry.sdk.metrics import Counter, Measure from opentelemetry.sdk.metrics.export import ( MetricRecord, MetricsExportResult, @@ -34,13 +34,7 @@ class TestCollectorMetricsExporter(unittest.TestCase): @classmethod def setUpClass(cls): # pylint: disable=protected-access - cls._meter_defaults = ( - metrics._METER_PROVIDER, - metrics._METER_PROVIDER_FACTORY, - ) - metrics.set_preferred_meter_provider_implementation( - lambda _: MeterProvider() - ) + cls._meter_defaults = metrics._METER_PROVIDER cls._meter = metrics.get_meter(__name__) kvp = {"environment": "staging"} cls._test_label_set = cls._meter.get_label_set(kvp) @@ -48,10 +42,7 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): # pylint: disable=protected-access - ( - metrics._METER_PROVIDER, - metrics._METER_PROVIDER_FACTORY, - ) = cls._meter_defaults + metrics._METER_PROVIDER = cls._meter_defaults def test_constructor(self): mock_get_node = mock.Mock() From a684297d3ddd5b9deb14fb831535a19064fd4c5e Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 17:27:58 -0600 Subject: [PATCH 11/28] Fix lint --- examples/metrics/collector.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/metrics/collector.py b/examples/metrics/collector.py index 230b2963934..25bc4ef9152 100644 --- a/examples/metrics/collector.py +++ b/examples/metrics/collector.py @@ -21,11 +21,10 @@ from opentelemetry.ext.otcollector.metrics_exporter import ( CollectorMetricsExporter, ) -from opentelemetry.sdk.metrics import Counter, MeterProvider +from opentelemetry.sdk.metrics import Counter from opentelemetry.sdk.metrics.export.controller import PushController # Meter is responsible for creating and recording metrics -metrics.set_preferred_meter_provider_implementation(lambda _: MeterProvider()) meter = metrics.get_meter(__name__) # exporter to export metrics to OT Collector exporter = CollectorMetricsExporter( From e2e0bcc822e7b2be42699af92a055cfda2c253fd Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 17:29:11 -0600 Subject: [PATCH 12/28] Update opentelemetry-api/src/opentelemetry/configuration/__init__.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Mauricio Vásquez --- opentelemetry-api/src/opentelemetry/configuration/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index 026e060323d..34fa2afa8fe 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -33,7 +33,7 @@ class Configuration: _instance = None - __slots__ = ["tracer_provider", "meter_provider"] + __slots__ = ("tracer_provider", "meter_provider") def __new__(cls) -> "Configuration": if Configuration._instance is None: From f54234bd2815a7ae7869ee5fd369f7f76308ad7f Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 17:29:25 -0600 Subject: [PATCH 13/28] Update opentelemetry-api/src/opentelemetry/configuration/__init__.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Mauricio Vásquez --- .../src/opentelemetry/configuration/__init__.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index 34fa2afa8fe..b010dec29d1 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -60,19 +60,10 @@ def __new__(cls) -> "Configuration": ) for key, value in configuration.items(): - underscored_key = "_{}".format(key) - - setattr(Configuration, underscored_key, value) setattr( Configuration, key, - property( - ( - lambda underscored_key: lambda self: getattr( - self, underscored_key - ) - )(underscored_key) - ), + property(lambda self, local_value=value: local_value), ) Configuration._instance = object.__new__(cls) From 342278adb1c50e351be33a64e8b0040d0b71e8f9 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 17:54:58 -0600 Subject: [PATCH 14/28] Fix lint --- .../tests/configuration/test_configuration.py | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/opentelemetry-api/tests/configuration/test_configuration.py b/opentelemetry-api/tests/configuration/test_configuration.py index 0c78a0123a2..7cefa060294 100644 --- a/opentelemetry-api/tests/configuration/test_configuration.py +++ b/opentelemetry-api/tests/configuration/test_configuration.py @@ -26,7 +26,7 @@ class TestConfiguration(TestCase): def configdir(self, tmpdir): # type: ignore # pylint: disable=no-self-use tmpdir.chdir() tmpdir.mkdir(".config").join("opentelemetry_python.json").write( - dumps({"tracer_provider": "default_tracer_provider"}) + dumps({"tracer_provider": "overridden_tracer_provider"}) ) def setUp(self): @@ -38,12 +38,20 @@ def tearDown(self): def test_singleton(self): self.assertIs(Configuration(), Configuration()) - @patch("os.path.expanduser") + def test_default_values(self): + self.assertEqual( + Configuration().tracer_provider, "default_tracer_provider" + ) # pylint: disable=no-member + self.assertEqual( + Configuration().meter_provider, "default_meter_provider" + ) # pylint: disable=no-member + + @patch("opentelemetry.configuration.expanduser") def test_configuration_file(self, mock_expanduser): # type: ignore mock_expanduser.return_value = getcwd() self.assertEqual( - Configuration().tracer_provider, "default_tracer_provider" + Configuration().tracer_provider, "overridden_tracer_provider" ) # pylint: disable=no-member self.assertEqual( Configuration().meter_provider, "default_meter_provider" @@ -61,19 +69,23 @@ def test_environment_variables(self): # type: ignore Configuration().meter_provider, "overridden_meter_provider" ) # pylint: disable=no-member - @patch("os.path.expanduser") + @patch("opentelemetry.configuration.expanduser") @patch.dict( "os.environ", - {"OPENTELEMETRY_PYTHON_METER_PROVIDER": "reoverridden_meter_provider"}, + { + "OPENTELEMETRY_PYTHON_TRACER_PROVIDER": ( + "reoverridden_tracer_provider" + ) + }, ) def test_configuration_file_environment_variables(self, mock_expanduser): # type: ignore mock_expanduser.return_value = getcwd() self.assertEqual( - Configuration().tracer_provider, "default_tracer_provider" + Configuration().tracer_provider, "reoverridden_tracer_provider" ) self.assertEqual( - Configuration().meter_provider, "reoverridden_meter_provider" + Configuration().meter_provider, "default_meter_provider" ) def test_property(self): From f5df21ac532aff7000cd6d31674831234fbe6de6 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 18:18:06 -0600 Subject: [PATCH 15/28] Revert changes that should not be in this PR --- docs/examples/http/tests/test_http.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/examples/http/tests/test_http.py b/docs/examples/http/tests/test_http.py index 0444e8d67d6..0ae81fe7de7 100644 --- a/docs/examples/http/tests/test_http.py +++ b/docs/examples/http/tests/test_http.py @@ -19,10 +19,11 @@ class TestHttpExample(unittest.TestCase): - def setUp(self): + @classmethod + def setup_class(cls): dirpath = os.path.dirname(os.path.realpath(__file__)) server_script = "{}/../server.py".format(dirpath) - self.server = subprocess.Popen([sys.executable, server_script]) + cls.server = subprocess.Popen([sys.executable, server_script]) sleep(1) def test_http(self): @@ -33,5 +34,6 @@ def test_http(self): ).decode() self.assertIn('name="/"', output) - def tearDown(self): - self.server.terminate() + @classmethod + def teardown_class(cls): + cls.server.terminate() From cbc1a03e27c9f44be3db64723b063e45c35741e1 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 11 Mar 2020 18:23:19 -0600 Subject: [PATCH 16/28] Fix lint --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index e1f28089664..4d13874fd34 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -428,7 +428,8 @@ def get_meter_provider() -> MeterProvider: try: _METER_PROVIDER = next( # type: ignore iter_entry_points( - "opentelemetry_meter_provider", configured_meter_provider # type: ignore + "opentelemetry_meter_provider", + name=configured_meter_provider, # type: ignore ) ).load()() except Exception: # pylint: disable=broad-except From cfcc34c8a17235e3d3d48d58b478fe09bf9ced6a Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 12 Mar 2020 18:03:53 -0600 Subject: [PATCH 17/28] Move iter_entry_points into the configuration manager --- .../opentelemetry/configuration/__init__.py | 40 ++++++++++++- .../src/opentelemetry/metrics/__init__.py | 28 +++------ .../src/opentelemetry/trace/__init__.py | 29 +++------- .../tests/configuration/test_configuration.py | 58 +++++++++++++++++-- 4 files changed, 107 insertions(+), 48 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index b010dec29d1..79a67f7268b 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -28,6 +28,10 @@ from json import load from os import environ from os.path import exists, expanduser, join +from pkg_resources import iter_entry_points +from logging import getLogger + +logger = getLogger(__name__) class Configuration: @@ -60,12 +64,46 @@ def __new__(cls) -> "Configuration": ) for key, value in configuration.items(): + underscored_key = "_{}".format(key) + + setattr(Configuration, underscored_key, None) setattr( Configuration, key, - property(lambda self, local_value=value: local_value), + property( + fget=lambda cls, local_key=key, local_value=value: + cls._load(key=local_key, value=local_value) + ), ) Configuration._instance = object.__new__(cls) return cls._instance + + @classmethod + def _load(cls, key=None, value=None): + underscored_key = "_{}".format(key) + + if getattr(cls, underscored_key) is None: + try: + setattr( + cls, + underscored_key, + next( # type: ignore + iter_entry_points( + "opentelemetry_{}".format(key), + name=value, # type: ignore + ) + ).load()() + ) + except Exception: # pylint: disable=broad-except + # FIXME Decide on how to handle this. Should an exception be + # raised here, or only a message should be logged and should + # we fall back to the default meter provider? + logger.error( + "Failed to load configured provider %s", + value, # type: ignore + ) + raise + + return getattr(cls, underscored_key) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 4d13874fd34..3d471f1c540 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -30,7 +30,6 @@ from logging import getLogger from typing import Callable, Dict, Sequence, Tuple, Type, TypeVar -from pkg_resources import iter_entry_points from opentelemetry.configuration import Configuration # type: ignore @@ -416,30 +415,17 @@ def get_meter( ) +def set_meter_provider(meter_provider: MeterProvider) -> None: + """Sets the current global :class:`~.MeterProvider` object.""" + global _METER_PROVIDER + _METER_PROVIDER = meter_provider + + def get_meter_provider() -> MeterProvider: """Gets the current global :class:`~.MeterProvider` object.""" global _METER_PROVIDER # pylint: disable=global-statement if _METER_PROVIDER is None: - configured_meter_provider = ( - Configuration().meter_provider # type: ignore # pylint: disable=no-member - ) - - try: - _METER_PROVIDER = next( # type: ignore - iter_entry_points( - "opentelemetry_meter_provider", - name=configured_meter_provider, # type: ignore - ) - ).load()() - except Exception: # pylint: disable=broad-except - # FIXME Decide on how to handle this. Should an exception be - # raised here, or only a message should be logged and should - # we fall back to the default meter provider? - logger.error( - "Failed to load configured meter provider %s", - configured_meter_provider, # type: ignore - ) - raise + _METER_PROVIDER = Configuration().meter_provider return _METER_PROVIDER # type: ignore diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index f1309ae7a34..fac88ba9f09 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -73,8 +73,6 @@ from contextlib import contextmanager from logging import getLogger -from pkg_resources import iter_entry_points - from opentelemetry.configuration import Configuration # type: ignore from opentelemetry.trace.status import Status from opentelemetry.util import types @@ -658,30 +656,17 @@ def get_tracer( ) +def set_tracer_provider(tracer_provider: TracerProvider) -> None: + """Sets the current global :class:`~.TracerProvider` object.""" + global _TRACER_PROVIDER + _TRACER_PROVIDER = tracer_provider + + def get_tracer_provider() -> TracerProvider: """Gets the current global :class:`~.TracerProvider` object.""" global _TRACER_PROVIDER # pylint: disable=global-statement if _TRACER_PROVIDER is None: - configured_tracer_provider = ( - Configuration().tracer_provider # type: ignore # pylint: disable=no-member - ) - - try: - _TRACER_PROVIDER = next( # type: ignore - iter_entry_points( - "opentelemetry_tracer_provider", - name=configured_tracer_provider, # type: ignore - ) - ).load()() - except Exception: # pylint: disable=broad-except - # FIXME Decide on how to handle this. Should an exception be - # raised here, or only a message should be logged and should - # we fall back to the default tracer provider? - logger.error( - "Failed to load tracer implementation: %s", - configured_tracer_provider, # type: ignore - ) - raise + _TRACER_PROVIDER = Configuration().tracer_provider return _TRACER_PROVIDER # type: ignore diff --git a/opentelemetry-api/tests/configuration/test_configuration.py b/opentelemetry-api/tests/configuration/test_configuration.py index 7cefa060294..bcdf3ce8172 100644 --- a/opentelemetry-api/tests/configuration/test_configuration.py +++ b/opentelemetry-api/tests/configuration/test_configuration.py @@ -22,6 +22,19 @@ class TestConfiguration(TestCase): + class IterEntryPointsMock: + def __init__(self, argument, name=None): + self._name = name + + def __next__(self): + return self + + def __call__(self): + return self._name + + def load(self): + return self + @fixture(autouse=True) def configdir(self, tmpdir): # type: ignore # pylint: disable=no-self-use tmpdir.chdir() @@ -38,7 +51,26 @@ def tearDown(self): def test_singleton(self): self.assertIs(Configuration(), Configuration()) - def test_default_values(self): + @patch( + "opentelemetry.configuration.iter_entry_points", + **{"side_effect": IterEntryPointsMock} + ) + def test_lazy(self, mock_iter_entry_points): + configuration = Configuration() + + self.assertIsNone(configuration._tracer_provider) + + configuration.tracer_provider + + self.assertEqual( + configuration._tracer_provider, "default_tracer_provider" + ) + + @patch( + "opentelemetry.configuration.iter_entry_points", + **{"side_effect": IterEntryPointsMock} + ) + def test_default_values(self, mock_iter_entry_points): self.assertEqual( Configuration().tracer_provider, "default_tracer_provider" ) # pylint: disable=no-member @@ -46,8 +78,14 @@ def test_default_values(self): Configuration().meter_provider, "default_meter_provider" ) # pylint: disable=no-member + @patch( + "opentelemetry.configuration.iter_entry_points", + **{"side_effect": IterEntryPointsMock} + ) @patch("opentelemetry.configuration.expanduser") - def test_configuration_file(self, mock_expanduser): # type: ignore + def test_configuration_file( + self, mock_expanduser, mock_iter_entry_points + ): # type: ignore mock_expanduser.return_value = getcwd() self.assertEqual( @@ -57,11 +95,17 @@ def test_configuration_file(self, mock_expanduser): # type: ignore Configuration().meter_provider, "default_meter_provider" ) # pylint: disable=no-member + @patch( + "opentelemetry.configuration.iter_entry_points", + **{"side_effect": IterEntryPointsMock} + ) @patch.dict( "os.environ", {"OPENTELEMETRY_PYTHON_METER_PROVIDER": "overridden_meter_provider"}, ) - def test_environment_variables(self): # type: ignore + def test_environment_variables( + self, mock_iter_entry_points + ): # type: ignore self.assertEqual( Configuration().tracer_provider, "default_tracer_provider" ) # pylint: disable=no-member @@ -69,6 +113,10 @@ def test_environment_variables(self): # type: ignore Configuration().meter_provider, "overridden_meter_provider" ) # pylint: disable=no-member + @patch( + "opentelemetry.configuration.iter_entry_points", + **{"side_effect": IterEntryPointsMock} + ) @patch("opentelemetry.configuration.expanduser") @patch.dict( "os.environ", @@ -78,7 +126,9 @@ def test_environment_variables(self): # type: ignore ) }, ) - def test_configuration_file_environment_variables(self, mock_expanduser): # type: ignore + def test_configuration_file_environment_variables( + self, mock_expanduser, mock_iter_entry_points + ): # type: ignore mock_expanduser.return_value = getcwd() self.assertEqual( From 5adb183098f4771a69013fed3f27b2d5b0b94912 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 12 Mar 2020 18:40:26 -0600 Subject: [PATCH 18/28] Fix test cases for exts --- ext/opentelemetry-ext-flask/tests/conftest.py | 25 ------------------- .../tests/conftest.py | 25 ------------------- .../tests/test_shim.py | 3 ++- .../tests/conftest.py | 25 ------------------- .../test_otcollector_metrics_exporter.py | 8 ++---- .../tests/conftest.py | 25 ------------------- .../tests/test_prometheus_exporter.py | 3 ++- .../ext/testutil/wsgitestutil.py | 3 ++- ext/opentelemetry-ext-wsgi/tests/conftest.py | 25 ------------------- 9 files changed, 8 insertions(+), 134 deletions(-) delete mode 100644 ext/opentelemetry-ext-flask/tests/conftest.py delete mode 100644 ext/opentelemetry-ext-opentracing-shim/tests/conftest.py delete mode 100644 ext/opentelemetry-ext-otcollector/tests/conftest.py delete mode 100644 ext/opentelemetry-ext-prometheus/tests/conftest.py delete mode 100644 ext/opentelemetry-ext-wsgi/tests/conftest.py diff --git a/ext/opentelemetry-ext-flask/tests/conftest.py b/ext/opentelemetry-ext-flask/tests/conftest.py deleted file mode 100644 index ff9e5ea43bb..00000000000 --- a/ext/opentelemetry-ext-flask/tests/conftest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from os import environ - - -def pytest_sessionstart(session): # pylint: disable=unused-argument - environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" - environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" - - -def pytest_sessionfinish(session): # pylint: disable=unused-argument - environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") - environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/ext/opentelemetry-ext-opentracing-shim/tests/conftest.py b/ext/opentelemetry-ext-opentracing-shim/tests/conftest.py deleted file mode 100644 index ff9e5ea43bb..00000000000 --- a/ext/opentelemetry-ext-opentracing-shim/tests/conftest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from os import environ - - -def pytest_sessionstart(session): # pylint: disable=unused-argument - environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" - environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" - - -def pytest_sessionfinish(session): # pylint: disable=unused-argument - environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") - environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py b/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py index 8a025be0368..9c8b57ebbc6 100644 --- a/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py +++ b/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py @@ -24,6 +24,7 @@ import opentelemetry.ext.opentracing_shim as opentracingshim from opentelemetry import propagators, trace from opentelemetry.context import Context +from opentelemetry.sdk.trace import TracerProvider from opentelemetry.ext.opentracing_shim import util from opentelemetry.trace.propagation import ( get_span_from_context, @@ -42,7 +43,7 @@ class TestShim(TestCase): def setUp(self): """Create an OpenTelemetry tracer and a shim before every test case.""" - + trace.set_tracer_provider(TracerProvider()) self.shim = opentracingshim.create_tracer(trace.get_tracer_provider()) @classmethod diff --git a/ext/opentelemetry-ext-otcollector/tests/conftest.py b/ext/opentelemetry-ext-otcollector/tests/conftest.py deleted file mode 100644 index ff9e5ea43bb..00000000000 --- a/ext/opentelemetry-ext-otcollector/tests/conftest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from os import environ - - -def pytest_sessionstart(session): # pylint: disable=unused-argument - environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" - environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" - - -def pytest_sessionfinish(session): # pylint: disable=unused-argument - environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") - environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py index 04b3ef0c42e..5bb22e983ab 100644 --- a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py +++ b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py @@ -20,6 +20,7 @@ from opencensus.proto.metrics.v1 import metrics_pb2 from opentelemetry import metrics +from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.ext.otcollector import metrics_exporter from opentelemetry.sdk.metrics import Counter, Measure from opentelemetry.sdk.metrics.export import ( @@ -34,16 +35,11 @@ class TestCollectorMetricsExporter(unittest.TestCase): @classmethod def setUpClass(cls): # pylint: disable=protected-access - cls._meter_defaults = metrics._METER_PROVIDER + metrics.set_meter_provider(MeterProvider()) cls._meter = metrics.get_meter(__name__) kvp = {"environment": "staging"} cls._test_label_set = cls._meter.get_label_set(kvp) - @classmethod - def tearDownClass(cls): - # pylint: disable=protected-access - metrics._METER_PROVIDER = cls._meter_defaults - def test_constructor(self): mock_get_node = mock.Mock() patch = mock.patch( diff --git a/ext/opentelemetry-ext-prometheus/tests/conftest.py b/ext/opentelemetry-ext-prometheus/tests/conftest.py deleted file mode 100644 index ff9e5ea43bb..00000000000 --- a/ext/opentelemetry-ext-prometheus/tests/conftest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from os import environ - - -def pytest_sessionstart(session): # pylint: disable=unused-argument - environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" - environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" - - -def pytest_sessionfinish(session): # pylint: disable=unused-argument - environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") - environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py index a0079b1fee1..0e01030e416 100644 --- a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py +++ b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py @@ -21,7 +21,7 @@ CustomCollector, PrometheusMetricsExporter, ) -from opentelemetry.metrics import get_meter_provider +from opentelemetry.metrics import set_meter_provider, get_meter_provider from opentelemetry.sdk import metrics from opentelemetry.sdk.metrics.export import MetricRecord, MetricsExportResult from opentelemetry.sdk.metrics.export.aggregate import CounterAggregator @@ -29,6 +29,7 @@ class TestPrometheusMetricExporter(unittest.TestCase): def setUp(self): + set_meter_provider(metrics.MeterProvider()) self._meter = get_meter_provider().get_meter(__name__) self._test_metric = self._meter.create_metric( "testname", diff --git a/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py b/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py index 39c2be27f9e..6ebcd55ff09 100644 --- a/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py +++ b/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py @@ -4,7 +4,7 @@ from importlib import reload from opentelemetry import trace as trace_api -from opentelemetry.sdk.trace import export +from opentelemetry.sdk.trace import export, TracerProvider from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( InMemorySpanExporter, ) @@ -16,6 +16,7 @@ class WsgiTestBase(unittest.TestCase): @classmethod def setUpClass(cls): global _MEMORY_EXPORTER # pylint:disable=global-statement + trace_api.set_tracer_provider(TracerProvider()) tracer_provider = trace_api.get_tracer_provider() _MEMORY_EXPORTER = InMemorySpanExporter() span_processor = export.SimpleExportSpanProcessor(_MEMORY_EXPORTER) diff --git a/ext/opentelemetry-ext-wsgi/tests/conftest.py b/ext/opentelemetry-ext-wsgi/tests/conftest.py deleted file mode 100644 index ff9e5ea43bb..00000000000 --- a/ext/opentelemetry-ext-wsgi/tests/conftest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from os import environ - - -def pytest_sessionstart(session): # pylint: disable=unused-argument - environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" - environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" - - -def pytest_sessionfinish(session): # pylint: disable=unused-argument - environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") - environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") From cfc1a09377d7c18b3f57fb5dff259e6d11333fb1 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 12 Mar 2020 18:44:53 -0600 Subject: [PATCH 19/28] Remove remaining conftest.py files --- docs/examples/basic_tracer/tests/conftest.py | 25 -------------------- docs/examples/basic_tracer/tracer.py | 2 ++ docs/examples/http/server.py | 2 ++ docs/examples/http/tests/conftest.py | 25 -------------------- docs/examples/http/tracer_client.py | 2 ++ 5 files changed, 6 insertions(+), 50 deletions(-) delete mode 100644 docs/examples/basic_tracer/tests/conftest.py delete mode 100644 docs/examples/http/tests/conftest.py diff --git a/docs/examples/basic_tracer/tests/conftest.py b/docs/examples/basic_tracer/tests/conftest.py deleted file mode 100644 index ff9e5ea43bb..00000000000 --- a/docs/examples/basic_tracer/tests/conftest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from os import environ - - -def pytest_sessionstart(session): # pylint: disable=unused-argument - environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" - environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" - - -def pytest_sessionfinish(session): # pylint: disable=unused-argument - environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") - environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/docs/examples/basic_tracer/tracer.py b/docs/examples/basic_tracer/tracer.py index a8ba537cc9c..92f96be89fd 100755 --- a/docs/examples/basic_tracer/tracer.py +++ b/docs/examples/basic_tracer/tracer.py @@ -17,6 +17,7 @@ import os from opentelemetry import trace +from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ( BatchExportSpanProcessor, ConsoleSpanExporter, @@ -52,6 +53,7 @@ # SpanExporter receives the spans and send them to the target location. span_processor = BatchExportSpanProcessor(exporter) +trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor(span_processor) with tracer.start_as_current_span("foo"): with tracer.start_as_current_span("bar"): diff --git a/docs/examples/http/server.py b/docs/examples/http/server.py index d706a269606..34c501a0759 100755 --- a/docs/examples/http/server.py +++ b/docs/examples/http/server.py @@ -20,6 +20,7 @@ import requests from opentelemetry import trace +from opentelemetry.sdk.trace import TracerProvider from opentelemetry.ext import http_requests from opentelemetry.ext.wsgi import OpenTelemetryMiddleware from opentelemetry.sdk.trace.export import ( @@ -42,6 +43,7 @@ # SpanExporter receives the spans and send them to the target location. span_processor = BatchExportSpanProcessor(exporter) +trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor(span_processor) # Integrations are the glue that binds the OpenTelemetry API and the diff --git a/docs/examples/http/tests/conftest.py b/docs/examples/http/tests/conftest.py deleted file mode 100644 index ff9e5ea43bb..00000000000 --- a/docs/examples/http/tests/conftest.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2020, OpenTelemetry Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from os import environ - - -def pytest_sessionstart(session): # pylint: disable=unused-argument - environ["OPENTELEMETRY_PYTHON_TRACER_PROVIDER"] = "sdk_tracer_provider" - environ["OPENTELEMETRY_PYTHON_METER_PROVIDER"] = "sdk_meter_provider" - - -def pytest_sessionfinish(session): # pylint: disable=unused-argument - environ.pop("OPENTELEMETRY_PYTHON_TRACER_PROVIDER") - environ.pop("OPENTELEMETRY_PYTHON_METER_PROVIDER") diff --git a/docs/examples/http/tracer_client.py b/docs/examples/http/tracer_client.py index 3ae6dc9ffed..593596df430 100755 --- a/docs/examples/http/tracer_client.py +++ b/docs/examples/http/tracer_client.py @@ -19,6 +19,7 @@ import requests from opentelemetry import trace +from opentelemetry.sdk.trace import TracerProvider from opentelemetry.ext import http_requests from opentelemetry.sdk.trace.export import ( BatchExportSpanProcessor, @@ -36,6 +37,7 @@ else: exporter = ConsoleSpanExporter() +trace.set_tracer_provider(TracerProvider()) tracer_provider = trace.get_tracer_provider() # SpanExporter receives the spans and send them to the target location. From aed33989b94d6619c0918d3a66bd28d728be4fa1 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Thu, 12 Mar 2020 19:03:30 -0600 Subject: [PATCH 20/28] Fixing lint WIP --- docs/examples/http/server.py | 2 +- docs/examples/http/tracer_client.py | 2 +- .../tests/test_shim.py | 2 +- .../tests/test_otcollector_metrics_exporter.py | 3 +-- .../tests/test_prometheus_exporter.py | 2 +- .../src/opentelemetry/ext/testutil/wsgitestutil.py | 2 +- .../src/opentelemetry/configuration/__init__.py | 10 ++++++---- .../src/opentelemetry/metrics/__init__.py | 1 - 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/examples/http/server.py b/docs/examples/http/server.py index 34c501a0759..a665abdd49d 100755 --- a/docs/examples/http/server.py +++ b/docs/examples/http/server.py @@ -20,9 +20,9 @@ import requests from opentelemetry import trace -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.ext import http_requests from opentelemetry.ext.wsgi import OpenTelemetryMiddleware +from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ( BatchExportSpanProcessor, ConsoleSpanExporter, diff --git a/docs/examples/http/tracer_client.py b/docs/examples/http/tracer_client.py index 593596df430..0e83c5c53ff 100755 --- a/docs/examples/http/tracer_client.py +++ b/docs/examples/http/tracer_client.py @@ -19,8 +19,8 @@ import requests from opentelemetry import trace -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.ext import http_requests +from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ( BatchExportSpanProcessor, ConsoleSpanExporter, diff --git a/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py b/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py index 9c8b57ebbc6..1d619ab2770 100644 --- a/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py +++ b/ext/opentelemetry-ext-opentracing-shim/tests/test_shim.py @@ -24,8 +24,8 @@ import opentelemetry.ext.opentracing_shim as opentracingshim from opentelemetry import propagators, trace from opentelemetry.context import Context -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.ext.opentracing_shim import util +from opentelemetry.sdk.trace import TracerProvider from opentelemetry.trace.propagation import ( get_span_from_context, set_span_in_context, diff --git a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py index 5bb22e983ab..ab6f4c8ccd5 100644 --- a/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py +++ b/ext/opentelemetry-ext-otcollector/tests/test_otcollector_metrics_exporter.py @@ -20,9 +20,8 @@ from opencensus.proto.metrics.v1 import metrics_pb2 from opentelemetry import metrics -from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.ext.otcollector import metrics_exporter -from opentelemetry.sdk.metrics import Counter, Measure +from opentelemetry.sdk.metrics import Counter, Measure, MeterProvider from opentelemetry.sdk.metrics.export import ( MetricRecord, MetricsExportResult, diff --git a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py index 0e01030e416..512a3170adb 100644 --- a/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py +++ b/ext/opentelemetry-ext-prometheus/tests/test_prometheus_exporter.py @@ -21,7 +21,7 @@ CustomCollector, PrometheusMetricsExporter, ) -from opentelemetry.metrics import set_meter_provider, get_meter_provider +from opentelemetry.metrics import get_meter_provider, set_meter_provider from opentelemetry.sdk import metrics from opentelemetry.sdk.metrics.export import MetricRecord, MetricsExportResult from opentelemetry.sdk.metrics.export.aggregate import CounterAggregator diff --git a/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py b/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py index 6ebcd55ff09..cdce28b9078 100644 --- a/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py +++ b/ext/opentelemetry-ext-testutil/src/opentelemetry/ext/testutil/wsgitestutil.py @@ -4,7 +4,7 @@ from importlib import reload from opentelemetry import trace as trace_api -from opentelemetry.sdk.trace import export, TracerProvider +from opentelemetry.sdk.trace import TracerProvider, export from opentelemetry.sdk.trace.export.in_memory_span_exporter import ( InMemorySpanExporter, ) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index 79a67f7268b..8ecd32ee36f 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -26,10 +26,11 @@ """ from json import load +from logging import getLogger from os import environ from os.path import exists, expanduser, join + from pkg_resources import iter_entry_points -from logging import getLogger logger = getLogger(__name__) @@ -71,8 +72,9 @@ def __new__(cls) -> "Configuration": Configuration, key, property( - fget=lambda cls, local_key=key, local_value=value: - cls._load(key=local_key, value=local_value) + fget=lambda cls, local_key=key, local_value=value: cls._load( + key=local_key, value=local_value + ) ), ) @@ -94,7 +96,7 @@ def _load(cls, key=None, value=None): "opentelemetry_{}".format(key), name=value, # type: ignore ) - ).load()() + ).load()(), ) except Exception: # pylint: disable=broad-except # FIXME Decide on how to handle this. Should an exception be diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 3d471f1c540..b7aa102f639 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -30,7 +30,6 @@ from logging import getLogger from typing import Callable, Dict, Sequence, Tuple, Type, TypeVar - from opentelemetry.configuration import Configuration # type: ignore logger = getLogger(__name__) From 7703cdddaadef2058786a24e4735264d64dee25b Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 13 Mar 2020 11:19:14 -0600 Subject: [PATCH 21/28] Fix lint --- .../src/opentelemetry/metrics/__init__.py | 6 ++-- .../src/opentelemetry/trace/__init__.py | 6 ++-- .../tests/configuration/test_configuration.py | 31 +++++++++++++------ 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index b7aa102f639..fccaa04fc1d 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -416,7 +416,7 @@ def get_meter( def set_meter_provider(meter_provider: MeterProvider) -> None: """Sets the current global :class:`~.MeterProvider` object.""" - global _METER_PROVIDER + global _METER_PROVIDER # pylint: disable=global-statement _METER_PROVIDER = meter_provider @@ -425,6 +425,8 @@ def get_meter_provider() -> MeterProvider: global _METER_PROVIDER # pylint: disable=global-statement if _METER_PROVIDER is None: - _METER_PROVIDER = Configuration().meter_provider + _METER_PROVIDER = ( + Configuration().meter_provider # pylint: disable=no-member + ) return _METER_PROVIDER # type: ignore diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index fac88ba9f09..aae94f58b84 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -658,7 +658,7 @@ def get_tracer( def set_tracer_provider(tracer_provider: TracerProvider) -> None: """Sets the current global :class:`~.TracerProvider` object.""" - global _TRACER_PROVIDER + global _TRACER_PROVIDER # pylint: disable=global-statement _TRACER_PROVIDER = tracer_provider @@ -667,6 +667,8 @@ def get_tracer_provider() -> TracerProvider: global _TRACER_PROVIDER # pylint: disable=global-statement if _TRACER_PROVIDER is None: - _TRACER_PROVIDER = Configuration().tracer_provider + _TRACER_PROVIDER = ( + Configuration().tracer_provider # pylint: disable=no-member + ) return _TRACER_PROVIDER # type: ignore diff --git a/opentelemetry-api/tests/configuration/test_configuration.py b/opentelemetry-api/tests/configuration/test_configuration.py index bcdf3ce8172..c8a6fdbfca3 100644 --- a/opentelemetry-api/tests/configuration/test_configuration.py +++ b/opentelemetry-api/tests/configuration/test_configuration.py @@ -23,7 +23,9 @@ class TestConfiguration(TestCase): class IterEntryPointsMock: - def __init__(self, argument, name=None): + def __init__( + self, argument, name=None + ): # pylint: disable=unused-argument self._name = name def __next__(self): @@ -55,22 +57,29 @@ def test_singleton(self): "opentelemetry.configuration.iter_entry_points", **{"side_effect": IterEntryPointsMock} ) - def test_lazy(self, mock_iter_entry_points): + def test_lazy( + self, mock_iter_entry_points, # pylint: disable=unused-argument + ): configuration = Configuration() - self.assertIsNone(configuration._tracer_provider) + self.assertIsNone( + configuration._tracer_provider # pylint: disable=no-member,protected-access + ) - configuration.tracer_provider + configuration.tracer_provider # pylint: disable=pointless-statement self.assertEqual( - configuration._tracer_provider, "default_tracer_provider" + configuration._tracer_provider, # pylint: disable=no-member,protected-access + "default_tracer_provider", ) @patch( "opentelemetry.configuration.iter_entry_points", **{"side_effect": IterEntryPointsMock} ) - def test_default_values(self, mock_iter_entry_points): + def test_default_values( + self, mock_iter_entry_points # pylint: disable=unused-argument + ): self.assertEqual( Configuration().tracer_provider, "default_tracer_provider" ) # pylint: disable=no-member @@ -84,7 +93,9 @@ def test_default_values(self, mock_iter_entry_points): ) @patch("opentelemetry.configuration.expanduser") def test_configuration_file( - self, mock_expanduser, mock_iter_entry_points + self, + mock_expanduser, + mock_iter_entry_points, # pylint: disable=unused-argument ): # type: ignore mock_expanduser.return_value = getcwd() @@ -104,7 +115,7 @@ def test_configuration_file( {"OPENTELEMETRY_PYTHON_METER_PROVIDER": "overridden_meter_provider"}, ) def test_environment_variables( - self, mock_iter_entry_points + self, mock_iter_entry_points # pylint: disable=unused-argument ): # type: ignore self.assertEqual( Configuration().tracer_provider, "default_tracer_provider" @@ -127,7 +138,9 @@ def test_environment_variables( }, ) def test_configuration_file_environment_variables( - self, mock_expanduser, mock_iter_entry_points + self, + mock_expanduser, + mock_iter_entry_points, # pylint: disable=unused-argument ): # type: ignore mock_expanduser.return_value = getcwd() From 33c7e1f90eaae4cd17504562ee2baa6a99148d71 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 13 Mar 2020 11:37:40 -0600 Subject: [PATCH 22/28] More and more fixing --- .../opentelemetry/configuration/__init__.py | 8 +++----- .../src/opentelemetry/metrics/__init__.py | 2 +- .../src/opentelemetry/trace/__init__.py | 2 +- .../tests/configuration/test_configuration.py | 20 +++++++++---------- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index 8ecd32ee36f..447e265b00d 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -91,10 +91,9 @@ def _load(cls, key=None, value=None): setattr( cls, underscored_key, - next( # type: ignore + next( iter_entry_points( - "opentelemetry_{}".format(key), - name=value, # type: ignore + "opentelemetry_{}".format(key), name=value, ) ).load()(), ) @@ -103,8 +102,7 @@ def _load(cls, key=None, value=None): # raised here, or only a message should be logged and should # we fall back to the default meter provider? logger.error( - "Failed to load configured provider %s", - value, # type: ignore + "Failed to load configured provider %s", value, ) raise diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index fccaa04fc1d..c37119529b6 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -426,7 +426,7 @@ def get_meter_provider() -> MeterProvider: if _METER_PROVIDER is None: _METER_PROVIDER = ( - Configuration().meter_provider # pylint: disable=no-member + Configuration().meter_provider # type: ignore # pylint: disable=no-member ) return _METER_PROVIDER # type: ignore diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index aae94f58b84..e23404f707b 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -668,7 +668,7 @@ def get_tracer_provider() -> TracerProvider: if _TRACER_PROVIDER is None: _TRACER_PROVIDER = ( - Configuration().tracer_provider # pylint: disable=no-member + Configuration().tracer_provider # type: ignore # pylint: disable=no-member ) return _TRACER_PROVIDER # type: ignore diff --git a/opentelemetry-api/tests/configuration/test_configuration.py b/opentelemetry-api/tests/configuration/test_configuration.py index c8a6fdbfca3..8d536c27be9 100644 --- a/opentelemetry-api/tests/configuration/test_configuration.py +++ b/opentelemetry-api/tests/configuration/test_configuration.py @@ -55,9 +55,9 @@ def test_singleton(self): @patch( "opentelemetry.configuration.iter_entry_points", - **{"side_effect": IterEntryPointsMock} + **{"side_effect": IterEntryPointsMock} # type: ignore ) - def test_lazy( + def test_lazy( # type: ignore self, mock_iter_entry_points, # pylint: disable=unused-argument ): configuration = Configuration() @@ -75,9 +75,9 @@ def test_lazy( @patch( "opentelemetry.configuration.iter_entry_points", - **{"side_effect": IterEntryPointsMock} + **{"side_effect": IterEntryPointsMock} # type: ignore ) - def test_default_values( + def test_default_values( # type: ignore self, mock_iter_entry_points # pylint: disable=unused-argument ): self.assertEqual( @@ -89,10 +89,10 @@ def test_default_values( @patch( "opentelemetry.configuration.iter_entry_points", - **{"side_effect": IterEntryPointsMock} + **{"side_effect": IterEntryPointsMock} # type: ignore ) @patch("opentelemetry.configuration.expanduser") - def test_configuration_file( + def test_configuration_file( # type: ignore self, mock_expanduser, mock_iter_entry_points, # pylint: disable=unused-argument @@ -108,13 +108,13 @@ def test_configuration_file( @patch( "opentelemetry.configuration.iter_entry_points", - **{"side_effect": IterEntryPointsMock} + **{"side_effect": IterEntryPointsMock} # type: ignore ) @patch.dict( "os.environ", {"OPENTELEMETRY_PYTHON_METER_PROVIDER": "overridden_meter_provider"}, ) - def test_environment_variables( + def test_environment_variables( # type: ignore self, mock_iter_entry_points # pylint: disable=unused-argument ): # type: ignore self.assertEqual( @@ -126,7 +126,7 @@ def test_environment_variables( @patch( "opentelemetry.configuration.iter_entry_points", - **{"side_effect": IterEntryPointsMock} + **{"side_effect": IterEntryPointsMock} # type: ignore ) @patch("opentelemetry.configuration.expanduser") @patch.dict( @@ -137,7 +137,7 @@ def test_environment_variables( ) }, ) - def test_configuration_file_environment_variables( + def test_configuration_file_environment_variables( # type: ignore self, mock_expanduser, mock_iter_entry_points, # pylint: disable=unused-argument From 0ea8bd5cd5c51d67e782359e40b0cb19fcfa5978 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 13 Mar 2020 14:52:25 -0600 Subject: [PATCH 23/28] Update opentelemetry-api/setup.py Co-Authored-By: Chris Kleinknecht --- opentelemetry-api/setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/opentelemetry-api/setup.py b/opentelemetry-api/setup.py index b2266dd23b4..5eb91d1f1b6 100644 --- a/opentelemetry-api/setup.py +++ b/opentelemetry-api/setup.py @@ -59,7 +59,6 @@ zip_safe=False, entry_points={ "opentelemetry_context": [ - "default_context = opentelemetry.context:DefaultContext", "contextvars_context = " "opentelemetry.context.contextvars_context:" "ContextVarsRuntimeContext", From 05944d8b0bd204588723225b7727754f28ab0817 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 13 Mar 2020 16:33:45 -0600 Subject: [PATCH 24/28] Remove configuration file from manager --- .../opentelemetry/configuration/__init__.py | 14 ------ .../configuration/opentelemetry_python.json | 4 -- .../tests/configuration/test_configuration.py | 47 ------------------- tests/w3c_tracecontext_validation_server.py | 10 +--- 4 files changed, 2 insertions(+), 73 deletions(-) delete mode 100644 opentelemetry-api/src/opentelemetry/configuration/opentelemetry_python.json diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index 447e265b00d..41261ae61cf 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -25,10 +25,8 @@ powerful one, Dynaconf, for example. """ -from json import load from logging import getLogger from os import environ -from os.path import exists, expanduser, join from pkg_resources import iter_entry_points @@ -47,18 +45,6 @@ def __new__(cls) -> "Configuration": key: "default_{}".format(key) for key in cls.__slots__ } - configuration_file_path = join( - expanduser("~"), ".config", "opentelemetry_python.json" - ) - - if exists(configuration_file_path): - - with open(configuration_file_path) as configuration_file: - file_configuration = load(configuration_file) - - for key, value in configuration.items(): - configuration[key] = file_configuration.get(key, value) - for key, value in configuration.items(): configuration[key] = environ.get( "OPENTELEMETRY_PYTHON_{}".format(key.upper()), value diff --git a/opentelemetry-api/src/opentelemetry/configuration/opentelemetry_python.json b/opentelemetry-api/src/opentelemetry/configuration/opentelemetry_python.json deleted file mode 100644 index c0ac3f4ff93..00000000000 --- a/opentelemetry-api/src/opentelemetry/configuration/opentelemetry_python.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "tracer_provider": "default_tracer_provider", - "meter_provider": "default_meter_provider" -} diff --git a/opentelemetry-api/tests/configuration/test_configuration.py b/opentelemetry-api/tests/configuration/test_configuration.py index 8d536c27be9..754f9c48942 100644 --- a/opentelemetry-api/tests/configuration/test_configuration.py +++ b/opentelemetry-api/tests/configuration/test_configuration.py @@ -13,7 +13,6 @@ # limitations under the License. from json import dumps -from os import getcwd from unittest import TestCase from unittest.mock import patch @@ -87,25 +86,6 @@ def test_default_values( # type: ignore Configuration().meter_provider, "default_meter_provider" ) # pylint: disable=no-member - @patch( - "opentelemetry.configuration.iter_entry_points", - **{"side_effect": IterEntryPointsMock} # type: ignore - ) - @patch("opentelemetry.configuration.expanduser") - def test_configuration_file( # type: ignore - self, - mock_expanduser, - mock_iter_entry_points, # pylint: disable=unused-argument - ): # type: ignore - mock_expanduser.return_value = getcwd() - - self.assertEqual( - Configuration().tracer_provider, "overridden_tracer_provider" - ) # pylint: disable=no-member - self.assertEqual( - Configuration().meter_provider, "default_meter_provider" - ) # pylint: disable=no-member - @patch( "opentelemetry.configuration.iter_entry_points", **{"side_effect": IterEntryPointsMock} # type: ignore @@ -124,33 +104,6 @@ def test_environment_variables( # type: ignore Configuration().meter_provider, "overridden_meter_provider" ) # pylint: disable=no-member - @patch( - "opentelemetry.configuration.iter_entry_points", - **{"side_effect": IterEntryPointsMock} # type: ignore - ) - @patch("opentelemetry.configuration.expanduser") - @patch.dict( - "os.environ", - { - "OPENTELEMETRY_PYTHON_TRACER_PROVIDER": ( - "reoverridden_tracer_provider" - ) - }, - ) - def test_configuration_file_environment_variables( # type: ignore - self, - mock_expanduser, - mock_iter_entry_points, # pylint: disable=unused-argument - ): # type: ignore - mock_expanduser.return_value = getcwd() - - self.assertEqual( - Configuration().tracer_provider, "reoverridden_tracer_provider" - ) - self.assertEqual( - Configuration().meter_provider, "default_meter_provider" - ) - def test_property(self): with self.assertRaises(AttributeError): Configuration().tracer_provider = "new_tracer_provider" diff --git a/tests/w3c_tracecontext_validation_server.py b/tests/w3c_tracecontext_validation_server.py index ddbbbd383f0..41a0f4bcfbd 100644 --- a/tests/w3c_tracecontext_validation_server.py +++ b/tests/w3c_tracecontext_validation_server.py @@ -19,7 +19,6 @@ """ import json -from os import environ import flask import requests @@ -27,14 +26,8 @@ # FIXME This could likely be avoided by integrating this script into the # standard test running mechanisms. -environ[ - "OPENTELEMETRY_PYTHON_TRACER_PROVIDER" -] = "sdk_tracer_provider" # isort:skip -environ[ - "OPENTELEMETRY_PYTHON_METER_PROVIDER" -] = "sdk_meter_provider" # isort:skip - from opentelemetry import trace # noqa # isort:skip +from opentelemetry.sdk.trace import TracerProvider from opentelemetry.ext import http_requests # noqa # isort:skip" from opentelemetry.ext.wsgi import OpenTelemetryMiddleware # noqa # isort:skip from opentelemetry.sdk.trace.export import ( # noqa # isort:skip @@ -45,6 +38,7 @@ # Integrations are the glue that binds the OpenTelemetry API and the # frameworks and libraries that are used together, automatically creating # Spans and propagating context as appropriate. +trace.set_tracer_provider(TracerProvider()) http_requests.enable(trace.get_tracer_provider()) # SpanExporter receives the spans and send them to the target location. From e376833f88707cd97d39ebee5b9a6c25ef9bffd7 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 13 Mar 2020 16:39:24 -0600 Subject: [PATCH 25/28] More fixing --- tests/w3c_tracecontext_validation_server.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/w3c_tracecontext_validation_server.py b/tests/w3c_tracecontext_validation_server.py index 41a0f4bcfbd..c2119f95873 100644 --- a/tests/w3c_tracecontext_validation_server.py +++ b/tests/w3c_tracecontext_validation_server.py @@ -23,11 +23,12 @@ import flask import requests +from opentelemetry.sdk.trace import TracerProvider + # FIXME This could likely be avoided by integrating this script into the # standard test running mechanisms. from opentelemetry import trace # noqa # isort:skip -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.ext import http_requests # noqa # isort:skip" from opentelemetry.ext.wsgi import OpenTelemetryMiddleware # noqa # isort:skip from opentelemetry.sdk.trace.export import ( # noqa # isort:skip From 76bb1252def4ee206479e0bce8200ce783eb8c9e Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 13 Mar 2020 17:20:01 -0600 Subject: [PATCH 26/28] Fix last test case --- docs/examples/basic_tracer/tracer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/basic_tracer/tracer.py b/docs/examples/basic_tracer/tracer.py index 92f96be89fd..8982e5cd7b1 100755 --- a/docs/examples/basic_tracer/tracer.py +++ b/docs/examples/basic_tracer/tracer.py @@ -45,6 +45,7 @@ print("Using ConsoleSpanExporter") exporter = ConsoleSpanExporter() +trace.set_tracer_provider(TracerProvider()) # 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. @@ -52,9 +53,8 @@ # SpanExporter receives the spans and send them to the target location. span_processor = BatchExportSpanProcessor(exporter) - -trace.set_tracer_provider(TracerProvider()) trace.get_tracer_provider().add_span_processor(span_processor) + with tracer.start_as_current_span("foo"): with tracer.start_as_current_span("bar"): with tracer.start_as_current_span("baz"): From d7ed20ea5a195e24808e92c9f40c536434d8fe92 Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Fri, 13 Mar 2020 17:54:55 -0600 Subject: [PATCH 27/28] Documenting the configuration manager --- .../opentelemetry/configuration/__init__.py | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index 41261ae61cf..312696293ff 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -18,11 +18,45 @@ """ Simple configuration manager -This configuration manager reads configuration values from a JSON file, the -values read there can be overriden by environment variables. - -It would probably be better to replace this configuration manager with a more -powerful one, Dynaconf, for example. +This is a configuration manager for the Tracer and Meter providers. It reads +configuration from environment variables prefixed with OPENTELEMETRY_PYHTON_: + +1. OPENTELEMETRY_PYTHON_TRACER_PROVIDER +2. OPENTELEMETRY_PYTHON_METER_PROVIDER + +The value of these environment variables should be the name of the entry point +that points to the class that implements either provider. This OpenTelemetry +API package provides one entry point for each, which can be found in the +setup.py file: + +entry_points={ + ... + "opentelemetry_meter_provider": [ + "default_meter_provider = " + "opentelemetry.metrics:DefaultMeterProvider" + ], + "opentelemetry_tracer_provider": [ + "default_tracer_provider = " + "opentelemetry.trace:DefaultTracerProvider" + ], +} + +To use the meter provider above, then the +OPENTELEMETRY_PYTHON_METER_PROVIDER should be set to +"default_meter_provider" (this is not actually necessary since the +OpenTelemetry API provided providers are the default ones used if no +configuration is found in the environment variables). + +Once this is done, the configuration manager can be used by simply importing +it from opentelemetry.configuration.Configuration. This is a class that can +be instantiated as many times as needed without concern because it will +always produce the same instance. Its attributes are lazy loaded and they +hold an instance of their corresponding provider. So, for example, to get +the configured meter provider: + +from opentelemetry.configuration import Configuration + +tracer_provider = Configuration().tracer_provider """ from logging import getLogger From 2920992da3aedfa7f8dda46b8386c7d577680551 Mon Sep 17 00:00:00 2001 From: Chris Kleinknecht Date: Sat, 14 Mar 2020 12:56:43 -0700 Subject: [PATCH 28/28] Update opentelemetry-api/src/opentelemetry/configuration/__init__.py --- opentelemetry-api/src/opentelemetry/configuration/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/configuration/__init__.py b/opentelemetry-api/src/opentelemetry/configuration/__init__.py index 312696293ff..2e6c29aa331 100644 --- a/opentelemetry-api/src/opentelemetry/configuration/__init__.py +++ b/opentelemetry-api/src/opentelemetry/configuration/__init__.py @@ -19,7 +19,7 @@ Simple configuration manager This is a configuration manager for the Tracer and Meter providers. It reads -configuration from environment variables prefixed with OPENTELEMETRY_PYHTON_: +configuration from environment variables prefixed with OPENTELEMETRY_PYTHON_: 1. OPENTELEMETRY_PYTHON_TRACER_PROVIDER 2. OPENTELEMETRY_PYTHON_METER_PROVIDER