ai-machine-learning

Melhores Práticas de Logs de LLM: 9 Regras que Seguimos em Produção [2026]

Escrito por Mert Batur
Aug 2, 2026
17 min de leitura
Melhores Práticas de Logs de LLM: 9 Regras que Seguimos em Produção [2026]

Melhores Práticas de Logs de LLM: 9 Regras que Seguimos em Produção [2026]

Estas nove melhores práticas de logs de LLM são as regras que nosso stack de produção realmente executa: registramos 1,2 milhão de requests de LLM por mês em quatro serviços, e cada um deles chega ao Grafana Loki como uma única linha JSON com model, tokens, latency, cost_usd e trace_id. O structlog 25.4.0 escreve o registro, o Presidio remove o PII antes, e o pipeline inteiro é a metade de logging do nosso stack de observabilidade.

Principais Aprendizados

  • Registre cada request de LLM como JSON estruturado com 14+ campos nomeados, nunca como texto livre.
  • Anonimize o PII antes da escrita do log com Presidio ou equivalente, não depois.
  • Anexe os atributos das convenções semânticas GenAI do OpenTelemetry a cada trace.
  • Com 1M de requests/dia, os mesmos 60GB custam US$ 108/mês no Datadog, US$ 30 no Loki e US$ 1,20 no ClickHouse.

O que Realmente Significa Logging de LLM (e Por que "Logar Tudo" Não Funciona)

Logging de LLM significa capturar um registro estruturado de cada request e response de modelo: o prompt, o completion, as contagens de tokens, a latência, o custo e o trace que conecta tudo a uma sessão de usuário. Não é logging de infraestrutura. CPU, memória e reinicializações de pod pertencem ao seu stack de métricas; este post cobre apenas o registro no nível do request que permite depurar, custear e auditar o comportamento do modelo.

O instinto de "logar tudo" é difícil de matar, e sai caro. Prompts e completions inteiros com 1M de requests por dia produzem cerca de 60GB de texto por mês, e uma parte desse texto é PII de clientes que você agora está armazenando indefinidamente. O princípio de minimização de dados do Artigo 5 do GDPR exige que os dados pessoais sejam "adequados, relevantes e limitados ao necessário", e um despejo bruto de prompts falha nesse teste já no primeiro dia. Logar tudo não é estratégia; é um passivo com fatura mensal.

Quais São as 9 Regras de Logging de LLM?

Nove regras, na ordem em que as implementaríamos: registre prompts e responses completos com identificadores em hash, emita JSON estruturado, capture tokens e custo por request, anexe o contexto de trace do OpenTelemetry, anonimize o PII antes da escrita, faça amostragem em alto volume, defina camadas de retenção, separe eventos de segurança e torne o resultado consultável. Cada uma abaixo vem com o código ou a tabela que a aplica.

Regra 1: Registre o Prompt e o Response Completos (Com Hashes, Não PII Bruto)

Registre o prompt completo e o completion completo de cada request, porque logs parciais são o que leva você a ficar encarando um incidente sem nenhum registro do que o modelo realmente viu. A única exceção é a identidade: nunca escreva IDs de usuário, e-mails ou nomes brutos no registro. Em vez disso, armazene um hash SHA-256 do ID do usuário. Um hash ainda permite reconstruir o histórico completo de sessão de um usuário com uma consulta offline, enquanto a linha de log em si permanece inútil para quem não deveria lê-la. A mesma lógica vale para system prompts: faça o hash deles, registre o hash e guarde o texto puro no seu registro de prompts, onde ele já tem controle de versão.

Regra 2: Use JSON Estruturado: Todos os Campos Nomeados, Nada de Texto Livre

Para melhores práticas de logs de LLM em Python ou qualquer outra linguagem, logs estruturados em JSON são a regra inegociável: todos os campos nomeados, tipados e consultáveis, nada despejado como string formatada. Uma linha de texto livre como INFO called gpt-4o, took 812ms só pode ser encontrada com grep. Um registro JSON pode ser agregado por modelo, somado por custo e juntado a um trace. As próprias práticas recomendadas de produção da OpenAI defendem a mesma ideia: capture metadados estruturados na camada do SDK, não com instruções print.

Aqui está o schema que cada serviço da Techsy emite, catorze campos:

