Il tracing è proprietario e vive nel tuo database. Nessun dato esce dal perimetro, e le tracce si interrogano in SQL come qualsiasi altra tabella.
Modello dati
run (un turno di conversazione)
└── span (un passo dentro la run, annidabile)
├── span_type = "agent" → un nodo del grafo ha lavorato
├── span_type = "llm" → una chiamata al modello (token e costo)
└── span_type = "tool" → una chiamata a un tool
events (log applicativi correlati alla run)
| Tabella | Contenuto |
|---|---|
liagraph.runs | input, output, stato, agenti coinvolti, token, costo, durata, errore |
liagraph.spans | gerarchia dei passi con tempi, modello, token e costo di ciascuno |
liagraph.events | log leggibili (tool invocati, errori, decisioni) |
Tre viste pronte all'uso: v_daily_usage, v_model_usage, v_agent_usage.
Come vengono raccolti i dati
app/observability/tracer.py definisce RunTracer, un callback handler di
LangChain creato per ogni run e passato a LangGraph. Riceve automaticamente:
| Callback | Cosa produce |
|---|---|
on_chain_start/end | span di tipo agent per i nodi di primo livello del grafo |
on_chat_model_start / on_llm_end | span llm con token e costo calcolato |
on_tool_start/end/error | span tool con argomenti e risultato |
Gli agenti non contengono una sola riga di codice di strumentazione: chi scrive un nuovo agente ottiene il tracing gratis.
Attribuzione degli span a un agente
Dentro il sotto-grafo di un agente, LangGraph espone un namespace del tipo
researcher:<uuid>|tools:<uuid>. Il primo segmento è il nodo del grafo
principale, quindi l'agente: è così che una chiamata a un tool annidata in
profondità viene attribuita al suo agente.
Perché i contenuti sono troncati
Prompt e risposte vengono salvati troncati (~2000 caratteri). Le tracce servono a
capire cosa è successo, non a duplicare l'intera conversazione, che è già in
messages. Il limite si cambia in tracer.py (_MAX_TESTO).
Calcolo dei costi
I token arrivano da usage_metadata dei messaggi, popolato da Bedrock con i
valori reali dell'API Converse. Il prezzo viene dal catalogo:
costo = (input_tokens × prezzo_input + output_tokens × prezzo_output) / 1.000.000
Il costo di uno span llm è quello della singola chiamata; il costo di una run è
la somma delle sue chiamate. Se un modello non è in models.yaml il costo è 0:
un prezzo mancante non deve mai far fallire una run, ma va corretto nel catalogo.
I prezzi in
config/models.yamlsono un punto di partenza. Verificali sul listino Bedrock per la tua regione: i costi mostrati nella UI sono accurati quanto quei numeri.
La console
Osservabilità mostra, per il periodo scelto (24 ore / 7 / 30 giorni):
- indicatori con variazione rispetto al periodo precedente: esecuzioni, costo totale, token, durata media, errori;
- andamento giornaliero del costo;
- ripartizione del costo per modello;
- attività per agente: invocazioni, chiamate LLM, tool, token, costo;
- elenco delle esecuzioni.
Selezionando una run si apre la traccia completa: timeline a cascata degli span (con durata proporzionale e annidamento), log e ingresso/uscita.
La pagina si aggiorna da sola ogni 15 secondi.
Interrogare le tracce in SQL
-- Le run più costose degli ultimi 7 giorni
select started_at, left(input, 60) as richiesta, agents_used, cost_usd, duration_ms
from liagraph.runs
where started_at > now() - interval '7 days'
order by cost_usd desc
limit 20;
-- Quanto costa mediamente ciascun agente per invocazione
select agent,
count(*) as invocazioni,
round(avg(cost_usd)::numeric, 6) as costo_medio
from liagraph.spans
where span_type = 'agent'
group by agent
order by costo_medio desc;
-- Tool più lenti
select name, count(*) as chiamate, avg(duration_ms)::int as durata_media
from liagraph.spans
where span_type = 'tool'
group by name
order by durata_media desc;
LangSmith
Facoltativo e disattivato per impostazione predefinita. Attivandolo
(LANGSMITH_TRACING=true più la chiave) funziona in parallelo al tracing
proprietario: nessuna funzione del sistema dipende da esso.
Cosa non c'è ancora
- alert su soglie di costo o tasso di errore;
- esportazione OpenTelemetry;
- ritenzione automatica delle tracce vecchie (per ora si cancella a mano);
- valutazione della qualità delle risposte.
Vedi ROADMAP.md.