Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make open-telemetry a soft dependency [RHELDST-27627] #196

Merged
merged 2 commits into from
Nov 13, 2024
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
2 changes: 0 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
pluggy
setuptools
opentelemetry-api
opentelemetry-sdk
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ def get_requirements():
"Topic :: Software Development :: Libraries :: Python Modules",
],
install_requires=get_requirements(),
extras_require={
"tracing": ["opentelemetry-api", "opentelemetry-sdk"],
},
python_requires=">=3.6",
project_urls={
"Documentation": "https://release-engineering.github.io/pubtools/",
Expand Down
38 changes: 28 additions & 10 deletions src/pubtools/_impl/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,23 @@ def func():
import os
import threading

from opentelemetry import baggage, context, trace
from opentelemetry.baggage.propagation import W3CBaggagePropagator
from opentelemetry.propagate import set_global_textmap
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from opentelemetry.trace import Status, StatusCode
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
try:
from opentelemetry import baggage, context, trace
from opentelemetry.baggage.propagation import W3CBaggagePropagator
from opentelemetry.propagate import set_global_textmap
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from opentelemetry.trace import Status, StatusCode
from opentelemetry.trace.propagation.tracecontext import (
TraceContextTextMapPropagator,
)

OPENTELEMETRY_AVAILABLE = True
except ImportError: # pragma: no cover
# Clients aren't expected to have open-telemetry. This flag will be used in
# TracingWrapper to provide pass through functions.
OPENTELEMETRY_AVAILABLE = False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could have a pragma: no cover added to pass the coverage check, given that it's probably not worth maintaining two separate test environments with otel present vs missing.


from pubtools.pluggy import pm

Expand Down Expand Up @@ -60,7 +69,16 @@ def _reset(self):
# trace.set_tracer_provider global singleton set below can *never* be set up
# more than once in a single process.

self._enabled_trace = os.getenv("OTEL_TRACING", "").lower() == "true"
self._enabled_trace = (
os.getenv("OTEL_TRACING", "").lower() == "true"
) and OPENTELEMETRY_AVAILABLE
if (
os.getenv("OTEL_TRACING", "").lower() == "true"
) and not OPENTELEMETRY_AVAILABLE:
log.debug(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally there should be a test which reaches this line.

You could probably monkeypatch.setattr(tracing, "OPENTELEMETRY_AVAILABLE", False) from within a test to force it to behave as though otel libraries are not available even when they are.

"Tracing is enabled but the open telemetry package is "
"unavailable. Tracing functionality will be disabled."
)
if self._enabled_trace and not self._processor:
log.info("Creating TracingWrapper instance")
exporter = pm.hook.otel_exporter() or ConsoleSpanExporter()
Expand All @@ -87,7 +105,6 @@ def instrument_func(self, span_name=None, carrier=None, args_to_attr=False):
Returns:
The decorated function
"""
tracer = trace.get_tracer(__name__)

def _instrument_func(func):
@functools.wraps(func)
Expand All @@ -104,6 +121,7 @@ def wrap(*args, **kwargs):
if not self._enabled_trace:
return func(*args, **kwargs)

tracer = trace.get_tracer(__name__)
trace_ctx = None
token = None
if not context.get_current():
Expand Down
2 changes: 2 additions & 0 deletions test-requirements.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pytest
pytest-cov
opentelemetry-api
opentelemetry-sdk
14 changes: 8 additions & 6 deletions test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@ opentelemetry-api==1.20.0 \
--hash=sha256:06abe351db7572f8afdd0fb889ce53f3c992dbf6f6262507b385cc1963e06983 \
--hash=sha256:982b76036fec0fdaf490ae3dfd9f28c81442a33414f737abc687a32758cdcba5
# via
# -r test-requirements.in
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
# opentelemetry-sdk
Expand Down Expand Up @@ -735,6 +736,7 @@ opentelemetry-sdk==1.20.0 \
--hash=sha256:702e432a457fa717fd2ddfd30640180e69938f85bb7fec3e479f85f61c1843f8 \
--hash=sha256:f2230c276ff4c63ea09b3cb2e2ac6b1265f90af64e8d16bbf275c81a9ce8e804
# via
# -r test-requirements.in
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
# pubtools
Expand Down Expand Up @@ -898,9 +900,9 @@ pyrsistent==0.20.0 \
--hash=sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98 \
--hash=sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022
# via pubtools-quay
pyspnego[kerberos]==0.11.1 \
--hash=sha256:129a4294f2c4d681d5875240ef87accc6f1d921e8983737fb0b59642b397951e \
--hash=sha256:e92ed8b0a62765b9d6abbb86a48cf871228ddb97678598dc01c9c39a626823f6
pyspnego[kerberos]==0.11.2 \
--hash=sha256:74abc1fb51e59360eb5c5c9086e5962174f1072c7a50cf6da0bda9a4bcfdfbd4 \
--hash=sha256:994388d308fb06e4498365ce78d222bf4f3570b6df4ec95738431f61510c971b
# via requests-kerberos
pytest==8.3.3 \
--hash=sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181 \
Expand Down Expand Up @@ -1165,9 +1167,9 @@ tenacity==9.0.0 \
--hash=sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b \
--hash=sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539
# via iiblib
tomli==2.0.2 \
--hash=sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38 \
--hash=sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed
tomli==2.1.0 \
--hash=sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8 \
--hash=sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391
# via
# coverage
# pytest
Expand Down
22 changes: 22 additions & 0 deletions tests/tracing/test_instrument_tracing.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import logging
from concurrent.futures import ThreadPoolExecutor, as_completed

import pytest
from opentelemetry import trace
from opentelemetry.trace.status import StatusCode

from pubtools._impl import tracing
from pubtools._impl.tracing import TracingWrapper
from pubtools.tracing import get_trace_wrapper

Expand Down Expand Up @@ -154,3 +156,23 @@ def foo():

assert foo() == 1
assert tw.provider is None


def test_otel_not_available(caplog, monkeypatch):
monkeypatch.setenv("OTEL_TRACING", "true")
monkeypatch.setattr(tracing, "OPENTELEMETRY_AVAILABLE", False)
caplog.set_level(logging.DEBUG)

# Recreate an instance of TracingWrapper
tw = TracingWrapper()

@tw.instrument_func()
def foo():
return 1

assert foo() == 1
assert tw.provider is None
assert (
"Tracing is enabled but the open telemetry package is unavailable. "
"Tracing functionality will be disabled." in caplog.text
)
Loading