json
{
  "request_id": "req_01J9XK4M7Q",
  "timestamp": "2026-07-18T09:24:31.482Z",
  "environment": "production",
  "model": "claude-sonnet-4-20250514",
  "prompt_tokens": 1284,
  "completion_tokens": 396,
  "latency_ms": 812,
  "cost_usd": 0.0098,
  "system_prompt_hash": "sha256:9f2c1a4e...",
  "user_id_hash": "sha256:b7e4d831...",
  "rag_sources": ["kb/pricing-2026.md", "kb/refund-policy.md"],
  "guardrail_result": "pass",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7"
}

Três campos merecem uma nota. cost_usd é calculado no momento do request a partir das contagens de tokens e da tarifa publicada do modelo, nunca preenchido depois por um job noturno. Os dois campos de hash são o compromisso da Regra 1: correlacionáveis offline, opacos no log. E trace_id e span_id são valores do trace-context do W3C, que é exatamente o assunto da Regra 4.

Se quatro serviços chamando provedores diretamente parecem quatro lugares para instrumentar, um proxy LiteLLM centraliza isso: um hook de logging na frente de cada provedor.

Regra 3: Capture Contagens de Tokens e Custo por Request

O rastreamento de uso de tokens pertence à própria linha de log, não a um job de data warehouse que roda amanhã. Todo provedor retorna as contagens de tokens de entrada e saída no response; multiplique pela tarifa por token do modelo naquele exato momento e escreva cost_usd no registro. Tarifas mudam e diferem entre tokens de entrada em cache e novos, então calcular o custo depois com uma tabela de preços estática reescreve a história silenciosamente. Com o custo em cada linha, "qual feature é cara?" vira uma consulta de uma linha em vez de um projeto financeiro, e alimenta diretamente o trabalho de reduzir seus custos de API de LLM.

Regra 4: Anexe o Contexto de Trace (Semconv GenAI do OpenTelemetry)

Uma linha de log sem trace ID é órfã: você consegue lê-la, mas não consegue dizer qual retry, qual etapa de RAG ou qual turno do usuário a produziu. A solução são as convenções semânticas GenAI do OpenTelemetry, os nomes de atributos padrão para instrumentar chamadas de modelo. Emita o log dentro de um span ativo e o trace_id e o span_id se anexam sozinhos, de modo que um clique no Grafana leva você da cascata do trace direto ao registro bruto.

Os atributos que valem a pena definir em todo span gen_ai:

AtributoTipoExemploFinalidade
gen_ai.systemstring"anthropic"Nome do provedor
gen_ai.request.modelstring"claude-sonnet-4-20250514"Modelo que você pediu
gen_ai.response.modelstring"claude-sonnet-4-20250514"Modelo que realmente respondeu
gen_ai.usage.input_tokensint1284Tamanho do prompt
gen_ai.usage.output_tokensint396Tamanho do completion
gen_ai.response.finish_reasonsstring[]["stop"]Por que a geração terminou
gen_ai.response.idstring"msg_01XK9..."ID do response do provedor
python
from opentelemetry import trace

tracer = trace.get_tracer("ai-sdr")

with tracer.start_as_current_span("chat.completion") as span:
    span.set_attribute("gen_ai.system", "anthropic")
    span.set_attribute("gen_ai.request.model", "claude-sonnet-4-20250514")
    response = client.messages.create(**payload)
    span.set_attribute("gen_ai.usage.input_tokens", response.usage.input_tokens)
    span.set_attribute("gen_ai.usage.output_tokens", response.usage.output_tokens)
    span.set_attribute("gen_ai.response.finish_reasons", [response.stop_reason])
    log.info("llm.request", cost_usd=cost)  # Rule 2 record, trace IDs auto-attached

Regra 5: Anonimize o PII Antes da Escrita do Log

A anonimização de PII precisa acontecer antes de o registro ser escrito, não ser raspada depois. Quando um endereço de e-mail está no Loki, ele também está nos seus backups de object storage, e "nós apagamos depois" não é uma resposta aceitável para o GDPR. No nosso setup, o Microsoft Presidio roda como um processor do structlog e captura 94% dos e-mails e números de telefone antes de chegarem ao Loki; os que escapam são quase todos de formatação estranha, que vamos corrigindo em recognizers personalizados conforme encontramos.

