Skip to content

Commit 936cf7e

Browse files
committed
PYTHON-5945 Cache the OpenTelemetry tracer instead of fetching it per command
trace.get_tracer() was being called on every command span. Even on an SDK cache hit this allocates two objects, takes a process-wide lock, and mutates the global warnings filter list, ~300x slower than a cached attribute read. Caching at import time is safe because get_tracer() returns a self-updating ProxyTracer when no real TracerProvider is registered yet.
1 parent bf54c31 commit 936cf7e

1 file changed

Lines changed: 9 additions & 7 deletions

File tree

pymongo/_otel.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,15 @@
3535
from opentelemetry.trace import SpanKind, Status, StatusCode
3636

3737
_HAS_OPENTELEMETRY = True
38+
# Safe to cache at import time: opentelemetry.trace.get_tracer() returns a
39+
# ProxyTracer when no real TracerProvider is registered yet, and that proxy
40+
# transparently starts delegating to the real tracer once the application
41+
# calls trace.set_tracer_provider() later, so this doesn't bind us to a
42+
# permanently-inert no-op tracer.
43+
_TRACER: Optional[Tracer] = trace.get_tracer("PyMongo", __version__)
3844
except ImportError:
3945
_HAS_OPENTELEMETRY = False
46+
_TRACER = None
4047

4148
if TYPE_CHECKING:
4249
from opentelemetry.trace import Span, Tracer
@@ -99,11 +106,6 @@ def _is_tracing_enabled(tracing_options: Optional[TracingOptions]) -> bool:
99106
return _env_truthy(_OTEL_ENABLED_ENV)
100107

101108

102-
def _get_tracer() -> Tracer:
103-
"""Return a Tracer scoped to this driver's name and version."""
104-
return trace.get_tracer("PyMongo", __version__)
105-
106-
107109
def _get_query_text_max_length(tracing_options: Optional[TracingOptions]) -> int:
108110
"""Return the configured db.query.text truncation length, or 0 to omit the attribute.
109111
@@ -236,8 +238,8 @@ def start_command_span(
236238
if max_query_text_length > 0:
237239
attributes["db.query.text"] = _build_query_text(cmd, max_query_text_length)
238240

239-
tracer = _get_tracer()
240-
return tracer.start_span(command_name, kind=SpanKind.CLIENT, attributes=attributes)
241+
assert _TRACER is not None # _is_tracing_enabled already checked _HAS_OPENTELEMETRY
242+
return _TRACER.start_span(command_name, kind=SpanKind.CLIENT, attributes=attributes)
241243

242244

243245
def end_command_span_success(span: Optional[Span], reply: _DocumentOut) -> None:

0 commit comments

Comments
 (0)