Skip to content

Commit df33ede

Browse files
committed
Default configurators do more for distros
1 parent e78c9c4 commit df33ede

File tree

5 files changed

+187
-146
lines changed

5 files changed

+187
-146
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.3.0-0.22b0...HEAD)
8+
- `opentelemtry-distro` & `opentelemetry-sdk` Moved Auto Instrumentation Configurator code to SDK
9+
to let distros use its default implementation
10+
([#1934](https://github.com/open-telemetry/opentelemetry-python/pull/1934))
811
- `opentelemetry-semantic-conventions` Generate semconv constants update for OTel Spec 1.5.0
912
([#1946](https://github.com/open-telemetry/opentelemetry-python/pull/1946))
1013

opentelemetry-distro/setup.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ packages=find_namespace:
4141
zip_safe = False
4242
include_package_data = True
4343
install_requires =
44-
opentelemetry-api ~= 1.3
44+
opentelemetry-api == 1.4.0.dev0
4545
opentelemetry-instrumentation == 0.23.dev0
4646
opentelemetry-sdk == 1.4.0.dev0
4747

@@ -52,7 +52,7 @@ where = src
5252
opentelemetry_distro =
5353
distro = opentelemetry.distro:OpenTelemetryDistro
5454
opentelemetry_configurator =
55-
configurator = opentelemetry.distro:Configurator
55+
configurator = opentelemetry.distro:OpenTelemetryConfigurator
5656

5757
[options.extras_require]
5858
test =

opentelemetry-distro/src/opentelemetry/distro/__init__.py

Lines changed: 4 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -14,143 +14,16 @@
1414
#
1515
import os
1616
from logging import getLogger
17-
from os import environ
18-
from typing import Sequence, Tuple
1917

20-
from pkg_resources import iter_entry_points
21-
22-
from opentelemetry import trace
23-
from opentelemetry.environment_variables import (
24-
OTEL_PYTHON_ID_GENERATOR,
25-
OTEL_TRACES_EXPORTER,
26-
)
27-
from opentelemetry.instrumentation.configurator import BaseConfigurator
18+
from opentelemetry.environment_variables import OTEL_TRACES_EXPORTER
2819
from opentelemetry.instrumentation.distro import BaseDistro
29-
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
30-
from opentelemetry.sdk.trace import TracerProvider
31-
from opentelemetry.sdk.trace.export import BatchSpanProcessor, SpanExporter
32-
from opentelemetry.sdk.trace.id_generator import IdGenerator
20+
from opentelemetry.sdk._configuration import _OTelSDKConfigurator
3321

3422
logger = getLogger(__file__)
3523

3624

37-
EXPORTER_OTLP = "otlp"
38-
EXPORTER_OTLP_SPAN = "otlp_proto_grpc_span"
39-
40-
RANDOM_ID_GENERATOR = "random"
41-
_DEFAULT_ID_GENERATOR = RANDOM_ID_GENERATOR
42-
43-
44-
def _get_id_generator() -> str:
45-
return environ.get(OTEL_PYTHON_ID_GENERATOR, _DEFAULT_ID_GENERATOR)
46-
47-
48-
def _get_exporter_names() -> Sequence[str]:
49-
trace_exporters = environ.get(OTEL_TRACES_EXPORTER)
50-
51-
exporters = set()
52-
53-
if trace_exporters and trace_exporters.lower().strip() != "none":
54-
exporters.update(
55-
{
56-
trace_exporter.strip()
57-
for trace_exporter in trace_exporters.split(",")
58-
}
59-
)
60-
61-
if EXPORTER_OTLP in exporters:
62-
exporters.remove(EXPORTER_OTLP)
63-
exporters.add(EXPORTER_OTLP_SPAN)
64-
65-
return list(exporters)
66-
67-
68-
def _init_tracing(
69-
exporters: Sequence[SpanExporter], id_generator: IdGenerator
70-
):
71-
# if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name
72-
# from the env variable else defaults to "unknown_service"
73-
provider = TracerProvider(
74-
id_generator=id_generator(),
75-
)
76-
trace.set_tracer_provider(provider)
77-
78-
for _, exporter_class in exporters.items():
79-
exporter_args = {}
80-
provider.add_span_processor(
81-
BatchSpanProcessor(exporter_class(**exporter_args))
82-
)
83-
84-
85-
def _import_tracer_provider_config_components(
86-
selected_components, entry_point_name
87-
) -> Sequence[Tuple[str, object]]:
88-
component_entry_points = {
89-
ep.name: ep for ep in iter_entry_points(entry_point_name)
90-
}
91-
component_impls = []
92-
for selected_component in selected_components:
93-
entry_point = component_entry_points.get(selected_component, None)
94-
if not entry_point:
95-
raise RuntimeError(
96-
"Requested component '{}' not found in entry points for '{}'".format(
97-
selected_component, entry_point_name
98-
)
99-
)
100-
101-
component_impl = entry_point.load()
102-
component_impls.append((selected_component, component_impl))
103-
104-
return component_impls
105-
106-
107-
def _import_exporters(
108-
exporter_names: Sequence[str],
109-
) -> Sequence[SpanExporter]:
110-
trace_exporters = {}
111-
112-
for (
113-
exporter_name,
114-
exporter_impl,
115-
) in _import_tracer_provider_config_components(
116-
exporter_names, "opentelemetry_exporter"
117-
):
118-
if issubclass(exporter_impl, SpanExporter):
119-
trace_exporters[exporter_name] = exporter_impl
120-
else:
121-
raise RuntimeError(
122-
"{0} is not a trace exporter".format(exporter_name)
123-
)
124-
return trace_exporters
125-
126-
127-
def _import_id_generator(id_generator_name: str) -> IdGenerator:
128-
# pylint: disable=unbalanced-tuple-unpacking
129-
[
130-
(id_generator_name, id_generator_impl)
131-
] = _import_tracer_provider_config_components(
132-
[id_generator_name.strip()], "opentelemetry_id_generator"
133-
)
134-
135-
if issubclass(id_generator_impl, IdGenerator):
136-
return id_generator_impl
137-
138-
raise RuntimeError("{0} is not an IdGenerator".format(id_generator_name))
139-
140-
141-
def _initialize_components():
142-
exporter_names = _get_exporter_names()
143-
trace_exporters = _import_exporters(exporter_names)
144-
id_generator_name = _get_id_generator()
145-
id_generator = _import_id_generator(id_generator_name)
146-
_init_tracing(trace_exporters, id_generator)
147-
148-
149-
class Configurator(BaseConfigurator):
150-
151-
# pylint: disable=no-self-use
152-
def _configure(self, **kwargs):
153-
_initialize_components()
25+
class OpenTelemetryConfigurator(_OTelSDKConfigurator):
26+
pass
15427

15528

15629
class OpenTelemetryDistro(BaseDistro):
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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+
#
15+
16+
"""
17+
OpenTelemetry SDK Configurator for Easy Instrumentation with Distros
18+
"""
19+
20+
import os
21+
from logging import getLogger
22+
from os import environ
23+
from typing import Sequence, Tuple
24+
25+
from pkg_resources import iter_entry_points
26+
27+
from opentelemetry import trace
28+
from opentelemetry.environment_variables import (
29+
OTEL_PYTHON_ID_GENERATOR,
30+
OTEL_TRACES_EXPORTER,
31+
)
32+
from opentelemetry.instrumentation.configurator import BaseConfigurator
33+
from opentelemetry.sdk.trace import TracerProvider
34+
from opentelemetry.sdk.trace.export import BatchSpanProcessor, SpanExporter
35+
from opentelemetry.sdk.trace.id_generator import IdGenerator
36+
37+
logger = getLogger(__file__)
38+
39+
40+
_EXPORTER_OTLP = "otlp"
41+
_EXPORTER_OTLP_SPAN = "otlp_proto_grpc_span"
42+
43+
_RANDOM_ID_GENERATOR = "random"
44+
_DEFAULT_ID_GENERATOR = _RANDOM_ID_GENERATOR
45+
46+
47+
def _get_id_generator() -> str:
48+
return environ.get(OTEL_PYTHON_ID_GENERATOR, _DEFAULT_ID_GENERATOR)
49+
50+
51+
def _get_exporter_names() -> Sequence[str]:
52+
trace_exporters = environ.get(OTEL_TRACES_EXPORTER)
53+
54+
exporters = set()
55+
56+
if trace_exporters and trace_exporters.lower().strip() != "none":
57+
exporters.update(
58+
{
59+
trace_exporter.strip()
60+
for trace_exporter in trace_exporters.split(",")
61+
}
62+
)
63+
64+
if _EXPORTER_OTLP in exporters:
65+
exporters.remove(_EXPORTER_OTLP)
66+
exporters.add(_EXPORTER_OTLP_SPAN)
67+
68+
return list(exporters)
69+
70+
71+
def _init_tracing(
72+
exporters: Sequence[SpanExporter], id_generator: IdGenerator
73+
):
74+
# if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name
75+
# from the env variable else defaults to "unknown_service"
76+
provider = TracerProvider(
77+
id_generator=id_generator(),
78+
)
79+
trace.set_tracer_provider(provider)
80+
81+
for _, exporter_class in exporters.items():
82+
exporter_args = {}
83+
provider.add_span_processor(
84+
BatchSpanProcessor(exporter_class(**exporter_args))
85+
)
86+
87+
88+
def _import_tracer_provider_config_components(
89+
selected_components, entry_point_name
90+
) -> Sequence[Tuple[str, object]]:
91+
component_entry_points = {
92+
ep.name: ep for ep in iter_entry_points(entry_point_name)
93+
}
94+
component_impls = []
95+
for selected_component in selected_components:
96+
entry_point = component_entry_points.get(selected_component, None)
97+
if not entry_point:
98+
raise RuntimeError(
99+
"Requested component '{}' not found in entry points for '{}'".format(
100+
selected_component, entry_point_name
101+
)
102+
)
103+
104+
component_impl = entry_point.load()
105+
component_impls.append((selected_component, component_impl))
106+
107+
return component_impls
108+
109+
110+
def _import_exporters(
111+
exporter_names: Sequence[str],
112+
) -> Sequence[SpanExporter]:
113+
trace_exporters = {}
114+
115+
for (
116+
exporter_name,
117+
exporter_impl,
118+
) in _import_tracer_provider_config_components(
119+
exporter_names, "opentelemetry_exporter"
120+
):
121+
if issubclass(exporter_impl, SpanExporter):
122+
trace_exporters[exporter_name] = exporter_impl
123+
else:
124+
raise RuntimeError(
125+
"{0} is not a trace exporter".format(exporter_name)
126+
)
127+
return trace_exporters
128+
129+
130+
def _import_id_generator(id_generator_name: str) -> IdGenerator:
131+
# pylint: disable=unbalanced-tuple-unpacking
132+
[
133+
(id_generator_name, id_generator_impl)
134+
] = _import_tracer_provider_config_components(
135+
[id_generator_name.strip()], "opentelemetry_id_generator"
136+
)
137+
138+
if issubclass(id_generator_impl, IdGenerator):
139+
return id_generator_impl
140+
141+
raise RuntimeError("{0} is not an IdGenerator".format(id_generator_name))
142+
143+
144+
def _initialize_components():
145+
exporter_names = _get_exporter_names()
146+
trace_exporters = _import_exporters(exporter_names)
147+
id_generator_name = _get_id_generator()
148+
id_generator = _import_id_generator(id_generator_name)
149+
_init_tracing(trace_exporters, id_generator)
150+
151+
152+
class _OTelSDKConfigurator(BaseConfigurator):
153+
"""A basic Configurator by OTel Python for initalizing OTel SDK components
154+
155+
Initializes several crucial OTel SDK components (i.e. TracerProvider,
156+
MeterProvider, Processors...) according to a default implementation. Other
157+
Configurators can subclass and slightly alter this initialization.
158+
159+
NOTE: This class should not be instantiated nor should it become an entry
160+
point on the `opentelemetry-sdk` package. Instead, distros should subclass
161+
this Configurator and enchance it as needed.
162+
"""
163+
164+
def _configure(self, **kwargs):
165+
_initialize_components()

0 commit comments

Comments
 (0)