Skip to content

Commit

Permalink
Test the setup_default_tracing()
Browse files Browse the repository at this point in the history
This resulted in some fix to the configuration too,
as consuming OTEL_SERVICE_NAME was not being done correctly

It does involve some messy reaching into otel internals though
  • Loading branch information
bloodearnest committed Mar 20, 2024
1 parent 534f574 commit 6448690
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 20 deletions.
43 changes: 25 additions & 18 deletions jobrunner/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,20 @@

logger = logging.getLogger(__name__)

# https://github.com/open-telemetry/semantic-conventions/tree/main/docs/resource#service
resource = Resource.create(
attributes={
"service.name": "jobrunner",
"service.namespace": os.environ.get("BACKEND", "unknown"),
"service.version": config.VERSION,
}
)
provider = TracerProvider(resource=resource)
trace.set_tracer_provider(provider)


def add_exporter(exporter, processor=BatchSpanProcessor):

def get_provider():
# https://github.com/open-telemetry/semantic-conventions/tree/main/docs/resource#service
resource = Resource.create(
attributes={
"service.name": os.environ.get("OTEL_SERVICE_NAME", "jobrunner"),
"service.namespace": os.environ.get("BACKEND", "unknown"),
"service.version": config.VERSION,
}
)
return TracerProvider(resource=resource)


def add_exporter(provider, exporter, processor=BatchSpanProcessor):
"""Utility method to add an exporter.
We use the BatchSpanProcessor by default, which is the default for
Expand All @@ -43,18 +44,24 @@ def add_exporter(exporter, processor=BatchSpanProcessor):
provider.add_span_processor(processor(exporter))


def setup_default_tracing():
def setup_default_tracing(set_global=True):
"""Inspect environment variables and set up exporters accordingly."""

provider = get_provider()

if "OTEL_EXPORTER_OTLP_HEADERS" in os.environ:
if "OTEL_SERVICE_NAME" not in os.environ:
os.environ["OTEL_SERVICE_NAME"] == "jobrunner"
if "OTEL_EXPORTER_OTLP_ENDPOINT" not in os.environ:
os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://api.honeycomb.io"

add_exporter(OTLPSpanExporter())
add_exporter(provider, OTLPSpanExporter())

if "OTEL_EXPORTER_CONSOLE" in os.environ:
add_exporter(ConsoleSpanExporter())
add_exporter(provider, ConsoleSpanExporter())

if set_global:
trace.set_tracer_provider(provider)

return provider


@warn_assertions
Expand Down
6 changes: 4 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
from jobrunner.lib.subprocess_utils import subprocess_run


# set up tracing
# set up test tracing
provider = tracing.get_provider()
tracing.trace.set_tracer_provider(provider)
test_exporter = InMemorySpanExporter()
tracing.add_exporter(test_exporter, processor=SimpleSpanProcessor)
tracing.add_exporter(provider, test_exporter, processor=SimpleSpanProcessor)


def pytest_configure(config):
Expand Down
55 changes: 55 additions & 0 deletions tests/test_tracing.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,68 @@
import os
import time

import opentelemetry.exporter.otlp.proto.http.trace_exporter
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.export import ConsoleSpanExporter

from jobrunner import config, models, tracing
from tests.conftest import get_trace
from tests.factories import job_factory, job_request_factory, job_results_factory


def test_setup_default_tracing_empty_env(monkeypatch):
env = {}
monkeypatch.setattr(os, "environ", env)
provider = tracing.setup_default_tracing(set_global=False)
assert provider._active_span_processor._span_processors == ()


def test_setup_default_tracing_console(monkeypatch):
env = {"OTEL_EXPORTER_CONSOLE": "1"}
monkeypatch.setattr(os, "environ", env)
provider = tracing.setup_default_tracing(set_global=False)

processor = provider._active_span_processor._span_processors[0]
assert isinstance(processor.span_exporter, ConsoleSpanExporter)


def test_setup_default_tracing_otlp_defaults(monkeypatch):
env = {"OTEL_EXPORTER_OTLP_HEADERS": "foo=bar"}
monkeypatch.setattr(os, "environ", env)
monkeypatch.setattr(
opentelemetry.exporter.otlp.proto.http.trace_exporter, "environ", env
)
provider = tracing.setup_default_tracing(set_global=False)
assert provider.resource.attributes["service.name"] == "jobrunner"

exporter = provider._active_span_processor._span_processors[0].span_exporter
assert isinstance(exporter, OTLPSpanExporter)
assert exporter._endpoint == "https://api.honeycomb.io/v1/traces"
assert exporter._headers == {"foo": "bar"}
assert env["OTEL_EXPORTER_OTLP_ENDPOINT"] == "https://api.honeycomb.io"


def test_setup_default_tracing_otlp_with_env(monkeypatch):
env = {
"OTEL_EXPORTER_OTLP_HEADERS": "foo=bar",
"OTEL_SERVICE_NAME": "service",
"OTEL_EXPORTER_OTLP_ENDPOINT": "https://endpoint",
}
monkeypatch.setattr(os, "environ", env)
monkeypatch.setattr(
opentelemetry.exporter.otlp.proto.http.trace_exporter, "environ", env
)
provider = tracing.setup_default_tracing(set_global=False)
assert provider.resource.attributes["service.name"] == "service"

exporter = provider._active_span_processor._span_processors[0].span_exporter

assert isinstance(exporter, OTLPSpanExporter)
assert exporter._endpoint == "https://endpoint/v1/traces"
assert exporter._headers == {"foo": "bar"}


def test_trace_attributes(db):
jr = job_request_factory(
original=dict(
Expand Down

0 comments on commit 6448690

Please sign in to comment.