study-buddy / tests /observability /test_export_failure.py
GitHub Actions
deploy d092bea3608b7a29952f16357fda39b7a29e399b
2e818da
Raw
History Blame Contribute Delete
2.69 kB
"""A failing exporter or store must never break or block product code.
Global constraint from the plan preamble: "Telemetry export, local persistence,
and SigNoz failures must never fail a product request."
"""
from __future__ import annotations
import pytest
from app.observability import bootstrap
from app.observability.local_store import LocalObservationStore
from app.observability.operation import observe_operation
class _FailingExporter:
def export(self, observation): # noqa: ARG002 - signature must match real exporter
raise RuntimeError("exporter boom")
class _FailingStore:
def record(self, observation): # noqa: ARG002
raise OSError("disk full")
def latest(self):
raise OSError("disk full")
@pytest.fixture(autouse=True)
def _reset_failure_counter():
bootstrap.reset_suppressed_failures()
yield
bootstrap.shutdown_observability(timeout_seconds=2.0)
# --- Brief Step 2 example ---------------------------------------------------
def test_export_failure_does_not_escape_product_operation():
exporter = _FailingExporter()
with observe_operation("rag.request", exporter=exporter):
result = "product-result"
assert result == "product-result"
def test_export_failure_is_counted_but_suppressed():
exporter = _FailingExporter()
with observe_operation("rag.request", exporter=exporter):
pass
assert bootstrap.get_suppressed_failure_count() >= 1
def test_store_failure_does_not_escape_product_operation():
store = _FailingStore()
with observe_operation("rag.request", store=store):
result = 42
assert result == 42
assert bootstrap.get_suppressed_failure_count() >= 1
def test_store_and_exporter_failure_together_still_returns_result(tmp_path):
store = _FailingStore()
exporter = _FailingExporter()
with observe_operation("rag.request", store=store, exporter=exporter) as op:
op.set("raw_candidate_count", 3)
value = ["ok"]
assert value == ["ok"]
def test_exporter_failure_does_not_suppress_a_real_exception():
exporter = _FailingExporter()
with pytest.raises(ValueError, match="product bug"):
with observe_operation("rag.request", exporter=exporter):
raise ValueError("product bug")
def test_working_store_still_records_when_exporter_fails(tmp_path):
store = LocalObservationStore(tmp_path)
exporter = _FailingExporter()
with observe_operation("rag.request", store=store, exporter=exporter) as op:
op.set("raw_candidate_count", 8)
# Store write must still succeed even though the exporter blew up.
assert store.latest()["attributes"]["raw_candidate_count"] == 8