Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ optional-dependencies = { test-tools = [
"pyfakefs (>=5,<6)",
"pytest-django (>=4,<5)",
], common-core = [
"flagsmith-common[otel]",
"django (>4,<6)",
"django-health-check",
"djangorestframework-recursive",
Expand All @@ -16,19 +17,20 @@ optional-dependencies = { test-tools = [
"drf-writable-nested",
"environs (<16)",
"gunicorn (>=19.1)",
"inflection",
"opentelemetry-api (>=1.25,<2)",
"opentelemetry-sdk (>=1.25,<2)",
"opentelemetry-exporter-otlp-proto-http (>=1.25,<2)",
"opentelemetry-instrumentation-django (>=0.46b0,<1)",
"opentelemetry-instrumentation-psycopg2 (>=0.46b0,<1)",
"opentelemetry-instrumentation-redis (>=0.46b0,<1)",
"redis (>=5,<6)",
"prometheus-client (>=0.0.16)",
"psycopg2-binary (>=2.9,<3)",
"requests",
"sentry-sdk (>=2.0.0,<3.0.0)",
"simplejson (>=3,<4)",
], otel = [
"inflection",
"opentelemetry-api (>=1.25,<2)",
"opentelemetry-sdk (>=1.25,<2)",
"opentelemetry-exporter-otlp-proto-http (>=1.25,<2)",
"sentry-sdk (>=2.0.0,<3.0.0)",
"structlog (>=24.4,<26)",
"typing_extensions",
], task-processor = [
Expand Down
7 changes: 4 additions & 3 deletions src/common/core/otel.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
from opentelemetry.exporter.otlp.proto.http.trace_exporter import (
OTLPSpanExporter,
)
from opentelemetry.instrumentation.django import DjangoInstrumentor
from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor
from opentelemetry.instrumentation.redis import RedisInstrumentor
from opentelemetry.propagate import set_global_textmap
from opentelemetry.propagators.composite import CompositePropagator
from opentelemetry.propagators.textmap import TextMapPropagator
Expand Down Expand Up @@ -195,6 +192,10 @@ def setup_tracing(
(e.g. ``"health/liveness,health/readiness"``). If not provided,
falls back to the ``OTEL_PYTHON_DJANGO_EXCLUDED_URLS`` env var.
"""
from opentelemetry.instrumentation.django import DjangoInstrumentor
from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor
from opentelemetry.instrumentation.redis import RedisInstrumentor

trace.set_tracer_provider(tracer_provider)

propagator: TextMapPropagator = CompositePropagator(
Expand Down
26 changes: 20 additions & 6 deletions tests/unit/common/core/test_otel.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,16 +210,20 @@ def test_setup_tracing__called__instruments_and_uninstruments_all_libraries(
mocker: pytest_mock.MockerFixture,
) -> None:
# Given
mocker.patch("common.core.otel.DjangoInstrumentor.instrument")
mocker.patch("common.core.otel.DjangoInstrumentor.uninstrument")
mocker.patch("opentelemetry.instrumentation.django.DjangoInstrumentor.instrument")
mocker.patch("opentelemetry.instrumentation.django.DjangoInstrumentor.uninstrument")
psycopg2_instrument = mocker.patch(
"common.core.otel.Psycopg2Instrumentor.instrument"
"opentelemetry.instrumentation.psycopg2.Psycopg2Instrumentor.instrument"
)
psycopg2_uninstrument = mocker.patch(
"common.core.otel.Psycopg2Instrumentor.uninstrument"
"opentelemetry.instrumentation.psycopg2.Psycopg2Instrumentor.uninstrument"
)
redis_instrument = mocker.patch(
"opentelemetry.instrumentation.redis.RedisInstrumentor.instrument"
)
redis_uninstrument = mocker.patch(
"opentelemetry.instrumentation.redis.RedisInstrumentor.uninstrument"
)
redis_instrument = mocker.patch("common.core.otel.RedisInstrumentor.instrument")
redis_uninstrument = mocker.patch("common.core.otel.RedisInstrumentor.uninstrument")
provider = TracerProvider()

# When
Expand All @@ -232,3 +236,13 @@ def test_setup_tracing__called__instruments_and_uninstruments_all_libraries(
# Then — uninstrumented on exit
psycopg2_uninstrument.assert_called_once()
redis_uninstrument.assert_called_once()


def test_otel_module__imported__no_module_level_instrumentor_references() -> None:
# Given / When
import common.core.otel as otel_module

# Then
assert not hasattr(otel_module, "DjangoInstrumentor")
assert not hasattr(otel_module, "Psycopg2Instrumentor")
assert not hasattr(otel_module, "RedisInstrumentor")
26 changes: 18 additions & 8 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.