Skip to content

refactor(telemetry): collapse 6 OpenTelemetry no-op stubs into one proxy#286

Merged
Kamilbenkirane merged 1 commit into
mainfrom
cleanup/telemetry-noop-proxy
Jun 17, 2026
Merged

refactor(telemetry): collapse 6 OpenTelemetry no-op stubs into one proxy#286
Kamilbenkirane merged 1 commit into
mainfrom
cleanup/telemetry-noop-proxy

Conversation

@Kamilbenkirane

Copy link
Copy Markdown
Member

What

When opentelemetry-api is not installed, telemetry.py falls back to six hand-written no-op stand-ins — _NoOpSpan, _NoOpTracer, _NoOpStatus, _NoOpStatusCode, _NoOpHistogram, _NoOpMeter. They're near-identical discard-everything boilerplate.

This replaces all six with a single _NoOp proxy that returns itself for every attribute access and call:

class _NoOp:
    ERROR = "ERROR"  # satisfies StatusCode.ERROR
    def __init__(self, *a, **k): ...
    def __call__(self, *a, **k): return self
    def __getattr__(self, name): return self
    def __enter__(self): return self
    def __exit__(self, *a): return None

Net −36 lines (telemetry.py: +24 / −60).

Why it's safe

Every call site the telemetry module makes against these objects is covered by the proxy, and all of them discard return values:

  • with tracer.start_as_current_span(...) as span:__getattr____call____enter__ all return self; span.set_attribute / set_attributes / add_event / record_exception / set_status / end(...) resolve through __getattr__/__call__.
  • Status(StatusCode.ERROR, str(exc))StatusCode.ERROR is the real class attr "ERROR"; Status(...) instantiates _NoOp and discards args.
  • meter.create_histogram(...).record(...) chains through the proxy.
  • Special methods (__enter__, __call__) are looked up on the type, so __getattr__ never shadows them. No ==/identity checks are made on Status objects.

_noop_use_span is kept as a separate function — it must yield the passed-in span, which a self-returning proxy would not. The real-OpenTelemetry path is untouched. No behavior change.

Tests

Adds tests/unit_tests/test_telemetry_noop.py driving the _NoOp proxy through every call shape the module uses. The import-fallback path previously had no coverage (the suite always runs with opentelemetry installed).

make ci green: 676 passed, coverage 81.76%, ruff + format + mypy + bandit clean.

Context

This is the single surviving cleanup from a repo-wide over-engineering audit. The audit's other candidates — including a "protocol client dedup" — were investigated and deliberately not done: the chatcompletions/openresponses protocols are a template-driven extension point and only ~14% identical, so merging them would fight the design.

When opentelemetry-api is not installed, telemetry fell back to six hand-written
no-op stand-ins (_NoOpSpan / _NoOpTracer / _NoOpStatus / _NoOpStatusCode /
_NoOpHistogram / _NoOpMeter). Replace them with a single _NoOp proxy that returns
itself for every attribute access and call, covering span/tracer/meter/histogram
usage plus Status(StatusCode.ERROR, ...) construction and the StatusCode.ERROR
attribute.

_noop_use_span stays separate: it must yield the passed-in span, which a
self-returning proxy would not.

Add test_telemetry_noop.py exercising every call shape the telemetry module uses
against the proxy; the import-fallback path previously had no test coverage.

No behavior change. The real-OpenTelemetry path is untouched.
@claude

claude Bot commented Jun 17, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@Kamilbenkirane Kamilbenkirane merged commit b7e33e1 into main Jun 17, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant