Skip to content

Commit f0245c6

Browse files
authored
distro: remove custom code in ElasticOpenTelemetryConfigurator (#250)
The custom code was introduced in 40ae8be for changing the semantics of the logs sdk. Since the semantic has been changed upstream too we can drop our custom code. While at it add an integration test to check that events are emitted.
1 parent 85b7633 commit f0245c6

File tree

3 files changed

+52
-73
lines changed

3 files changed

+52
-73
lines changed

src/elasticotel/distro/__init__.py

Lines changed: 2 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717
import logging
1818
import os
1919

20-
from opentelemetry._logs import set_logger_provider
21-
from opentelemetry._events import set_event_logger_provider
2220
from opentelemetry.environment_variables import (
2321
OTEL_LOGS_EXPORTER,
2422
OTEL_METRICS_EXPORTER,
@@ -30,29 +28,13 @@
3028
_DEFAULT_CONFIG as SYSTEM_METRICS_DEFAULT_CONFIG,
3129
SystemMetricsInstrumentor,
3230
)
33-
from opentelemetry.semconv.resource import ResourceAttributes
34-
from opentelemetry.sdk._configuration import (
35-
_OTelSDKConfigurator,
36-
_import_exporters,
37-
_get_exporter_names,
38-
_get_sampler,
39-
_import_sampler,
40-
_get_id_generator,
41-
_import_id_generator,
42-
_init_tracing,
43-
_init_metrics,
44-
)
45-
from opentelemetry.sdk._events import EventLoggerProvider
46-
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
47-
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
31+
from opentelemetry.sdk._configuration import _OTelSDKConfigurator
4832
from opentelemetry.sdk.environment_variables import (
4933
OTEL_METRICS_EXEMPLAR_FILTER,
5034
OTEL_EXPERIMENTAL_RESOURCE_DETECTORS,
5135
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
5236
OTEL_EXPORTER_OTLP_PROTOCOL,
53-
_OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED,
5437
)
55-
from opentelemetry.sdk.resources import Resource
5638
from opentelemetry.util._importlib_metadata import EntryPoint
5739

5840
from elasticotel.distro.environment_variables import ELASTIC_OTEL_SYSTEM_METRICS_ENABLED
@@ -63,59 +45,7 @@
6345

6446

6547
class ElasticOpenTelemetryConfigurator(_OTelSDKConfigurator):
66-
def _configure(self, **kwargs):
67-
"""This is overriden to enable the log machinery (and thus log events) without
68-
attaching the OTel handler to the Python logging module.
69-
70-
This code is a simplified version of _initialize_components plus the changes
71-
required to have log events enabled out of the box"""
72-
span_exporters, metric_exporters, log_exporters = _import_exporters(
73-
_get_exporter_names("traces"),
74-
_get_exporter_names("metrics"),
75-
_get_exporter_names("logs"),
76-
)
77-
sampler_name = _get_sampler()
78-
sampler = _import_sampler(sampler_name)
79-
id_generator_name = _get_id_generator()
80-
id_generator = _import_id_generator(id_generator_name)
81-
82-
resource_attributes = {}
83-
# populate version if using auto-instrumentation
84-
auto_instrumentation_version = kwargs.get("auto_instrumentation_version")
85-
if auto_instrumentation_version:
86-
resource_attributes[ResourceAttributes.TELEMETRY_AUTO_VERSION] = auto_instrumentation_version
87-
# if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name
88-
# from the env variable else defaults to "unknown_service"
89-
resource = Resource.create(resource_attributes)
90-
91-
_init_tracing(
92-
exporters=span_exporters,
93-
id_generator=id_generator,
94-
sampler=sampler,
95-
resource=resource,
96-
)
97-
_init_metrics(metric_exporters, resource)
98-
99-
# from here we change the semantics of _OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED from
100-
# controlling all the logging support to just the logging handler. So we can use log events without
101-
# exporting all the logs to OTLP
102-
logger_provider = LoggerProvider(resource=resource)
103-
set_logger_provider(logger_provider)
104-
105-
for _, exporter_class in log_exporters.items():
106-
exporter_args = {}
107-
logger_provider.add_log_record_processor(BatchLogRecordProcessor(exporter_class(**exporter_args)))
108-
109-
setup_logging_handler = (
110-
os.getenv(_OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED, "false").strip().lower() == "true"
111-
)
112-
if setup_logging_handler:
113-
handler = LoggingHandler(level=logging.NOTSET, logger_provider=logger_provider)
114-
logging.getLogger().addHandler(handler)
115-
116-
# now setup the event logger
117-
event_logger_provider = EventLoggerProvider(logger_provider=logger_provider)
118-
set_event_logger_provider(event_logger_provider)
48+
pass
11949

12050

12151
class ElasticOpenTelemetryDistro(BaseDistro):

tests/integration/test_integration.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,19 @@ def test_metrics_with_system_metrics(self):
117117
"process.open_file_descriptor.count",
118118
],
119119
)
120+
121+
def test_log_events_are_sent(self):
122+
def send_event():
123+
from opentelemetry._events import Event
124+
from opentelemetry._events import get_event_logger
125+
126+
event = Event(name="test.event", attributes={}, body={"key": "value", "dict": {"nestedkey": "nestedvalue"}})
127+
event_logger = get_event_logger(__name__)
128+
event_logger.emit(event)
129+
130+
stdout, stderr, returncode = self.run_script(send_event, wrapper_script="opentelemetry-instrument")
131+
132+
telemetry = self.get_telemetry()
133+
(log,) = telemetry["logs"]
134+
self.assertEqual(log["attributes"]["event.name"], "test.event")
135+
self.assertEqual(log["body"], {"key": "value", "dict": {"nestedkey": "nestedvalue"}})

