MODULO 6.4

πŸ“Š Logs, Observabilidade e Monitoramento

Em producao, voce nao pode abrir o terminal e dar console.log. Logs estruturados, metricas de tokens e latencia, e alertas automaticos sao o que separa um app que funciona de um app que voce sabe que funciona.

6
Topicos
~50min
Duracao
Intermediario
Nivel
Teoria + Pratica
Tipo
1

πŸ“ 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.

2

πŸ—‚οΈ 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.

3

πŸ“ˆ 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.

4

🚨 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.

5

πŸ” 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.

1.
Prompt Versioning

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.

2.
A/B Testing de Prompts

Rodar duas versoes do prompt simultaneamente (50/50) e medir qual performa melhor. Metricas: taxa de erro, satisfacao do usuario, tokens consumidos, custo.

3.
Conversation Replay

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

1
Isolar o prompt Copie o prompt exato para o playground do provider (Anthropic Console, OpenAI Playground). Funciona la? Se sim, o problema e no codigo. Se nao, e no prompt.
2
Reducao do contexto Remova partes do contexto ate encontrar o que causa o comportamento indesejado. Prompt longo demais frequentemente degrada a qualidade da resposta.
3
Temperature sweep Teste o mesmo prompt com temperature 0 (deterministico) vs 0.7 (criativo). Comportamento inconsistente com temperature alta pode ser normal, nao um bug.
4
Eval sets Mantenha um conjunto de inputs com outputs esperados. Rode automaticamente apos cada mudanca de prompt. Se a acuracia cai, voce sabe que a mudanca causou regressao.

πŸ’» 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.

6

πŸ› οΈ 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

1

Adicionar Structured Logging

Configure Pino (ou Winston) no seu projeto:

☐Instalar pino e pino-pretty como dependencias
☐Criar logger.ts com configuracao base (service name, env, level)
☐Adicionar middleware de correlation ID em todas as rotas
☐Substituir todos os console.log por chamadas ao logger
2

Implementar Token Tracking

Registre o custo de cada chamada ao LLM:

☐Criar tabela usage_log no banco (user_id, model, tokens, cost, latency, timestamp)
☐Criar funcao calculateCost com tabela de precos por modelo
☐Gravar usage apos cada chamada de IA (input_tokens, output_tokens, cost_usd)
☐Criar endpoint /api/admin/usage com custo por usuario e por dia
3

Construir Dashboard de Custo

Uma pagina simples que mostra os numeros:

☐Custo total hoje, esta semana, este mes
☐Top 10 usuarios por consumo de tokens
☐Grafico de custo por dia (ultimos 30 dias)
☐P50 e P95 de latencia por modelo
4

Configurar Alertas

Alertas automaticos para os cenarios criticos:

☐Alerta quando error rate > 5% em 5 min (via Telegram ou Discord)
☐Alerta quando custo diario > budget definido no .env
☐Health check endpoint que retorna status do app e dos providers
☐Testar disparando um erro artificial e verificando que o alerta chega

Criterios de Sucesso

☐ Logs em JSON com correlation ID no stdout
☐ Cada request de IA registra tokens e custo no DB
☐ Dashboard mostra custo por usuario e por dia
☐ Alerta dispara quando error rate passa de 5%
☐ Health check endpoint responde com status 200
☐ Nenhum dado sensivel (prompts, PII) nos logs

πŸ“‹ Resumo do Modulo

Logue metadata, nao conteudo - Tokens, latencia, custo, modelo, status. Nunca prompts completos ou PII em logs operacionais.
Structured logging e inegociavel - JSON, log levels, correlation IDs. Pino para performance, Winston para flexibilidade. Nada de console.log em producao.
Tokens sao a nova unidade de custo - Track por request, por usuario, por dia. P50/P95 de latencia revelam problemas antes do usuario reclamar.
Alertas acionaveis, nao ruidosos - Error spikes, cost anomalies, latency degradation. Canais certos para severidades certas.
Debugging de IA exige novas tecnicas - Prompt versioning, A/B testing, conversation replay, eval sets. Ferramentas como LangSmith e Helicone ajudam.
Observabilidade transforma operacao cega em operacao informada - Com logs, metricas e alertas, voce sabe o que esta acontecendo no seu SaaS 24/7.