Skip to content

Commit 3ae3ce8

Browse files
committed
opentelemetry: cleanup linter errors
1 parent d3df9b7 commit 3ae3ce8

1 file changed

Lines changed: 114 additions & 25 deletions

File tree

tracing.py

Lines changed: 114 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
"""
3535
from __future__ import annotations
3636

37+
# opentelemetry packages are available at runtime but not in the linter env
38+
# pylint: disable=import-error
39+
3740
import builtins
3841
import os
3942
from typing import Optional, Set
@@ -62,7 +65,8 @@ def force_flush(timeout_millis: int = 5000) -> bool:
6265
# pytest plugin entry point
6366
# ---------------------------------------------------------------------------
6467

65-
def pytest_configure(config) -> None:
68+
69+
def pytest_configure(config) -> None: # pylint: disable=unused-argument
6670
"""Called once per worker process before test collection starts."""
6771
if not _TRACEPARENT:
6872
return
@@ -73,6 +77,7 @@ def pytest_configure(config) -> None:
7377
# Custom headers propagator
7478
# ---------------------------------------------------------------------------
7579

80+
7681
class _TraceIdSpanIdPropagator:
7782
"""
7883
Minimal propagator that injects 'trace-id' and 'span-id' headers
@@ -84,9 +89,37 @@ class _TraceIdSpanIdPropagator:
8489
_FIELDS: Set[str] = {"trace-id", "span-id"}
8590

8691
def inject(self, carrier, context: Optional[object] = None, setter=None) -> None:
92+
"""
93+
Minimal propagator for injecting custom 'trace-id' and 'span-id' headers.
94+
95+
This class implements a propagator conforming to the OpenTelemetry propagators API,
96+
but tailored for systems that expect lowercase, hyphenated 'trace-id' and 'span-id'
97+
headers instead of standard OTel formats.
98+
99+
The propagator only performs injection (outbound context propagation) and does not
100+
extract or parse incoming headers (extract() is a no-op). This is useful for test
101+
environments or systems with custom trace context expectations.
102+
103+
Attributes:
104+
_FIELDS (Set[str]): The set of field names injected by this propagator.
105+
106+
Methods:
107+
inject(carrier, context=None, setter=None):
108+
Injects 'trace-id' and 'span-id' headers into the provided carrier
109+
using the current span context.
110+
111+
extract(carrier, context=None, getter=None):
112+
No-op. Returns the context unmodified.
113+
114+
fields:
115+
Returns the set of header names injected by this propagator.
116+
"""
117+
# pylint: disable=import-outside-toplevel
87118
from opentelemetry import trace as otel_trace
88119
from opentelemetry.propagators.textmap import default_setter
89120

121+
# pylint: enable=import-outside-toplevel
122+
90123
if setter is None:
91124
setter = default_setter
92125

@@ -97,27 +130,44 @@ def inject(self, carrier, context: Optional[object] = None, setter=None) -> None
97130
setter.set(carrier, "trace-id", format(span_ctx.trace_id, "032x"))
98131
setter.set(carrier, "span-id", format(span_ctx.span_id, "016x"))
99132

100-
def extract(self, carrier, context=None, getter=None):
133+
def extract(self, _carrier, context=None, _getter=None):
134+
"""
135+
Returns the docstring for the _TraceIdSpanIdPropagator class.
136+
137+
:return: The class docstring.
138+
:rtype: str
139+
"""
101140
return context
102141

103142
@property
104143
def fields(self) -> Set[str]:
144+
"""
145+
Returns the docstring for the _TraceIdSpanIdPropagator class.
146+
147+
:return: The class docstring as a string.
148+
:rtype: str
149+
"""
105150
return self._FIELDS
106151

107152

108153
# ---------------------------------------------------------------------------
109154
# Internal helpers
110155
# ---------------------------------------------------------------------------
111156

157+
112158
def _attach_root_context() -> None:
113159
"""
114160
Reconstruct the root SpanContext from the bash-generated TRACEPARENT env
115161
var and attach it to the running context so every span created during the
116162
test session inherits the same trace ID.
117163
"""
118-
from opentelemetry import trace as otel_trace, context as otel_context
164+
# pylint: disable=import-outside-toplevel
165+
from opentelemetry import trace as otel_trace
166+
from opentelemetry import context as otel_context
119167
from opentelemetry.trace import NonRecordingSpan, SpanContext, TraceFlags
120168

169+
# pylint: enable=import-outside-toplevel
170+
121171
parts = _TRACEPARENT.split("-")
122172
if len(parts) != 4:
123173
return
@@ -134,51 +184,86 @@ def _attach_root_context() -> None:
134184
pass
135185

