P1.1 — Implement real ai_router.chat_completion / stream_chat_completion using Ollama Cloud primary + OpenRouter fallback. Fixes AttributeError on /api/v1/chat and /api/v1/wallet-clusters. P1.2 — Fix broken RAG call paths: telegram bot now hits /api/v1/rag/v2/search then ai_router.chat_completion; unified_wallet_scanner._rag_enrich uses async httpx + correct path. Mount app.domains.databus.router. P1.3 — Implement setup_otel / shutdown_otel in core/tracing.py and create core/langfuse.py with init_langfuse / flush_langfuse as safe no-ops when SDK is missing or env vars unset. P1.4 — Fix Prometheus alert rule metric name drift: rmi_requests_total -> rmi_http_requests_total (matches metrics.py). P1.5 — Move dead admin_backend.py (1691 LOC) to app/domains/admin/router.py and mount it. Admin login endpoint now reachable. P2.1 — Rename app/domains/auth/__init__.py (507 LOC router file that broke mypy) -> app/domains/auth/router.py. Mount app.domains.auth.router so /register, /login, /wallet/*, /user/me, /2fa/*, OAuth, Telegram are live. P2.1b — Add pyotp + qrcode to requirements.txt so 2FA endpoints don't 503.
49 lines
No EOL
1.2 KiB
Python
49 lines
No EOL
1.2 KiB
Python
"""Langfuse LLM tracing - opt-in via env vars.
|
|
|
|
Safe no-op when LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY are unset
|
|
or the `langfuse` package is not installed.
|
|
"""
|
|
|
|
import os
|
|
|
|
LANGFUSE_ENABLED = bool(
|
|
os.getenv("LANGFUSE_PUBLIC_KEY", "") and os.getenv("LANGFUSE_SECRET_KEY", "")
|
|
)
|
|
LANGFUSE_HOST = os.getenv("LANGFUSE_HOST", "https://cloud.langfuse.com")
|
|
|
|
_initialized = False
|
|
|
|
|
|
def init_langfuse() -> bool:
|
|
"""Initialize the Langfuse client. Returns True on success."""
|
|
global _initialized
|
|
if not LANGFUSE_ENABLED:
|
|
return False
|
|
try:
|
|
from langfuse import Langfuse # noqa: F401
|
|
|
|
Langfuse(
|
|
public_key=os.getenv("LANGFUSE_PUBLIC_KEY"),
|
|
secret_key=os.getenv("LANGFUSE_SECRET_KEY"),
|
|
host=LANGFUSE_HOST,
|
|
)
|
|
_initialized = True
|
|
return True
|
|
except ImportError:
|
|
return False
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def flush_langfuse() -> None:
|
|
"""Flush any pending Langfuse events. Safe to call on shutdown."""
|
|
if not _initialized:
|
|
return
|
|
try:
|
|
from langfuse import Langfuse
|
|
|
|
Langfuse().flush()
|
|
except ImportError:
|
|
pass
|
|
except Exception:
|
|
pass |