otel: Explicitly initialize telemetry provider and tracer

Doing this setup on import is simple, but it has issues if the pungi
code is directly imported into a different process.

Specifically, ODCS may have created its own provider and set things up
as needed, and then imports pungi, which tries to set a new provider.
This is prohibited by the SDK docs, and emits a warning. In reality it
is causing spans to be attributed to a wrong service.

As a side effect, RequestsIntrumentor doesn't start, and so the parent
process will need to do that on its own instead of relying on the side
effect.

Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
(cherry picked from commit e0a3343a4be96f9e284b752e5c5f31e02883a0a8)
This commit is contained in:
Lubomír Sedlář 2025-06-18 12:00:33 +02:00 committed by Stepan Oksanichenko
parent 65c507e2c0
commit 2dd2b5c82a
2 changed files with 16 additions and 2 deletions

View File

@ -12,6 +12,9 @@ depending on whether environment variables configuring OTel are configured.
class DummyTracing:
"""A dummy tracing module that doesn't actually do anything."""
def setup(self):
pass
@contextmanager
def span(self, *args, **kwargs):
yield
@ -38,7 +41,11 @@ class DummyTracing:
class OtelTracing:
"""This class implements the actual integration with opentelemetry."""
def __init__(self):
def setup(self):
"""Configure opentelemetry tracing based on environment variables. This
setup is optional as it may not be desirable when pungi is used as a
library.
"""
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
@ -61,7 +68,6 @@ class OtelTracing:
self.processor = BatchSpanProcessor(OTLPSpanExporter())
provider.add_span_processor(self.processor)
trace.set_tracer_provider(provider)
self.tracer = trace.get_tracer(__name__)
traceparent = os.environ.get("TRACEPARENT")
if traceparent:
@ -74,6 +80,12 @@ class OtelTracing:
except ImportError:
pass
@property
def tracer(self):
from opentelemetry import trace
return trace.get_tracer(__name__)
@contextmanager
def span(self, name, **attributes):
"""Create a new span as a child of the current one. Attributes can be

View File

@ -653,6 +653,8 @@ def cli_main():
signal.signal(signal.SIGINT, sigterm_handler)
signal.signal(signal.SIGTERM, sigterm_handler)
tracing.setup()
with tracing.span("run-compose"):
try:
main()