π O que Logar em Sistemas com IA
Sistemas com IA geram um volume de dados que apps tradicionais nunca geraram. Cada chamada a um LLM envolve request, response, tokens consumidos, latencia, custo e possiveis erros. Saber o que logar e tao importante quanto saber o que NAO logar. Logar demais queima storage e expoe dados sensiveis. Logar de menos te deixa cego quando algo quebra.
π― Conceito Principal
Em apps com LLM, voce precisa logar metadata da interacao, nao o conteudo bruto. A metadata te diz tudo que voce precisa para debugging, billing e performance: quantos tokens, quanto custou, quanto tempo levou, qual modelo respondeu, se deu erro ou sucesso.
O que logar:
- • Request/response pairs: Timestamp, user ID, model usado, status code (200, 429, 500). Nao o conteudo do prompt, so os metadados
- • Token usage: input_tokens, output_tokens, total. Essencial para billing e para detectar prompts que estao consumindo demais
- • Latencia: Tempo total do request (ms). Quanto o usuario esperou. Identifica degradacao de performance antes do usuario reclamar
- • Erros e retries: Tipo do erro (rate limit, timeout, invalid request), numero de retries, provider que falhou
- • Tool calls: Se o agente usou tools (browser, search, database), logar qual tool, se teve sucesso, e quanto tempo levou
π¨ O que NAO Logar
Logar conteudo de prompts em producao e um risco de seguranca e compliance. Prompts podem conter dados pessoais, informacoes medicas, financeiras ou confidenciais que os usuarios compartilham com a IA.
- ✗ Conteudo completo de prompts - Podem conter PII (nome, CPF, email, endereco)
- ✗ API keys em logs - Parece obvio, mas acontece quando voce loga o objeto de configuracao inteiro
- ✗ System prompts - Contem logica de negocio proprietaria. Se vazar, concorrentes copiam
- ✗ Respostas completas da IA - Podem conter dados sensΓveis refletidos do input do usuario
π‘ Dica Pratica
Se voce precisa debugar prompts em producao, use um sistema separado de debug logging com acesso restrito, retencao de 24-48h, e criptografia em repouso. Nunca no mesmo pipeline dos logs operacionais. Ferramentas como LangSmith, Helicone e Braintrust foram criadas exatamente para isso: observabilidade de LLM com controle de acesso.
ποΈ Structured Logging
console.log("deu erro aqui") nao escala. Quando voce tem centenas de requests por minuto, precisa de logs que sejam filtrΓ‘veis, pesquisaveis e parseΓ‘veis por mΓ‘quina. Structured logging significa que cada log entry e um objeto JSON com campos padronizados, nao uma string solta.
π― Conceito Principal
JSON e o formato padrao para logs em 2026. Cada entry tem campos fixos: timestamp, level, service, message, e campos extras especificos do evento. Ferramentas de log aggregation (Datadog, Grafana Loki, CloudWatch) parseiam JSON nativamente.
Log Levels (do menos ao mais grave):
- debug Detalhes para desenvolvimento. Desligado em producao
- info Operacoes normais. Request processado, user logou, pagamento confirmado
- warn Algo estranho mas nao fatal. Rate limit chegando, retry necessario, resposta lenta
- error Falha que impacta o usuario. API timeout, payment failed, agent crash
Campos obrigatorios:
- • timestamp: ISO 8601 com timezone
- • level: debug, info, warn, error
- • service: Qual microsservico gerou
- • correlation_id: UUID que conecta todos os logs de um request
- • message: Descricao curta do evento
π» Setup com Pino (Recomendado para Node.js)
Instalacao e configuracao:
npm install pino pino-pretty
// logger.ts
import pino from 'pino';
const logger = pino({
level: process.env.LOG_LEVEL || 'info',
transport: process.env.NODE_ENV === 'development'
? { target: 'pino-pretty', options: { colorize: true } }
: undefined, // JSON puro em producao
base: { service: 'ai-gateway', env: process.env.NODE_ENV },
});
export default logger;
Uso com correlation ID e request tracing:
import { randomUUID } from 'crypto';
// Middleware: atribui correlation ID a cada request
app.use((req, res, next) => {
req.correlationId = req.headers['x-correlation-id'] || randomUUID();
res.setHeader('x-correlation-id', req.correlationId);
next();
});
// Em qualquer lugar do codigo:
logger.info({
correlationId: req.correlationId,
userId: req.user?.id,
action: 'llm_request',
model: 'claude-sonnet-4',
inputTokens: 1200,
outputTokens: 450,
latencyMs: 2340,
status: 'success'
}, 'LLM request completed');
// Output em producao (JSON puro):
// {"level":30,"time":1710000000,"service":"ai-gateway",
// "correlationId":"abc-123","userId":"usr_42",
// "action":"llm_request","model":"claude-sonnet-4",
// "inputTokens":1200,"outputTokens":450,
// "latencyMs":2340,"status":"success",
// "msg":"LLM request completed"}
βοΈ Winston vs Pino
Pino
- ✓5x mais rapido que Winston
- ✓JSON nativo, zero overhead de formatacao
- ✓Async por padrao, nao bloqueia event loop
- -Menos transports built-in
Winston
- ✓Ecossistema maior, mais transports
- ✓Formatacao customizavel
- ✓Community support mais amplo
- -Mais lento em alta carga
Recomendacao: Pino para producao (performance), Winston se voce precisa de transports especificos (email, Slack, database).
π‘ Dica Pratica
Use correlation IDs desde o primeiro dia. Quando um usuario reporta um problema, voce pede o correlation ID (ou pega pelo user ID) e ve toda a jornada do request no Grafana ou Datadog. Sem correlation ID, voce fica procurando agulha em palheiro de logs.
π Metricas de IA: Tokens, Latencia, Custo
Em SaaS tradicional, voce monitora CPU, memoria e throughput. Em SaaS com IA, tokens sao a sua nova unidade de custo. Cada request custa dinheiro real. Se voce nao mede tokens por request, tokens por usuario e custo por dia, vai ter surpresas desagradaveis na fatura.
π― Conceito Principal
As tres metricas fundamentais de IA operations sao:
Tokens por Request
Quantos tokens de input e output cada chamada consome. Varia drasticamente: um chat simples pode usar 500 tokens, um agente com RAG pode usar 50.000. Tracking granular permite identificar quais features ou usuarios estao queimando mais.
Latencia P50 / P95
P50 e a mediana: metade dos requests sao mais rapidos. P95 e o pior caso tipico: 95% dos requests sao mais rapidos que esse valor. Se seu P50 e 2s mas o P95 e 15s, tem algo errado com 5% dos requests. Investigue: modelo lento? Prompt muito grande? Retry?
Custo por Usuario / Agente / Dia
Multiplique tokens pelo preco do modelo. Agrupe por dimensao relevante: custo por usuario (billing), custo por agente (otimizacao), custo por dia (budget). Se um usuario free esta gastando mais que um pro, algo esta errado.
π° Referencia de Custo por Modelo (Marco 2026)
| Modelo | Input (1M tok) | Output (1M tok) | Custo/1k requests* |
|---|---|---|---|
| GPT-4o | $2.50 | $10.00 | ~$6.25 |
| Claude Sonnet 4 | $3.00 | $15.00 | ~$9.00 |
| GPT-4o-mini | $0.15 | $0.60 | ~$0.37 |
| Claude Haiku 3.5 | $0.80 | $4.00 | ~$2.40 |
| DeepSeek R1 | $0.55 | $2.19 | ~$1.37 |
*Estimativa baseada em ~500 tokens input + 500 tokens output por request. Precos podem variar.
π» Construindo um Cost Dashboard
// Tabela de precos por modelo (por token)
const PRICING = {
'gpt-4o': { input: 2.50 / 1e6, output: 10.00 / 1e6 },
'claude-sonnet-4': { input: 3.00 / 1e6, output: 15.00 / 1e6 },
'gpt-4o-mini': { input: 0.15 / 1e6, output: 0.60 / 1e6 },
};
function calculateCost(model, tokens) {
const prices = PRICING[model];
if (!prices) return 0;
return (tokens.input * prices.input) + (tokens.output * prices.output);
}
// Gravar custo a cada request
async function trackUsage(userId, agentId, model, tokens, latencyMs) {
const cost = calculateCost(model, tokens);
await db.insert('usage_log', {
user_id: userId,
agent_id: agentId,
model,
input_tokens: tokens.input,
output_tokens: tokens.output,
cost_usd: cost,
latency_ms: latencyMs,
created_at: new Date()
});
}
// Query: custo por usuario nos ultimos 30 dias
const costByUser = await db.query(`
SELECT user_id, SUM(cost_usd) as total_cost,
SUM(input_tokens + output_tokens) as total_tokens,
COUNT(*) as total_requests
FROM usage_log
WHERE created_at > NOW() - INTERVAL '30 days'
GROUP BY user_id
ORDER BY total_cost DESC
LIMIT 20
`);
π‘ Dica Pratica
Crie um daily cost report que roda automaticamente. Mesmo que simples (um script que roda no cron e envia para Telegram/Slack), voce vai pegar anomalias cedo. Um usuario que de repente gasta 10x mais que o normal pode indicar um loop infinito, um bot abusando, ou uma feature que precisa de rate limiting.
π¨ Alertas e Incidentes
Monitoramento sem alertas e um dashboard que ninguem olha. Alertas automaticos sao o sistema nervoso do seu SaaS. Quando algo sai do normal, voce precisa saber em minutos, nao em horas. O usuario nao deve ser o primeiro a te avisar que o app esta fora do ar.
π― Conceito Principal
Alertas bons tem tres propriedades: sao acionaveis (voce sabe o que fazer quando recebe), relevantes (nao disparam por qualquer coisa), e urgentes (chegam no canal certo na hora certa). Alerta que dispara toda hora e ignorado. Alerta que nao dispara quando devia e inutil.
O que deve disparar alertas em SaaS com IA:
- • Error spikes: Taxa de erro > 5% nos ultimos 5 minutos. Pode indicar que o provider de IA esta fora, API key expirou, ou um deploy quebrou algo
- • Cost anomalies: Custo diario > 2x a media dos ultimos 7 dias. Um loop infinito de agente pode queimar $100 em minutos
- • Latency degradation: P95 > 15 segundos. Experiencia do usuario degradou ao ponto de abandono
- • Rate limit exhaustion: Voce esta batendo no rate limit do provider. Requests estao falhando ou ficando na fila
π‘ Canais de Notificacao por Severidade
Warning
Latencia alta, custo subindo
Slack / Discord channel
High
Error rate > 5%, cost spike
Telegram / SMS
Critical
App down, data breach
PagerDuty / Phone call
π» Alerta via Telegram Bot
// Funcao de alerta via Telegram
async function sendAlert(severity, message) {
const emoji = { warning: 'β οΈ', high: 'π', critical: 'π¨' };
const text = `${emoji[severity]} [${severity.toUpperCase()}]\n\n${message}`;
await fetch(`https://api.telegram.org/bot${process.env.ALERT_BOT_TOKEN}/sendMessage`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_id: process.env.ALERT_CHAT_ID,
text,
parse_mode: 'HTML'
})
});
}
// Checagem periodica (roda a cada 5 min via cron ou setInterval)
async function checkAlerts() {
const last5min = await db.query(`
SELECT COUNT(*) as total,
SUM(CASE WHEN status = 'error' THEN 1 ELSE 0 END) as errors,
AVG(latency_ms) as avg_latency,
SUM(cost_usd) as cost
FROM usage_log
WHERE created_at > NOW() - INTERVAL '5 minutes'
`);
const errorRate = last5min.errors / last5min.total;
if (errorRate > 0.05) {
await sendAlert('high',
`Error rate em ${(errorRate * 100).toFixed(1)}%\n` +
`${last5min.errors}/${last5min.total} requests falharam nos ultimos 5min`
);
}
if (last5min.avg_latency > 15000) {
await sendAlert('warning',
`Latencia media em ${(last5min.avg_latency/1000).toFixed(1)}s\n` +
`Threshold: 15s. Investigar provider de IA.`
);
}
}
π‘ Dica Pratica
Configure um "dead man's switch": um alerta que dispara quando o sistema para de enviar heartbeats. Se o seu servico de monitoramento cair junto com o app, ninguem te avisa. Use um servico externo (UptimeRobot, Better Uptime) que pinga seu endpoint de health check a cada minuto. Se nao responder em 3 tentativas, dispara o alerta.
π Debugging Sistemas de IA
Debugar sistemas com IA e fundamentalmente diferente de debugar codigo tradicional. O mesmo input pode gerar outputs diferentes. O comportamento muda com a versao do modelo, com a temperatura, com o tamanho do contexto. Voce nao pode simplesmente colocar um breakpoint e inspecionar. Precisa de estrategias especificas.
π― Conceito Principal
Reproduzir problemas com LLMs exige que voce salve o estado completo da interacao: o prompt exato (system + user), o modelo e versao, a temperatura, o contexto/historico, e quaisquer tool calls. Sem isso, voce nao consegue reproduzir o bug.
Trate prompts como codigo. Versione no Git. Cada mudanca tem um hash. Quando o comportamento da IA muda, voce sabe qual versao do prompt estava ativa.
Rodar duas versoes do prompt simultaneamente (50/50) e medir qual performa melhor. Metricas: taxa de erro, satisfacao do usuario, tokens consumidos, custo.
Salvar a sequencia completa de messages (sem PII) para poder "replay" uma conversa problematica em ambiente de teste. Essencial para agentes multi-turn.
π οΈ Tecnicas de Debug para LLMs
π» Prompt Versioning + A/B Test
// Prompts versionados como objetos
const PROMPTS = {
'agent-v1': {
version: '1.0.0',
system: 'You are a helpful assistant. Be concise.',
temperature: 0.3,
},
'agent-v2': {
version: '2.0.0',
system: 'You are an expert assistant. Think step by step. Be precise.',
temperature: 0.2,
},
};
// A/B test: 50/50 split
function getActivePrompt(userId) {
const hash = hashString(userId); // Deterministic per user
const variant = hash % 2 === 0 ? 'agent-v1' : 'agent-v2';
return { ...PROMPTS[variant], variant };
}
// Log qual variante foi usada
logger.info({
userId,
promptVariant: prompt.variant,
promptVersion: prompt.version,
tokens: result.usage,
latencyMs: elapsed,
}, 'AB test request completed');
// Depois: query para comparar performance
// SELECT prompt_variant, AVG(latency_ms), AVG(cost_usd),
// SUM(CASE WHEN status='error' THEN 1 ELSE 0 END) / COUNT(*) as error_rate
// FROM usage_log WHERE created_at > NOW() - INTERVAL '7 days'
// GROUP BY prompt_variant
π‘ Dica Pratica
Ferramentas como LangSmith (LangChain), Braintrust, e Helicone automatizam prompt versioning, A/B testing e eval sets. Nao reinvente a roda. Se voce tem mais de 3 prompts em producao, adote uma dessas ferramentas. O custo e minimo comparado ao custo de um prompt mal otimizado rodando milhares de vezes.
π οΈ Exercicio: Observabilidade Basica
Hora de implementar. Neste exercicio voce vai adicionar structured logging, token tracking e alertas de erro ao seu SaaS. Quando terminar, voce vai saber exatamente quanto cada request custa, quanto tempo leva, e ser notificado quando algo quebrar.
Exercicio: Observabilidade Basica
Tempo estimado: 35-45 minutos
Adicionar Structured Logging
Configure Pino (ou Winston) no seu projeto:
Implementar Token Tracking
Registre o custo de cada chamada ao LLM:
Construir Dashboard de Custo
Uma pagina simples que mostra os numeros:
Configurar Alertas
Alertas automaticos para os cenarios criticos: