Coverage for src / lexigram / contracts / observability / ai.py: 0%
26 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-15 18:57 +0800
1"""AI observability contracts."""
3from __future__ import annotations
5from typing import Any, Protocol, runtime_checkable
7from lexigram.contracts.exceptions import LexigramError
10# Observability Errors
11class MonitoringError(LexigramError):
12 """Base error raised during AI observability monitoring."""
14 _code: str = "LEX_ERR_AI_005"
17class MetricsCollectionError(MonitoringError):
18 """Error raised during metrics collection."""
20 _code: str = "LEX_ERR_AI_003"
23class TracingError(LexigramError):
24 """Error raised during tracing operations."""
26 _code: str = "LEX_ERR_AI_004"
29@runtime_checkable
30class ObservabilityProtocol(Protocol):
31 """Protocol for AI-specific metrics and tracing."""
33 async def record_generation(
34 self,
35 model: str,
36 provider: str,
37 tokens_prompt: int,
38 tokens_completion: int,
39 latency_ms: float,
40 successful: bool,
41 ) -> None:
42 """Record a single LLM generation event."""
43 ...
45 async def start_trace(
46 self, name: str, metadata: dict[str, Any] | None = None
47 ) -> str:
48 """Start a trace block, returning a trace ID."""
49 ...
51 async def end_trace(
52 self, trace_id: str, metadata: dict[str, Any] | None = None
53 ) -> None:
54 """End a trace block."""
55 ...
58@runtime_checkable
59class AITracerProtocol(Protocol):
60 """Protocol for AI distributed tracing.
62 Implementations wrap individual LLM/vector calls in named spans,
63 allowing distributed trace propagation without coupling to a
64 specific tracing backend (OpenTelemetry, Jaeger, etc.).
65 """
67 def trace_llm_call(
68 self,
69 provider: str,
70 model: str,
71 *,
72 streaming: bool = False,
73 ) -> Any:
74 """Return a context manager that wraps an LLM call in a trace span.
76 Args:
77 provider: Provider name (e.g. ``"openai"``).
78 model: Model identifier.
79 streaming: Whether this is a streaming call.
81 Returns:
82 A synchronous context manager.
83 """
84 ...
87@runtime_checkable
88class AIMetricsProtocol(Protocol):
89 """Protocol for AI metrics collection.
91 Implementations record counters, histograms, and gauges for
92 LLM/vector operations without coupling to a specific metrics
93 backend (Prometheus, StatsD, etc.).
94 """
96 def record_completion(
97 self,
98 provider: str,
99 model: str,
100 tokens: int,
101 cost: float,
102 ) -> None:
103 """Record a successful LLM completion.
105 Args:
106 provider: Provider name.
107 model: Model identifier.
108 tokens: Total tokens consumed.
109 cost: Estimated dollar cost.
110 """
111 ...
113 def record_error(self, provider: str, error_type: str) -> None:
114 """Record an LLM or vector store error.
116 Args:
117 provider: Provider name.
118 error_type: Short error category string.
119 """
120 ...
123@runtime_checkable
124class AIHealthMonitorProtocol(Protocol):
125 """Protocol for AI health monitoring.
127 Allows the DI container to resolve health status of AI sub-systems
128 (LLM availability, vector store connectivity, etc.) through a
129 stable interface.
130 """
132 async def check(self) -> Any:
133 """Run health checks and return a ``HealthCheckResult``-like object.
135 Returns:
136 An object with at least a ``status`` attribute.
137 """
138 ...
140 def register_check(self, name: str, check: Any) -> None:
141 """Register a named health-check callable.
143 Args:
144 name: Unique check name.
145 check: An async callable returning a health status.
146 """
147 ...
150__all__ = [
151 "AIHealthMonitorProtocol",
152 "AIMetricsProtocol",
153 "AITracerProtocol",
154 "MetricsCollectionError",
155 "MonitoringError",
156 "ObservabilityProtocol",
157 "TracingError",
158]