Skip to content

Commit

Permalink
Support PEP 561 to opentelemetry-instrumentation-pymongo (#3136)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kludex authored Jan 10, 2025
1 parent a606fab commit 3ebdb63
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#3100](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3100))
- Add support to database stability opt-in in `_semconv` utilities and add tests
([#3111](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3111))
- `opentelemetry-opentelemetry-pymongo` Add `py.typed` file to enable PEP 561
([#3136](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3136))
- `opentelemetry-opentelemetry-requests` Add `py.typed` file to enable PEP 561
([#3135](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3135))
- `opentelemetry-instrumentation-system-metrics` Add `py.typed` file to enable PEP 561
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ def failed_hook(span, event):
"""

from __future__ import annotations

from logging import getLogger
from typing import Callable, Collection
from typing import Any, Callable, Collection, TypeVar

from pymongo import monitoring

Expand All @@ -88,7 +90,7 @@ def failed_hook(span, event):
from opentelemetry.instrumentation.pymongo.version import __version__
from opentelemetry.instrumentation.utils import is_instrumentation_enabled
from opentelemetry.semconv.trace import DbSystemValues, SpanAttributes
from opentelemetry.trace import SpanKind, get_tracer
from opentelemetry.trace import SpanKind, Tracer, get_tracer
from opentelemetry.trace.span import Span
from opentelemetry.trace.status import Status, StatusCode

Expand All @@ -98,14 +100,21 @@ def failed_hook(span, event):
ResponseHookT = Callable[[Span, monitoring.CommandSucceededEvent], None]
FailedHookT = Callable[[Span, monitoring.CommandFailedEvent], None]

CommandEvent = TypeVar(
"CommandEvent",
monitoring.CommandStartedEvent,
monitoring.CommandSucceededEvent,
monitoring.CommandFailedEvent,
)


def dummy_callback(span, event): ...
def dummy_callback(span: Span, event: CommandEvent): ...


class CommandTracer(monitoring.CommandListener):
def __init__(
self,
tracer,
tracer: Tracer,
request_hook: RequestHookT = dummy_callback,
response_hook: ResponseHookT = dummy_callback,
failed_hook: FailedHookT = dummy_callback,
Expand Down Expand Up @@ -195,10 +204,12 @@ def failed(self, event: monitoring.CommandFailedEvent):
_LOG.exception(hook_exception)
span.end()

def _pop_span(self, event):
def _pop_span(self, event: CommandEvent) -> Span | None:
return self._span_dict.pop(_get_span_dict_key(event), None)

def _get_statement_by_command_name(self, command_name, event):
def _get_statement_by_command_name(
self, command_name: str, event: CommandEvent
) -> str:
statement = command_name
command_attribute = COMMAND_TO_ATTRIBUTE_MAPPING.get(command_name)
command = event.command.get(command_attribute)
Expand All @@ -207,14 +218,16 @@ def _get_statement_by_command_name(self, command_name, event):
return statement


def _get_span_dict_key(event):
def _get_span_dict_key(
event: CommandEvent,
) -> int | tuple[int, tuple[str, int | None]]:
if event.connection_id is not None:
return event.request_id, event.connection_id
return event.request_id


class PymongoInstrumentor(BaseInstrumentor):
_commandtracer_instance = None # type CommandTracer
_commandtracer_instance: CommandTracer | None = None
# The instrumentation for PyMongo is based on the event listener interface
# https://api.mongodb.com/python/current/api/pymongo/monitoring.html.
# This interface only allows to register listeners and does not provide
Expand All @@ -225,7 +238,7 @@ class PymongoInstrumentor(BaseInstrumentor):
def instrumentation_dependencies(self) -> Collection[str]:
return _instruments

def _instrument(self, **kwargs):
def _instrument(self, **kwargs: Any):
"""Integrate with pymongo to trace it using event listener.
https://api.mongodb.com/python/current/api/pymongo/monitoring.html
Expand Down Expand Up @@ -259,6 +272,6 @@ def _instrument(self, **kwargs):
# If already created, just enable it
self._commandtracer_instance.is_enabled = True

def _uninstrument(self, **kwargs):
def _uninstrument(self, **kwargs: Any):
if self._commandtracer_instance is not None:
self._commandtracer_instance.is_enabled = False

0 comments on commit 3ebdb63

Please sign in to comment.