Emit a docling_serve.request span per instance attempt

This commit is contained in:
Yiorgis Gozadinos 2026-07-10 11:16:27 +03:00
parent da79f92af1
commit 73ba764922
No known key found for this signature in database
3 changed files with 40 additions and 2 deletions

View file

@ -4,6 +4,7 @@
### Changed
- Logfire spans carry `service.version` and a per-process `service.name` (`haiku-ingester`, `haiku-rag`, `haiku-rag-app`); `OTEL_SERVICE_NAME` / `LOGFIRE_SERVICE_NAME` override the default.
- Each docling-serve request emits a `docling_serve.request` span carrying the instance `url` and `attempt`.
## [0.65.0] - 2026-07-09

View file

@ -11,6 +11,7 @@ import httpx
from haiku.rag.circuit_breaker import CircuitBreaker
from haiku.rag.config import CircuitBreakerConfig, DoclingServeConfig
from haiku.rag.telemetry import logfire
logger = logging.getLogger(__name__)
@ -156,8 +157,14 @@ class DoclingServeClient:
base_url = self._pick_url(exclude=frozenset(tried))
breaker = self._breaker_for(base_url)
try:
async with self._httpx_client() as client:
result = await attempt(client, base_url)
with logfire.span(
"docling_serve.request",
name=name,
url=base_url,
attempt=attempt_no,
):
async with self._httpx_client() as client:
result = await attempt(client, base_url)
except Exception as exc:
if not _is_retryable(exc):
raise

View file

@ -301,6 +301,36 @@ async def test_task_failure_is_not_retried():
assert set(seen) == {"h"}
@pytest.mark.asyncio
async def test_request_span_records_instance_per_attempt(monkeypatch):
"""Each attempt opens a docling_serve.request span tagged with the
instance URL, so failover is traceable in Logfire."""
from contextlib import nullcontext
from haiku.rag.providers import docling_serve as ds_module
spans: list[dict] = []
def _fake_span(span_name, /, **attrs):
spans.append({"span_name": span_name, **attrs})
return nullcontext()
monkeypatch.setattr(ds_module.logfire, "span", _fake_span)
transport, _ = _failover_transport({"down-s"}, "t", {"ok": True})
client = DoclingServeClient(
base_urls=["http://down-s:5001", "http://up-s:5001"],
transport=transport,
retry_base_delay=0.0,
)
await _poll(client)
requests = [s for s in spans if s["span_name"] == "docling_serve.request"]
assert [s["url"] for s in requests] == ["http://down-s:5001", "http://up-s:5001"]
assert [s["attempt"] for s in requests] == [0, 1]
def test_pick_url_skips_excluded_instances():
"""On retry, _pick_url advances past every excluded instance."""
urls = ["http://p1:5001", "http://p2:5001", "http://p3:5001"]