136186

137-
def _bootstrap_otel() -> None:
138-
global _provider
139-
from opentelemetry import trace as otel_trace, propagate
187+
def _create_provider():
188+
"""Build a TracerProvider with a service-name resource and return it."""
189+
# pylint: disable=import-outside-toplevel
190+
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
140191
from opentelemetry.sdk.trace import TracerProvider
141-
from opentelemetry.sdk.resources import Resource, SERVICE_NAME
142-
from opentelemetry.propagators.composite import CompositePropagator
143-
from opentelemetry.propagators.b3 import B3MultiFormat
144-
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
192+
193+
# pylint: enable=import-outside-toplevel
145194

146195
service_name = os.environ.get("OTEL_SERVICE_NAME", "atp3-python-runner")
147196
resource = Resource({SERVICE_NAME: service_name})
148-
provider = TracerProvider(resource=resource)
149-
_provider = provider
197+
return TracerProvider(resource=resource)
198+
150199

200+
def _add_otlp_exporter(provider) -> None:
201+
"""Attach a BatchSpanProcessor with OTLPSpanExporter if an endpoint is configured."""
151202
otlp_endpoint = os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT")
152-
if otlp_endpoint:
153-
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
154-
from opentelemetry.sdk.trace.export import BatchSpanProcessor
155-
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
203+
if not otlp_endpoint:
204+
return
205+
# pylint: disable=import-outside-toplevel
206+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
207+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
156208

157-
otel_trace.set_tracer_provider(provider)
209+
# pylint: enable=import-outside-toplevel
210+
211+
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
212+
213+
214+
def _setup_propagators(provider) -> None:
215+
"""Register the tracer provider and composite propagator globally."""
216+
# pylint: disable=import-outside-toplevel
217+
from opentelemetry import propagate
218+
from opentelemetry import trace as otel_trace
219+
from opentelemetry.propagators.b3 import B3MultiFormat
220+
from opentelemetry.propagators.composite import CompositePropagator
221+
from opentelemetry.trace.propagation.tracecontext import (
222+
TraceContextTextMapPropagator,
223+
)
224+
225+
# pylint: enable=import-outside-toplevel
158226

159-
composite = CompositePropagator([
160-
TraceContextTextMapPropagator(),
161-
B3MultiFormat(),
162-
_TraceIdSpanIdPropagator(),
163-
])
227+
otel_trace.set_tracer_provider(provider)
228+
composite = CompositePropagator(
229+
[
230+
TraceContextTextMapPropagator(),
231+
B3MultiFormat(),
232+
_TraceIdSpanIdPropagator(),
233+
]
234+
)
164235
propagate.set_global_textmap(composite)
165236

166-
_attach_root_context()
167237

238+
def _instrument_http() -> None:
239+
"""Auto-instrument outgoing HTTP calls via requests and urllib3 if available."""
168240
try:
241+
# pylint: disable=import-outside-toplevel
169242
from opentelemetry.instrumentation.requests import RequestsInstrumentor
243+
244+
# pylint: enable=import-outside-toplevel
170245
RequestsInstrumentor().instrument()
171246
except ImportError as e:
172247
print("RequestsInstrumentation import error, skipping tracing.", e.name, e.path)
173-
pass
174248

175249
try:
250+
# pylint: disable=import-outside-toplevel
176251
from opentelemetry.instrumentation.urllib3 import URLLib3Instrumentor
252+
253+
# pylint: enable=import-outside-toplevel
177254
URLLib3Instrumentor().instrument()
178255
except ImportError as e:
179256
print("URLLib3Instrumentation import error, skipping tracing.", e.name, e.path)
180-
pass
181257

258+
259+
def _bootstrap_otel() -> None:
260+
"""Orchestrate OTel initialisation: provider, exporter, propagators, instrumentation."""
261+
global _provider # pylint: disable=global-statement
262+
_provider = _create_provider()
263+
_add_otlp_exporter(_provider)
264+
_setup_propagators(_provider)
265+
_attach_root_context()
266+
_instrument_http()
182267
_patch_print()
183268

184269

@@ -190,7 +275,11 @@ def _patch_print() -> None:
190275
_orig = builtins.print
191276

192277
def _traced(*args, **kwargs):
278+
# pylint: disable=import-outside-toplevel
193279
from opentelemetry import trace as otel_trace
280+
281+
# pylint: enable=import-outside-toplevel
282+
194283
span_ctx = otel_trace.get_current_span().get_span_context()
195284
if span_ctx and span_ctx.is_valid:
196285
_orig(f"[traceId={format(span_ctx.trace_id, '032x')}]", *args, **kwargs)

0 commit comments

Comments
 (0)