O hook inteiro tem quinze linhas:

python
from presidio_analyzer import AnalyzerEngine
from presidio_anonymizer import AnonymizerEngine

analyzer = AnalyzerEngine()
anonymizer = AnonymizerEngine()

PII_ENTITIES = ["PERSON", "EMAIL_ADDRESS", "PHONE_NUMBER", "CREDIT_CARD", "IBAN_CODE"]

def redact_pii(text: str) -> str:
    results = analyzer.analyze(text=text, language="en", entities=PII_ENTITIES)
    return anonymizer.anonymize(text=text, analyzer_results=results).text

# In the structlog processor chain, before JSONRenderer:
# event_dict["prompt"] = redact_pii(event_dict["prompt"])

A anonimização fica na mesma camada do pipeline que seus filtros de entrada e saída, e deve ser testada do mesmo jeito. Nosso pipeline de guardrails trata um e-mail vazado em um log como uma eval falha, não uma nota de rodapé de operações.

Regra 6: Faça Amostragem Inteligente em Alto Volume

Abaixo de cerca de 100 mil requests por dia, registre tudo. Acima disso, logging em volume total é um imposto de armazenamento sobre dados que você nunca vai ler, e amostragem é como você mantém os registros que importam. A pegadinha: amostragem aleatória é a pior opção para tráfego de LLM, porque falhas, recusas e requests de cinco dólares são raros por definição, então uma taxa uniforme de 10% descarta exatamente os eventos que você depura. Amostre por resultado, não por cara ou coroa.

EstratégiaQuando UsarComplexidade
Aleatória (10% fixo)Métricas de volume basais com tráfego estávelBaixa
Baseada em regrasSempre manter modelos, tenants ou rotas específicasBaixa
Baseada em cauda (tail)Manter requests lentos, caros ou com erro; descartar os normaisMédia
Baseada em gatilhoContexto completo só quando um guardrail dispara ou uma eval falhaMédia
AdaptativaA taxa de amostragem sobe e desce com o volume de tráfegoAlta

Um setup comum é baseada em regras nas bordas (produção e tenants enterprise: sempre logar) mais baseada em cauda no meio. O ângulo específico de logs neste framework: seus campos guardrail_result e cost_usd são os sinais de amostragem, já presentes se você seguiu as Regras 2 e 8.

Regra 7: Defina uma Política de Retenção Antes de Precisar Dela

Uma política de retenção de logs é uma decisão que você toma enquanto está calmo, porque a alternativa é tomá-la durante uma revisão de custos com o dobro do volume. O princípio de limitação de armazenamento do Artigo 5 do GDPR diz que dados pessoais devem ser mantidos "por não mais tempo que o necessário", o que na prática significa retenção em camadas:

CamadaRetençãoArmazenamentoCaso de Uso
Hot7 diasDisco local do Loki / ClickHouseDepuração ao vivo, consultas de plantão
Warm30 diasÍndice em object storage (S3)Análise de custo de sprint, revisão de incidentes
Cold1 anoArquivo compactado em S3/GCSSolicitações de compliance, auditorias anuais

Hot responde "o que aconteceu dez minutos atrás?" rápido e caro; cold responde "o que dissemos a este cliente em março?" devagar e barato. Apague no prazo, automaticamente, ou as camadas são apenas um diagrama.

Regra 8: Registre Eventos de Guardrail e Segurança Separadamente

Eventos de segurança (bloqueios de guardrail, recusas, violações de política) não são telemetria; são registros de auditoria e pertencem ao seu próprio stream. Três razões. Alertas: um pico em injeções de prompt bloqueadas deveria chamar alguém, e você não consegue calibrar esse alerta contra 1M de linhas rotineiras. Retenção: o compliance pode exigir que registros de segurança sobrevivam aos logs de depuração por anos. Acesso: auditores recebem o stream de segurança, não seu firehose inteiro. Marque o veredito no registro principal (guardrail_result: "block") e roteie o registro completo para o stream separado. O que conta como evento de segurança está coberto no nosso guia de eventos de guardrail.

Regra 9: Torne os Logs Consultáveis, Não Apenas Armazenados

