| """Observability via Langfuse (v4). |
| |
| Initializes the Langfuse client from our settings and re-exports the pieces the |
| rest of the app uses to trace itself: |
| |
| - ``observe`` : decorator that turns a function into a traced span |
| (use as_type="generation" for model calls, |
| as_type="tool" for tool calls). |
| - ``trace_attributes`` : context manager that stamps trace-level fields |
| (session_id, tags, metadata) onto every span |
| created inside it. |
| - ``annotate_span`` : add metadata to the currently-running span. |
| - ``flush`` / ``current_trace_url`` : flush buffered events; fetch the URL of |
| the trace currently in scope. |
| |
| If Langfuse keys are not configured, every export degrades to a safe no-op so |
| the app and eval still run untraced. |
| """ |
|
|
| from __future__ import annotations |
|
|
| from contextlib import contextmanager, nullcontext |
|
|
| from src.config import settings |
|
|
| |
| enabled = bool(settings.langfuse_public_key and settings.langfuse_secret_key) |
|
|
|
|
| if enabled: |
| from langfuse import Langfuse, get_client |
| from langfuse import observe as observe |
| from langfuse import propagate_attributes as _propagate |
|
|
| |
| |
| |
| Langfuse( |
| public_key=settings.langfuse_public_key, |
| secret_key=settings.langfuse_secret_key, |
| host=settings.langfuse_host, |
| ) |
| _client = get_client() |
|
|
| def trace_attributes(**kwargs): |
| """Stamp trace-level attributes (session_id, tags, metadata, ...).""" |
| return _propagate(**kwargs) |
|
|
| def annotate_span(**kwargs) -> None: |
| """Attach metadata/name/level to the current span.""" |
| _client.update_current_span(**kwargs) |
|
|
| def flush() -> None: |
| _client.flush() |
|
|
| def current_trace_url() -> str | None: |
| try: |
| return _client.get_trace_url() |
| except Exception: |
| return None |
|
|
| else: |
|
|
| def observe(func=None, **_kwargs): |
| """No-op stand-in for langfuse.observe (supports @observe and @observe(...)).""" |
| if callable(func): |
| return func |
|
|
| def _decorator(f): |
| return f |
|
|
| return _decorator |
|
|
| def trace_attributes(**_kwargs): |
| return nullcontext() |
|
|
| def annotate_span(**_kwargs) -> None: |
| pass |
|
|
| def flush() -> None: |
| pass |
|
|
| def current_trace_url() -> str | None: |
| return None |
|
|