Skip to content

Commit 0011637

Browse files
author
alrex
authored
Remove SDK dependency from auto-instrumentation (#1420)
1 parent 33fa7b9 commit 0011637

File tree

8 files changed

+129
-43
lines changed

8 files changed

+129
-43
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020
([#1449](https://github.com/open-telemetry/opentelemetry-python/pull/1449))
2121
- Added support for Jaeger propagator
2222
([#1219](https://github.com/open-telemetry/opentelemetry-python/pull/1219))
23+
- Remove dependency on SDK from `opentelemetry-instrumentation` package. The
24+
`opentelemetry-sdk` package now registers an entrypoint `opentelemetry_configurator`
25+
to allow `opentelemetry-instrument` to load the configuration for the SDK
26+
([#1420](https://github.com/open-telemetry/opentelemetry-python/pull/1420))
2327

2428
## [0.16b1](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v0.16b1) - 2020-11-26
2529
### Added

opentelemetry-instrumentation/setup.cfg

-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ zip_safe = False
4343
include_package_data = True
4444
install_requires =
4545
opentelemetry-api == 0.17.dev0
46-
opentelemetry-sdk == 0.17.dev0
4746
wrapt >= 1.0.0, < 2.0.0
4847

4948
[options.packages.find]

opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py

+27-7
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818

1919
from pkg_resources import iter_entry_points
2020

21-
from opentelemetry.instrumentation.auto_instrumentation.components import (
22-
initialize_components,
23-
)
24-
2521
logger = getLogger(__file__)
2622

2723

28-
def auto_instrument():
24+
def _load_distros():
25+
# will be implemented in a subsequent PR
26+
pass
27+
28+
29+
def _load_instrumentors():
2930
for entry_point in iter_entry_points("opentelemetry_instrumentor"):
3031
try:
3132
entry_point.load()().instrument() # type: ignore
@@ -35,10 +36,29 @@ def auto_instrument():
3536
raise exc
3637

3738

39+
def _load_configurators():
40+
configured = None
41+
for entry_point in iter_entry_points("opentelemetry_configurator"):
42+
if configured is not None:
43+
logger.warning(
44+
"Configuration of %s not loaded, %s already loaded",
45+
entry_point.name,
46+
configured,
47+
)
48+
continue
49+
try:
50+
entry_point.load()().configure() # type: ignore
51+
configured = entry_point.name
52+
except Exception as exc: # pylint: disable=broad-except
53+
logger.exception("Configuration of %s failed", entry_point.name)
54+
raise exc
55+
56+
3857
def initialize():
3958
try:
40-
initialize_components()
41-
auto_instrument()
59+
_load_distros()
60+
_load_configurators()
61+
_load_instrumentors()
4262
except Exception: # pylint: disable=broad-except
4363
logger.exception("Failed to auto initialize opentelemetry")
4464

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# type: ignore
15+
16+
"""
17+
OpenTelemetry Base Configurator
18+
"""
19+
20+
from abc import ABC, abstractmethod
21+
from logging import getLogger
22+
23+
_LOG = getLogger(__name__)
24+
25+
26+
class BaseConfigurator(ABC):
27+
"""An ABC for configurators
28+
29+
Configurators are used to configure
30+
SDKs (i.e. TracerProvider, MeterProvider, Processors...)
31+
to reduce the amount of manual configuration required.
32+
"""
33+
34+
_instance = None
35+
_is_instrumented = False
36+
37+
def __new__(cls, *args, **kwargs):
38+
39+
if cls._instance is None:
40+
cls._instance = object.__new__(cls, *args, **kwargs)
41+
42+
return cls._instance
43+
44+
@abstractmethod
45+
def _configure(self, **kwargs):
46+
"""Configure the SDK"""
47+
48+
def configure(self, **kwargs):
49+
"""Configure the SDK"""
50+
self._configure(**kwargs)
51+
52+
53+
__all__ = ["BaseConfigurator"]

opentelemetry-sdk/setup.cfg

+3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ zip_safe = False
4343
include_package_data = True
4444
install_requires =
4545
opentelemetry-api == 0.17.dev0
46+
opentelemetry-instrumentation == 0.17.dev0
4647

4748
[options.packages.find]
4849
where = src
@@ -57,6 +58,8 @@ opentelemetry_propagator =
5758
opentelemetry_exporter =
5859
console_span = opentelemetry.sdk.trace.export:ConsoleSpanExporter
5960
console_metrics = opentelemetry.sdk.metrics.export:ConsoleMetricsExporter
61+
opentelemetry_configurator =
62+
sdk_configurator = opentelemetry.sdk.configuration:Configurator
6063

6164
[options.extras_require]
6265
test =
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
from opentelemetry import trace
2121
from opentelemetry.configuration import Configuration
22+
from opentelemetry.instrumentation.configurator import BaseConfigurator
2223
from opentelemetry.sdk.metrics.export import MetricsExporter
2324
from opentelemetry.sdk.resources import Resource
2425
from opentelemetry.sdk.trace import TracerProvider
@@ -38,15 +39,15 @@
3839
_DEFAULT_IDS_GENERATOR = RANDOM_IDS_GENERATOR
3940

4041

41-
def get_ids_generator() -> str:
42+
def _get_ids_generator() -> str:
4243
return Configuration().IDS_GENERATOR or _DEFAULT_IDS_GENERATOR
4344

4445

45-
def get_service_name() -> str:
46+
def _get_service_name() -> str:
4647
return Configuration().SERVICE_NAME or ""
4748

4849

49-
def get_exporter_names() -> Sequence[str]:
50+
def _get_exporter_names() -> Sequence[str]:
5051
exporter = Configuration().EXPORTER or _DEFAULT_EXPORTER
5152
if exporter.lower().strip() == "none":
5253
return []
@@ -62,10 +63,10 @@ def get_exporter_names() -> Sequence[str]:
6263
return names
6364

6465

65-
def init_tracing(
66+
def _init_tracing(
6667
exporters: Sequence[SpanExporter], ids_generator: trace.IdsGenerator
6768
):
68-
service_name = get_service_name()
69+
service_name = _get_service_name()
6970
provider = TracerProvider(
7071
resource=Resource.create({"service.name": service_name}),
7172
ids_generator=ids_generator(),
@@ -85,12 +86,12 @@ def init_tracing(
8586
)
8687

8788

88-
def init_metrics(exporters: Sequence[MetricsExporter]):
89+
def _init_metrics(exporters: Sequence[MetricsExporter]):
8990
if exporters:
9091
logger.warning("automatic metric initialization is not supported yet.")
9192

9293

93-
def import_tracer_provider_config_components(
94+
def _import_tracer_provider_config_components(
9495
selected_components, entry_point_name
9596
) -> Sequence[Tuple[str, object]]:
9697
component_entry_points = {
@@ -112,15 +113,15 @@ def import_tracer_provider_config_components(
112113
return component_impls
113114

114115

115-
def import_exporters(
116+
def _import_exporters(
116117
exporter_names: Sequence[str],
117118
) -> Tuple[Sequence[SpanExporter], Sequence[MetricsExporter]]:
118119
trace_exporters, metric_exporters = {}, {}
119120

120121
for (
121122
exporter_name,
122123
exporter_impl,
123-
) in import_tracer_provider_config_components(
124+
) in _import_tracer_provider_config_components(
124125
exporter_names, "opentelemetry_exporter"
125126
):
126127
if issubclass(exporter_impl, SpanExporter):
@@ -136,11 +137,11 @@ def import_exporters(
136137
return trace_exporters, metric_exporters
137138

138139

139-
def import_ids_generator(ids_generator_name: str) -> trace.IdsGenerator:
140+
def _import_ids_generator(ids_generator_name: str) -> trace.IdsGenerator:
140141
# pylint: disable=unbalanced-tuple-unpacking
141142
[
142143
(ids_generator_name, ids_generator_impl)
143-
] = import_tracer_provider_config_components(
144+
] = _import_tracer_provider_config_components(
144145
[ids_generator_name.strip()], "opentelemetry_ids_generator"
145146
)
146147

@@ -150,14 +151,19 @@ def import_ids_generator(ids_generator_name: str) -> trace.IdsGenerator:
150151
raise RuntimeError("{0} is not an IdsGenerator".format(ids_generator_name))
151152

152153

153-
def initialize_components():
154-
exporter_names = get_exporter_names()
155-
trace_exporters, metric_exporters = import_exporters(exporter_names)
156-
ids_generator_name = get_ids_generator()
157-
ids_generator = import_ids_generator(ids_generator_name)
158-
init_tracing(trace_exporters, ids_generator)
154+
def _initialize_components():
155+
exporter_names = _get_exporter_names()
156+
trace_exporters, metric_exporters = _import_exporters(exporter_names)
157+
ids_generator_name = _get_ids_generator()
158+
ids_generator = _import_ids_generator(ids_generator_name)
159+
_init_tracing(trace_exporters, ids_generator)
159160

160161
# We don't support automatic initialization for metric yet but have added
161162
# some boilerplate in order to make sure current implementation does not
162163
# lock us out of supporting metrics later without major surgery.
163-
init_metrics(metric_exporters)
164+
_init_metrics(metric_exporters)
165+
166+
167+
class Configurator(BaseConfigurator):
168+
def _configure(self, **kwargs):
169+
_initialize_components()

opentelemetry-instrumentation/tests/test_auto_tracing.py renamed to opentelemetry-sdk/tests/configuration/test_configurator.py

+14-14
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
from unittest.mock import patch
1919

2020
from opentelemetry.configuration import Configuration
21-
from opentelemetry.instrumentation.auto_instrumentation import components
21+
from opentelemetry.sdk.configuration import (
22+
_get_ids_generator,
23+
_import_ids_generator,
24+
_init_tracing,
25+
)
2226
from opentelemetry.sdk.resources import Resource
2327
from opentelemetry.trace.ids_generator import RandomIdsGenerator
2428

@@ -71,11 +75,10 @@ class TestTraceInit(TestCase):
7175
def setUp(self):
7276
super()
7377
self.get_provider_patcher = patch(
74-
"opentelemetry.instrumentation.auto_instrumentation.components.TracerProvider",
75-
Provider,
78+
"opentelemetry.sdk.configuration.TracerProvider", Provider,
7679
)
7780
self.get_processor_patcher = patch(
78-
"opentelemetry.instrumentation.auto_instrumentation.components.BatchExportSpanProcessor",
81+
"opentelemetry.sdk.configuration.BatchExportSpanProcessor",
7982
Processor,
8083
)
8184
self.set_provider_patcher = patch(
@@ -96,7 +99,7 @@ def tearDown(self):
9699
def test_trace_init_default(self):
97100
environ["OTEL_SERVICE_NAME"] = "my-test-service"
98101
Configuration._reset()
99-
components.init_tracing({"zipkin": Exporter}, RandomIdsGenerator)
102+
_init_tracing({"zipkin": Exporter}, RandomIdsGenerator)
100103

101104
self.assertEqual(self.set_provider_mock.call_count, 1)
102105
provider = self.set_provider_mock.call_args[0][0]
@@ -111,7 +114,7 @@ def test_trace_init_default(self):
111114
def test_trace_init_otlp(self):
112115
environ["OTEL_SERVICE_NAME"] = "my-otlp-test-service"
113116
Configuration._reset()
114-
components.init_tracing({"otlp": OTLPExporter}, RandomIdsGenerator)
117+
_init_tracing({"otlp": OTLPExporter}, RandomIdsGenerator)
115118

116119
self.assertEqual(self.set_provider_mock.call_count, 1)
117120
provider = self.set_provider_mock.call_args[0][0]
@@ -128,21 +131,18 @@ def test_trace_init_otlp(self):
128131

129132
@patch.dict(environ, {"OTEL_IDS_GENERATOR": "custom_ids_generator"})
130133
@patch(
131-
"opentelemetry.instrumentation.auto_instrumentation.components.trace.IdsGenerator",
132-
new=IdsGenerator,
133-
)
134-
@patch(
135-
"opentelemetry.instrumentation.auto_instrumentation.components.iter_entry_points"
134+
"opentelemetry.sdk.configuration.trace.IdsGenerator", new=IdsGenerator,
136135
)
136+
@patch("opentelemetry.sdk.configuration.iter_entry_points")
137137
def test_trace_init_custom_ids_generator(self, mock_iter_entry_points):
138138
mock_iter_entry_points.configure_mock(
139139
return_value=[
140140
IterEntryPoint("custom_ids_generator", CustomIdsGenerator)
141141
]
142142
)
143143
Configuration._reset()
144-
ids_generator_name = components.get_ids_generator()
145-
ids_generator = components.import_ids_generator(ids_generator_name)
146-
components.init_tracing({}, ids_generator)
144+
ids_generator_name = _get_ids_generator()
145+
ids_generator = _import_ids_generator(ids_generator_name)
146+
_init_tracing({}, ids_generator)
147147
provider = self.set_provider_mock.call_args[0][0]
148148
self.assertIsInstance(provider.ids_generator, CustomIdsGenerator)

tox.ini

+4-3
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ commands_pre =
8484
py3{5,6,7,8,9}: python -m pip install -U pip setuptools wheel
8585
; Install common packages for all the tests. These are not needed in all the
8686
; cases but it saves a lot of boilerplate in this file.
87-
test: pip install {toxinidir}/opentelemetry-api {toxinidir}/opentelemetry-sdk {toxinidir}/tests/util
87+
test: pip install {toxinidir}/opentelemetry-api {toxinidir}/opentelemetry-instrumentation {toxinidir}/opentelemetry-sdk {toxinidir}/tests/util
8888

8989
test-core-proto: pip install {toxinidir}/opentelemetry-proto
9090
instrumentation: pip install {toxinidir}/opentelemetry-instrumentation
@@ -141,8 +141,8 @@ deps =
141141

142142
commands_pre =
143143
python -m pip install -e {toxinidir}/opentelemetry-api[test]
144-
python -m pip install -e {toxinidir}/opentelemetry-sdk[test]
145144
python -m pip install -e {toxinidir}/opentelemetry-instrumentation[test]
145+
python -m pip install -e {toxinidir}/opentelemetry-sdk[test]
146146
python -m pip install -e {toxinidir}/opentelemetry-proto[test]
147147
python -m pip install -e {toxinidir}/tests/util[test]
148148
python -m pip install -e {toxinidir}/instrumentation/opentelemetry-instrumentation-opentracing-shim[test]
@@ -176,8 +176,8 @@ deps =
176176

177177
commands_pre =
178178
pip install -e {toxinidir}/opentelemetry-api \
179-
-e {toxinidir}/opentelemetry-sdk \
180179
-e {toxinidir}/opentelemetry-instrumentation \
180+
-e {toxinidir}/opentelemetry-sdk \
181181
-e {toxinidir}/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-requests \
182182
-e {toxinidir}/opentelemetry-python-contrib/instrumentation/opentelemetry-instrumentation-wsgi
183183

@@ -194,6 +194,7 @@ changedir =
194194

195195
commands_pre =
196196
pip install -e {toxinidir}/opentelemetry-api \
197+
-e {toxinidir}/opentelemetry-instrumentation \
197198
-e {toxinidir}/opentelemetry-sdk \
198199
-e {toxinidir}/tests/util \
199200
-e {toxinidir}/exporter/opentelemetry-exporter-opencensus

0 commit comments

Comments
 (0)