O Grafana Loki é um sistema de agregação de logs altamente disponível e escalável horizontalmente. Ele é projetado para simplicidade e eficiência de custos. Criado pela Grafana Labs em 2018, o Loki rapidamente se tornou uma alternativa interessante aos sistemas tradicionais de registro, especialmente para ambientes nativos de nuvem e Kubernetes.
O Loki pode fornecer uma jornada de log abrangente. Podemos selecionar os fluxos de log corretos e, em seguida, filtrar para nos concentrarmos nos logs relevantes. Podemos então analisar dados de log estruturados para serem formatados de acordo com nossas necessidades de análise personalizadas. Os logs também podem ser transformados adequadamente para apresentação, por exemplo, ou para processamento adicional em pipeline.
O Loki se integra perfeitamente com o amplo ecossistema Grafana. Os usuários podem consultar logs usando LogQL – uma linguagem de consulta projetada intencionalmente para se assemelhar ao PromQL do Prometheus. Isso proporciona uma experiência familiar para usuários que já trabalham com métricas do Prometheus e permite uma correlação poderosa entre métricas e logs nos painéis do Grafana.
Este artigo começa com os fundamentos do Loki, seguido por uma visão arquitetônica básica. Os conceitos básicos do LogQL seguem, e concluímos com as compensações envolvidas.
Fundamentos do Loki
Para organizações que gerenciam sistemas complexos, Loki oferece uma solução unificada de registro. Ele suporta a ingestão de logs de qualquer fonte por meio de uma ampla variedade de agentes ou sua API, garantindo cobertura abrangente de hardware e software diversos. O Loki armazena seus logs como fluxos de log, conforme mostrado no Diagrama 1. Cada entrada possui o seguinte:
- Um timestamp com precisão de nanossegundos
- Pares de chave-valor chamados rótulos são usados para buscar logs. Os rótulos fornecem os metadados para a linha de log. Eles são utilizados para a identificação e recuperação de dados. Eles formam o índice para os fluxos de log e estruturam o armazenamento de logs. Cada combinação única de rótulos e seus valores define um fluxo de log distinto. As entradas de log dentro de um fluxo são agrupadas, compactadas e armazenadas em segmentos.
- O conteúdo real do log. Esta é a linha de log bruta. Não é indexada e é armazenada em blocos compactados.
Arquitetura
Vamos analisar a arquitetura do Loki com base em três características básicas. Ler, escrever e armazenar logs. O Loki pode operar em modo monolítico (binário único) ou em modo de microsserviços, onde os componentes são separados para escalonamento independente. A funcionalidade de leitura e escrita pode ser escalada de forma independente para atender a casos de uso específicos. Vamos considerar cada caminho com mais detalhes.
Escrevendo
No Diagrama 2, o caminho de escrita é o caminho verde. Conforme os logs entram no Loki, o distribuidor divide os logs com base em rótulos. O ingester então armazena os logs na memória, e o compactador otimiza o armazenamento. Os principais passos envolvidos são os seguintes.
Passo 1: Logs Entram no Loki
As escritas para os logs recebidos chegam ao distribuidor. Os logs são estruturados como fluxos, com rótulos (como {job="nginx", level="error"}
). O distribuidor divide os logs, particiona-os e envia os logs para os ingesters. Ele faz o hash dos rótulos de cada fluxo e os atribui a um ingester usando hashing consistente. Os distribuidores validam os logs e impedem dados malformados. O hashing consistente pode garantir uma distribuição uniforme de logs entre os ingesters.
Passo 2: Armazenamento de Curto Prazo
O ingester armazena os logs na memória para rápida recuperação. Os logs são agrupados e gravados em Write-Ahead Logs (WAL) para evitar perda de dados. O WAL ajuda na durabilidade, mas não é diretamente consultável – os ingesters ainda precisam permanecer online para consultar logs recentes.
Periodicamente, os logs são descarregados dos ingesters para o armazenamento de objetos. O questionador e o governante leem o ingester para acessar os dados mais recentes. O questionador também pode acessar os dados de armazenamento de objetos.
Passo 3: Logs São Movidos para Armazenamento de Longo Prazo
O compactador processa periodicamente logs armazenados do armazenamento de longo prazo (object-storage
). O armazenamento de objetos é barato e escalável. Isso permite que o Loki armazene grandes quantidades de logs sem altos custos. O compactador remove logs redundantes, comprime logs para eficiência de armazenamento e exclui logs antigos com base nas configurações de retenção. Os logs são armazenados em formato segmentado (não indexado em texto completo).
Leitura
No Diagrama 2, o caminho de leitura é o caminho azul. As consultas vão para o frontend de consulta, e o consultor recupera os logs. Os logs são filtrados, analisados e analisados usando LogQL. Os principais passos envolvidos são os seguintes.
Passo 1: Frontend de Consulta Otimiza Solicitações
Os usuários consultam logs usando LogQL no Grafana. O frontend de consulta divide consultas grandes em pedaços menores e os distribui entre vários consultores, pois a execução paralela acelera as consultas. Ele é responsável por acelerar a execução da consulta e garantir tentativas novamente em caso de falha. O frontend de consulta ajuda a evitar expirações de tempo limite e sobrecargas, enquanto consultas falhadas são refeitas automaticamente.
Passo 2: Consultor Recupera Logs
Os consultores analisam o LogQL e consultam ingestores e armazenamento de objetos. Logs recentes são recuperados dos ingestores, e logs mais antigos são recuperados do armazenamento de objetos. Logs com o mesmo timestamp, etiquetas e conteúdo são deduplicados.
Filtros de Bloom e etiquetas de índice são usados para encontrar logs de forma eficiente. Consultas de agregação, como count_over_time()
, são mais rápidas porque o Loki não indexa completamente os logs. Ao contrário do Elasticsearch, o Loki não indexa o conteúdo completo do log.
Em vez disso, ele indexa rótulos de metadados ({app="nginx", level="error"}
), o que ajuda a encontrar logs de forma eficiente e econômica. Pesquisas de texto completo são realizadas apenas em partes relevantes dos logs, reduzindo os custos de armazenamento.
Fundamentos do LogQL
LogQL é a linguagem de consulta usada no Grafana Loki para buscar, filtrar e transformar logs de forma eficiente. Consiste em dois componentes principais:
- Selecionador de stream – Seleciona streams de logs com base em correspondências de rótulos
- Filtragem e transformação – Extrai linhas relevantes de logs, analisa dados estruturados e formata os resultados da consulta
Ao combinar esses recursos, o LogQL permite que os usuários recuperem logs de forma eficiente, extraiam insights e gerem métricas úteis a partir dos dados de log.
Selecionador de Stream
Um selecionador de stream é o primeiro passo em cada consulta LogQL. Ele seleciona streams de logs com base em correspondências de rótulos. Para refinar os resultados da consulta para streams de logs específicos, podemos empregar operadores básicos para filtrar por rótulos do Loki. Melhorar a precisão da nossa seleção de streams de logs minimiza o volume de streams escaneados, aumentando assim a velocidade da consulta.
Exemplos
{app="nginx"} # Selects logs where app="nginx"
{env=~"prod|staging"} # Selects logs from prod or staging environments
{job!="backend"} # Excludes logs from the backend job
Filtros de Linha
Uma vez que os logs são selecionados, os filtros de linha refinam os resultados buscando texto específico ou aplicando condições lógicas. Os filtros de linha funcionam no conteúdo do log, não nos rótulos.
Exemplos
{app="nginx"} |= "error" # Select logs from nginx that contain "error"
{app="db"} != "timeout" # Exclude logs with "timeout"
{job="frontend"} |~ "5\d{2}" # Match HTTP 500-series errors (500-599)
Parseadores
Loki pode aceitar logs não estruturados, semi-estruturados ou estruturados. No entanto, compreender os formatos de log com os quais estamos trabalhando é crucial ao projetar e construir soluções de observabilidade. Dessa forma, podemos ingerir, armazenar e analisar dados de log para serem usados de forma eficaz. Loki suporta analisadores JSON, logfmt, padrão, regexp e unpack.
Exemplos
{app="payments"} | json # Extracts JSON fields
{app="auth"} | logfmt # Extracts key-value pairs
{app="nginx"} | regexp "(?P<status>\d{3})" # Extracts HTTP status codes
Filtros de Etiquetas
Uma vez analisados, os logs podem ser filtrados por campos extraídos. As etiquetas podem ser extraídas como parte do pipeline de log usando expressões de analisador e formatador. A expressão do filtro de etiqueta pode então ser usada para filtrar nossa linha de log com uma dessas etiquetas.
Exemplos
{app="web"} | json | status="500" # Extract JSON, then filter by status=500
{app="db"} | logfmt | user="admin" # Extract key-value logs, filter by user=admin
Formato de Linha
Usado para modificar a saída de log, extraindo e formatando campos. Isso formata como os logs são exibidos no Grafana.
Exemplo
{app="nginx"} | json | line_format "User {user} encountered {status} error"
Formato de Etiqueta
Usado para renomear, modificar, criar ou eliminar etiquetas. Aceita uma lista separada por vírgulas de operações de igualdade, permitindo que múltiplas operações sejam realizadas simultaneamente.
Exemplos
1. {app="nginx"} | label_format new_label=old_label. #If a log has {old_label="backend"}, it is renamed to {new_label="backend"}. The original old_label is removed.
2. {app="web"} | label_format status="HTTP {{.status}}" #If {status="500"}, it becomes {status="HTTP 500"}.
3. {app="db"} | label_format severity="critical". #Adds {severity="critical"} to all logs.
4. {app="api"} | drop log_level # Drops log_level
Trade-Offs
Grafana Loki oferece uma solução de logística escalável e econômica que armazena logs em fragmentos compactados com indexação mínima. Isso vem com compensações no desempenho da consulta e na velocidade de recuperação. Ao contrário de sistemas tradicionais de gerenciamento de logs que indexam o conteúdo completo do log, a indexação baseada em etiquetas do Loki acelera a filtragem.
No entanto, isso pode retardar as buscas de texto complexo. Além disso, enquanto o Loki se destaca no manuseio de ambientes distribuídos de alto rendimento, ele depende do armazenamento de objetos para escalabilidade. Isso pode introduzir latência e requer uma seleção cuidadosa de rótulos para evitar problemas de alta cardinalidade.
Escalabilidade e Multilocação
O Loki é projetado para escalabilidade e multilocação. No entanto, a escalabilidade vem com compensações arquiteturais. Escalar gravações (ingesters) é direto devido à capacidade de fragmentar logs com base na partição baseada em rótulos. Escalar leituras (queriers) é mais complicado porque a consulta de grandes conjuntos de dados do armazenamento de objetos pode ser lenta. A multilocação é suportada, mas gerenciar cotas específicas do locatário, explosão de rótulos e segurança (isolamento de dados por locatário) requer uma configuração cuidadosa.
Ingestão Simples Sem Pré-Análise
O Loki não requer pré-análise porque não indexa o conteúdo completo do log. Ele armazena logs no formato bruto em blocos comprimidos. Como o Loki não possui indexação de texto completo, consultar logs estruturados (por exemplo, JSON) requer análise LogQL. Isso significa que o desempenho da consulta depende de quão bem os logs estão estruturados antes da ingestão. Sem logs estruturados, a eficiência da consulta é prejudicada porque a filtragem deve ocorrer no momento da recuperação, não na ingestão.
Armazenamento em Armazenamento de Objetos
O Loki envia blocos de logs para o armazenamento de objetos (por exemplo, S3, GCS, Azure Blob). Isso reduz a dependência de armazenamento de blocos caro como, por exemplo, o Elasticsearch requer.
No entanto, ler logs do armazenamento de objetos pode ser lento em comparação com a consulta direta a um banco de dados. O Loki compensa isso mantendo logs recentes em ingesters para recuperação mais rápida. A compactação reduz a sobrecarga de armazenamento, mas a latência na recuperação de logs ainda pode ser um problema para consultas em larga escala.
Rótulos e Cardinalidade
Uma vez que os rótulos são usados para buscar logs, eles são críticos para consultas eficientes. Roteamento inadequado pode levar a problemas de alta cardinalidade. O uso de rótulos de alta cardinalidade (por exemplo, user_id
, session_id
) aumenta o uso de memória e desacelera as consultas. O Loki faz hash dos rótulos para distribuir logs entre os ingesters, portanto, um mau design de rótulo pode causar uma distribuição desigual dos logs.
Filtrando Cedo
Como o Loki armazena logs brutos comprimidos em armazenamento de objetos, é importante filtrar cedo se quisermos que nossas consultas sejam rápidas. Processar análises complexas em conjuntos de dados menores aumentará o tempo de resposta. Segundo essa regra, uma boa consulta seria a Consulta 1, e uma má consulta seria a Consulta 2.
Consulta 1
{job="nginx", status_code=~"5.."} | json
A Consulta 1 filtra logs onde job="nginx"
e o status_code
começa com 5 (erros 500–599). Em seguida, extrai campos JSON estruturados usando | json
. Isso minimiza o número de logs processados pelo analisador JSON, tornando-o mais rápido.
Consulta 2
{job="nginx"} | json | status_code=~"5.."
A Consulta 2 primeiro recupera todos os logs do nginx
. Isso pode ser milhões de entradas. Em seguida, analisa JSON para cada entrada de log individual antes de filtrar por status_code
. Isso é ineficiente e significativamente mais lento.
Concluindo
Grafana Loki é um sistema poderoso e econômico de agregação de logs projetado para escalabilidade e simplicidade. Ao indexar apenas metadados, mantém os custos de armazenamento baixos, permitindo consultas rápidas usando o LogQL.
A sua arquitetura de microsserviços suporta implantações flexíveis, tornando-o ideal para ambientes nativos de nuvem. Este artigo abordou os conceitos básicos do Loki e da sua linguagem de consulta. Ao navegar pelas principais características da arquitetura do Loki, podemos ter uma melhor compreensão dos compromissos envolvidos.
Source:
https://dzone.com/articles/grafana-loki-fundamentals-and-architecture