Depois de configurar o Prometheus para métricas e o Grafana para dashboards, ainda faltava uma peça. Os logs.
Ao longo dos anos fui enviando logs para sítios diferentes. Uma tabela de base de dados no início, depois o Azure Application Insights, depois um cluster Elasticsearch gerido. Cada vez, o setup funcionava mas trazia trade-offs que continuei a aceitar sem questionar. O Elasticsearch em particular é poderoso, mas também é caro e pesado de operar para o que a maioria das aplicações realmente precisa dos logs.
O Loki é a resposta que gostaria de ter encontrado mais cedo.
O Que Torna o Loki Diferente
A maioria dos sistemas de agregação de logs indexa o conteúdo completo de cada linha de log. O Elasticsearch faz isso. Esse indexing é o que torna as pesquisas rápidas, mas também torna a ingestão cara e o armazenamento grande. Acabas a pagar por pesquisa de texto completo em logs que pesquisas talvez uma vez por mês.
O Loki tem uma abordagem diferente. Indexa apenas as labels associadas a um stream de logs, não o conteúdo do log em si. O texto dos logs é armazenado comprimido e só é lido quando fazes query. Isto torna o Loki dramaticamente mais barato de correr e mais simples de operar. O trade-off é que filtrar por conteúdo de log requer scanning, não lookups de índice. Na prática, para a maioria dos workloads, isto é completamente aceitável.
O modelo mental é o mesmo do Prometheus. As labels identificam um stream, o conteúdo é o payload. Se já percebes como funcionam as labels do Prometheus, o Loki faz sentido imediatamente.
Configuração com .NET
Numa aplicação .NET, o Serilog é a biblioteca de logging que uso. Ligá-lo ao Loki requer um package e algumas linhas de configuração.
dotnet add package Serilog.Sinks.Grafana.LokiLog.Logger = new LoggerConfiguration()
.WriteTo.GrafanaLoki("http://localhost:3100",
labels: new[] {
new LokiLabel { Key = "app", Value = "my-api" },
new LokiLabel { Key = "env", Value = "production" }
})
.CreateLogger();Essas labels são como o Loki identifica o stream. Cada linha de log desta aplicação será etiquetada com app=my-api e env=production. Podes depois consultar todos os logs para essa app, ou filtrar por ambiente, sem tocar no conteúdo dos logs.
Mantém as labels com baixa cardinalidade. Não uses IDs de pedido ou IDs de utilizador como labels. Esses pertencem à linha de log em si, não como identificadores de stream. Labels com alta cardinalidade criam demasiados streams e prejudicam a arquitetura do Loki.
LogQL é Direto
A linguagem de query do Loki chama-se LogQL. Tem dois modos: queries de log que retornam linhas de log, e queries de métricas que transformam dados de log em números (útil para contar erros ao longo do tempo, por exemplo).
Uma query básica tem este aspeto:
{app="my-api", env="production"} |= "Exception"As chavetas selecionam o stream por label. O pipe filtra linhas de log que contêm a palavra "Exception". Isso cobre a maior parte do que precisas no dia a dia.
Também podes extrair campos de logs estruturados:
{app="my-api"} | json | status_code >= 500Se a tua aplicação fizer log em JSON (o que deveria), o Loki consegue fazer parse dos campos em tempo real e deixar-te filtrar por eles sem qualquer pre-indexing. Isto é genuinamente útil e algo para o qual o Elasticsearch precisaria de mapeamentos de índice.
A Ligação ao Grafana
No Grafana, adicionas o Loki como fonte de dados a par do Prometheus. A partir daí, podes construir painéis que combinam ambos. Um dashboard a mostrar a taxa de erros das métricas Prometheus e as linhas de log de erro reais do Loki no mesmo ecrã é algo que uso regularmente. Vês o pico na métrica e saltas imediatamente para os logs daquela janela temporal sem mudar de ferramenta.
O Grafana tem também uma funcionalidade chamada Explore que é basicamente uma interface de query em bruto para Prometheus e Loki. Uso-a constantemente ao fazer debugging. Mudas entre métricas e logs na mesma vista, correlacionas timestamps, e passas de "algo correu mal às 14:32" para "aqui está o stack trace exato" em poucos cliques.
Comparado com o Que Usava Antes
O Application Insights também faz logs. É aceitável. Mas é exclusivo do Azure, fica caro em volume, e a linguagem de query (Kusto) é algo que tinha sempre de consultar em vez de saber de cor.
O Elasticsearch gerido que usei num projeto custava mais por mês do que toda a restante infraestrutura. Era rápido e a pesquisa de texto completo era poderosa, mas a maior parte dessa potência nunca era usada. Pesquisávamos logs por nome de serviço, intervalo de tempo e nível de erro. O Loki trata de tudo isso facilmente a uma fração do custo.
Correr o Loki tu mesmo é simples. É um único binário ou um contentor Docker. O armazenamento pode ser disco local ou object storage como S3 ou Azure Blob. Para o workload de produção de uma equipa pequena, podes corrê-lo por quase nada.
O Quadro Completo
Com Prometheus, Loki e Grafana juntos, tens o stack de observabilidade completo. As métricas dizem-te que algo está errado. Os logs dizem-te exatamente o que aconteceu. O Grafana liga os dois num só lugar.
Nada disto está ligado a um fornecedor de cloud específico. Os três são open source. Os teus dashboards, as tuas regras de alerta, as tuas queries de logs são portáteis. Isso importa mais do que parece quando estás a configurar, e importa muito quando algo muda mais tarde.
Se já migraste para Prometheus e Grafana, adicionar o Loki é o próximo passo natural. Fecha o ciclo.



