From 2dd2b5c82a421cdd7486573bb91e4dd33faa841c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubom=C3=ADr=20Sedl=C3=A1=C5=99?= Date: Wed, 18 Jun 2025 12:00:33 +0200 Subject: [PATCH] otel: Explicitly initialize telemetry provider and tracer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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ář (cherry picked from commit e0a3343a4be96f9e284b752e5c5f31e02883a0a8) --- pungi/otel.py | 16 ++++++++++++++-- pungi/scripts/pungi_koji.py | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/pungi/otel.py b/pungi/otel.py index 1f2d7d08..66c63877 100644 --- a/pungi/otel.py +++ b/pungi/otel.py @@ -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 diff --git a/pungi/scripts/pungi_koji.py b/pungi/scripts/pungi_koji.py index f2fb772c..a0306734 100644 --- a/pungi/scripts/pungi_koji.py +++ b/pungi/scripts/pungi_koji.py @@ -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()