tests/integration/utils.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,27 @@ def normalize_attributes(attributes) -> dict:
134134
for a in attributes
135135
}
136136

137+
def normalize_kvlist(body) -> dict:
138+
"""
139+
normalizes oteltest values in the form
140+
{'kvlistValue': {'values': [{'key': 'key', 'value': {'stringValue': 'value'}},
141+
{'key': 'dict',
142+
'value': {'kvlistValue': {'values': [{'key': 'nestedkey',
143+
'value': {'stringValue': 'nestedvalue'}}]}}}]}}
144+
to plain dicts
145+
"""
146+
dict_values = {}
147+
values = body["kvlistValue"]["values"]
148+
for value in values:
149+
key = value["key"]
150+
if "kvlistValue" in value["value"]:
151+
dict_values[key] = normalize_kvlist(value["value"])
152+
elif "stringValue" in value["value"]:
153+
dict_values[key] = value["value"]["stringValue"]
154+
elif "intValue" in value["value"]:
155+
dict_values[key] = value["value"]["intValue"]
156+
return dict_values
157+
137158
metrics = []
138159
for request in telemetry["metric_requests"]:
139160
elems = []
@@ -168,8 +189,20 @@ def normalize_attributes(attributes) -> dict:
168189
span["traceId"] = decode_id(span["traceId"])
169190
traces.append(span)
170191

192+
logs = []
193+
for request in telemetry["log_requests"]:
194+
for resource_log in request["pbreq"]["resourceLogs"]:
195+
resource_attributes = normalize_attributes(resource_log["resource"]["attributes"])
196+
for proto_scope_logs in resource_log["scopeLogs"]:
197+
for proto_log in proto_scope_logs["logRecords"]:
198+
log = proto_log.copy()
199+
log["attributes"] = normalize_attributes(log["attributes"])
200+
log["body"] = normalize_kvlist(log["body"])
201+
log["resource"] = resource_attributes
202+
logs.append(log)
203+
171204
return {
172-
"logs": telemetry["log_requests"], # TODO
205+
"logs": logs,
173206
"metrics": metrics,
174207
"traces": traces,
175208
}

0 commit comments

Comments
 (0)