Um log que você não consegue consultar em menos de um minuto é um backup, não um sinal de observabilidade. Consultável significa campos indexados, uma linguagem de consulta que seu plantonista realmente conhece e dashboards construídos antes do incidente. Rodamos Loki e o consultamos mais de 30 vezes por semana para anomalias de custo, regressões de latência e "me mostre todas as recusas do tenant X ontem". A documentação do Grafana Loki é a referência para a sintaxe; o padrão que se paga é filtrar diretamente nos campos JSON parseados:

logql
{service="ai-sdr"} |= "llm.request" | json
  | model = "claude-sonnet-4-20250514"
  | cost_usd > 0.05
  | line_format "{{.timestamp}} {{.request_id}} ${{.cost_usd}} {{.latency_ms}}ms"

Cinco linhas, sem exportar para um notebook. Se seu armazenamento atual não consegue fazer isso, ele é o problema a corrigir primeiro.

O que Realmente Registramos em Produção

Chega de teoria. Aqui está a configuração anonimizada do nosso pipeline de AI SDR, o serviço por trás do número de 1,2M de requests por mês da introdução. Ele roda structlog 25.4.0 renderizando JSON, enviado ao Grafana Cloud Loki via Promtail. O modelo neste pipeline é o claude-sonnet-4-20250514, e cada chamada passa exatamente pela cadeia de processors das Regras 2 e 5:

python
import structlog

structlog.configure(
    processors=[
        structlog.contextvars.merge_contextvars,
        structlog.processors.add_log_level,
        structlog.processors.TimeStamper(fmt="iso"),
        redact_pii,          # Rule 5: Presidio, before serialization
        add_otel_trace_ids,  # Rule 4: trace_id + span_id from the active span
        structlog.processors.JSONRenderer(),
    ],
)
log = structlog.get_logger()

Dois números do primeiro trimestre com esse setup. A ingestão mensal se estabilizou em 47GB nos quatro serviços, e a latência p95 de escrita de log é 3ms, o que significa que o pipeline não adiciona nada mensurável ao tempo do request.

A mudança de configuração que se pagou: adicionamos cost_usd a cada entrada de log em março de 2026. Em uma semana encontramos um template de prompt queimando US$ 340/mês em loops de retry. Um erro transitório de API disparava três retries, cada um reenviando o contexto completo de 4.000 tokens. Os logs tornaram isso uma consulta de uma linha; sem o custo por request, teria aparecido como um item inexplicado na próxima revisão orçamentária trimestral.

Quanto Custa o Armazenamento de Logs de LLM em Escala?

Com 1M de requests por dia, o armazenamento de logs de LLM custa entre aproximadamente US$ 1,20 e US$ 108 por mês pelos mesmos dados, dependendo do armazenamento. A conta: um registro estruturado completo tem em média cerca de 2KB, então 1M de requests por dia são 2GB por dia, ou 60GB por mês. Os preços publicados pelos fornecedores abaixo (julho de 2026) são o que esses 60GB custam em três backends comuns.

BackendModelo de Preço (publicado pelo fornecedor, julho de 2026)60GB/MêsObservações
Datadog LLM Observability$0,10/GB ingerido + $1,70/GB indexado~US$ 108A indexação é a linha cara
Grafana Cloud Loki~$0,50/GB via object storage~US$ 30Ainda mais barato com self-host
ClickHouse (self-host, S3)~$0,02/GB em armazenamento compactado~US$ 1,20 + computaçãoA computação é o custo real

Fontes: preços do Datadog, Grafana Loki e a documentação de observabilidade do ClickHouse.

Duas ressalvas, porque este é o nosso cálculo a partir das tarifas dos fornecedores, não um benchmark que rodamos. Primeiro, o número do Datadog supõe que você indexa tudo; a maioria das equipes indexa um subconjunto e paga bem menos, enquanto Loki e ClickHouse cobram principalmente pelo que você armazena. Segundo, os US$ 1,20 do ClickHouse self-host escondem uma conta real: a computação para rodar o cluster e as horas de engenharia para operá-lo. Com 60GB por mês, um serviço gerenciado é quase sempre a resposta mais barata no total. Self-host começa a fazer sentido acima de aproximadamente 1TB por mês, onde a diferença por GB supera o overhead operacional.

A diferença é a lição. Com 1M de requests por dia, o abismo entre Datadog indexado e ClickHouse self-host é de aproximadamente 90x: US$ 108 contra US$ 1,20 pelos mesmos 60GB. Escolha o armazenamento na hora da arquitetura, não depois que a fatura chega.

Qual Ferramenta de Logging Você Deve Escolher?

Para a maioria das equipes, a escolha se resume a quatro opções: uma plataforma nativa de LLM (Langfuse ou LangSmith), uma ferramenta de camada de proxy (Helicone) ou um pipeline simples de OpenTelemetry na infraestrutura que você já roda. A tabela cobre os pontos de decisão que realmente diferem; dashboards, playback e versionamento de prompts são requisitos básicos nas quatro.

LangfuseLangSmithHeliconeOTel nativo (Loki/ClickHouse)
Self-host possívelSim (core open-source)Não (SaaS)Sim (open-source)Totalmente
Compatível com OTelSim (ingest OTLP)Parcial (export OTLP)ParcialNativo
Rastreamento de custoSimSimSimDIY (calcule cost_usd você mesmo)
Anonimização de PII embutidaNão (pré-processe)NãoNãoNão (Presidio, pela Regra 5)
Plano gratuitoSim (cloud + self-host)Sim (limitado)SimSoftware gratuito; você paga a infra

Nossa opinião, sem rodeios: rodamos OTel nativo mais Loki porque já tínhamos o stack Grafana para todo o resto, e adicionar mais uma fonte de dados venceu adotar um quarto fornecedor. Se você está começando do zero sem nenhum stack de observabilidade, o modelo de tracing do Langfuse e seu plano gratuito são o caminho mais rápido até algo útil, e a opção de self-host mantém a porta de saída aberta. Se está escolhendo entre os dois líderes nativos de LLM, nosso comparativo Langfuse vs LangSmith faz a comparação completa. E se o logging é uma peça de uma decisão maior de monitoramento, a comparação completa de plataformas cobre o campo mais amplo.

Quais São os Erros Mais Comuns de Logging de LLM?

Seis erros respondem pela maior parte dos setups quebrados de logging de LLM que já examinamos. Cada um é barato de evitar se você o pega antes que o volume de logs pegue:

  • Logar PII bruto sem anonimização. O mais comum e o mais caro. Uma exportação de suporte ou um bucket violado transforma logs de prompts em um incidente de proteção de dados. Anonimize antes da escrita (Regra 5), não na leitura.
  • Nenhuma política de retenção. Armazenamento indefinido é o padrão em todo lugar, e ele dobra silenciosamente sua fatura todo ano. Se você nunca apaga, você não tem um sistema de logging; tem um arquivo com delírios de grandeza.
  • Logs de texto não estruturado. Saída de print que só pode ser encontrada com grep funciona em escala de demo e colapsa com 100 mil requests por dia, quando "encontre cada request com falha do modelo X" vira uma tarde de script shell em vez de uma consulta.
  • Logar apenas erros. Requests bem-sucedidos são a linha de base contra a qual você detecta desvios, e são a matéria-prima do seu pipeline de avaliação. Registre os acertos também, com amostragem se o volume obrigar.
  • Ignorar campos de custo. Sem cost_usd por request não há alertas de custo, nem atribuição por feature, e o loop de retry de US$ 340/mês da seção de produção acima permanece invisível até a fatura trimestral.
  • Sem correlação de traces. Logs desconectados de spans tornam a depuração de agentes multi-etapas um jogo de adivinhação. Se sua linha de log não tem trace_id, a Regra 4 é a correção.

Sobre o Autor

Mert Batur é Co-Fundador da Techsy.io, onde a equipe entrega agentes de IA, sistemas de automação e pipelines de voz/SDR para clientes B2B. Ele escreve sobre o stack de ferramentas de LLM que a equipe da Techsy realmente usa em produção. Conecte-se no LinkedIn.

Perguntas Frequentes

O que você deve registrar para cada request de LLM?

No mínimo: o prompt e o completion completos com PII anonimizado, o nome do modelo, as contagens de tokens de entrada e saída, a latência, o custo em USD, um identificador de usuário em hash e os IDs de trace e span do OpenTelemetry. Adicione os IDs de origem do RAG e o veredito do guardrail se seu pipeline tem esses estágios. Catorze campos nomeados, uma linha JSON por request.

Qual é o melhor formato para logs de LLM?

JSON estruturado, um objeto por request, com cada campo explicitamente nomeado. Logs de texto livre só podem ser buscados com grep; registros JSON podem ser agregados por modelo, somados por custo e juntados a traces. Emita o registro com um logger estruturado como structlog em Python ou pino em Node, e renderize com um serializador JSON, nunca com formatação de strings.

Como lidar com PII em logs de LLM?

Anonimize antes da escrita do log, não depois. Passe o prompt e o completion por um detector como o Microsoft Presidio dentro do seu pipeline de logging, substituindo nomes, e-mails e números de telefone por tokens como <EMAIL_ADDRESS>. Quando PII bruto chega ao seu armazenamento de logs, ele também está nos seus backups, e a exclusão retroativa raramente satisfaz o teste de minimização do GDPR.

Quanto custa o armazenamento de logs de LLM em escala?

Para 1M de requests por dia, cerca de 60GB por mês com 2KB por registro, espere aproximadamente US$ 108/mês no preço indexado do LLM Observability do Datadog, US$ 30/mês no Grafana Cloud Loki ou cerca de US$ 1,20/mês em armazenamento S3 compactado para ClickHouse self-host mais computação. Essas são as tarifas publicadas pelos fornecedores em julho de 2026; self-host adiciona tempo de engenharia por cima.

O que são as convenções semânticas GenAI do OpenTelemetry?

São os nomes de atributos padrão do OpenTelemetry para instrumentar chamadas de LLM: gen_ai.system para o provedor, gen_ai.request.model para o modelo, gen_ai.usage.input_tokens e output_tokens para as contagens de tokens e gen_ai.response.finish_reasons para o motivo pelo qual a geração parou. Usá-las significa que qualquer backend compatível com OTel, do Jaeger ao Tempo passando pelo Langfuse, lê seus traces sem parsers customizados.

Como fazer amostragem de logs de LLM com tráfego alto?

Mantenha cada erro, cada bloqueio de guardrail e cada request acima de um limite de custo, depois amostre o resto. Essa abordagem baseada em cauda preserva os eventos raros que você realmente depura, enquanto a amostragem aleatória uniforme os descarta na mesma taxa que o tráfego banal. Abaixo de 100 mil requests por dia, pule a amostragem por completo e registre tudo.

Por quanto tempo você deve reter logs de LLM?

Em camadas: 7 dias hot para depuração ao vivo, 30 dias warm para revisão de incidentes e análise de custo e até 1 ano cold em object storage compactado para compliance e auditorias. O princípio de limitação de armazenamento do GDPR proíbe manter dados pessoais por mais tempo que o necessário, então combine cada camada com exclusão automática, não limpeza manual.

Qual é a diferença entre logging de LLM e tracing de LLM?

Um log é um registro plano de um evento: este request aconteceu, com estes campos. Um trace é uma árvore causal de spans ao longo de todo o caminho de um request, digamos retrieval, depois a chamada do modelo, depois duas chamadas de ferramentas. Logs dizem o quê; traces dizem onde e por quê. Setups de produção emitem ambos, unidos pelo trace_id.

Conclusão

Recapitulando: registre cada request como JSON com campos nomeados, calcule o custo no momento do request, anexe o contexto de trace do OTel, anonimize o PII antes da escrita, faça amostragem por resultado depois de passar de 100 mil requests por dia e escolha um armazenamento que você realmente consiga consultar. As nove regras estão ordenadas para que você possa adotar uma por sprint, e as Regras 2, 4 e 5 são as três que se pagam mais rápido. Se você está escolhendo o stack de monitoramento mais amplo ao redor dos logs, comece pelo nosso resumo das melhores plataformas de observabilidade de IA. E se precisa de ajuda para configurar logs estruturados no seu stack de LLM, receba uma consultoria gratuita.

Etiquetas

melhores práticas de logs de llmlogs estruturadosopentelemetry genaianonimização de piiobservabilidade de llmretenção de logs

Partilhar este artigo

Inicia o Teu Projeto

Pronto para criar algo extraordinário?

Vamos transformar a sua visão em realidade. A nossa equipa está pronta para o ajudar a criar software que faz a diferença.