Implementação de SLOs com Prometheus e Grafana: Um Tutorial Técnico Passo a Passo

A adoção de práticas de engenharia de Confiabilidade de Sites (SRE) transformou a maneira como as equipes de operações e desenvolvimento gerenciam a saúde e o desempenho de serviços. No centro dessa prática estão os Objetivos de Nível de Serviço (SLOs), que fornecem um framework quantitativo para definir e medir a confiabilidade. Implementar SLOs de forma eficaz requer ferramentas robustas para coleta, armazenamento e visualização de métricas. A combinação de prometheus e grafana emergiu como um padrão de mercado para essa finalidade, oferecendo uma solução de observabilidade poderosa e de código aberto.

Este artigo detalha o processo técnico de implementação de SLOs utilizando Prometheus para a coleta de métricas e definição de regras, e Grafana para a criação de dashboards de visualização e monitoramento. Abordaremos desde os conceitos fundamentais até a configuração de alertas proativos baseados no consumo do seu orçamento de erro (error budget).

Fundamentos Essenciais: SLI, SLO e Error Budget

Antes de mergulhar na implementação técnica, é crucial solidificar a compreensão dos três pilares que sustentam a gestão de confiabilidade baseada em SLOs.

SLI (Service Level Indicator)

Um Indicador de Nível de Serviço (SLI) é uma métrica quantitativa que mede um aspecto específico da performance ou disponibilidade de um serviço. Um bom SLI está diretamente relacionado à experiência do usuário. Ele deve ser mensurável, confiável e representar claramente a saúde do serviço. Exemplos comuns de SLIs incluem:

  • Disponibilidade: A proporção de requisições bem-sucedidas em relação ao total de requisições. Ex: (requisições com código HTTP 2xx) / (total de requisições).
  • Latência: O tempo que um serviço leva para responder a uma requisição. Geralmente medido em percentis, como o 95º ou 99º percentil (p95, p99), para excluir outliers extremos.
  • Taxa de Erros: A proporção de requisições que resultam em erro (ex: códigos HTTP 5xx) em relação ao total.
  • Throughput: O número de requisições por segundo que o sistema consegue processar.

SLO (Service Level Objective)

Um Objetivo de Nível de Serviço (SLO) é a meta definida para um SLI específico durante um período de tempo. Ele formaliza a expectativa de confiabilidade para os stakeholders. Um SLO bem definido é realista, alcançável e alinhado com as necessidades do negócio. A estrutura de um SLO é tipicamente: SLI <operador> META % durante PERÍODO.

Exemplos:

  • Disponibilidade: 99.9% das requisições ao endpoint /api/v1/users devem retornar um código HTTP não-5xx, medido ao longo de 28 dias.
  • Latência: 95% das requisições de escrita no banco de dados devem ser completadas em menos de 250ms, medido ao longo de 7 dias.

Error Budget

O Orçamento de Erro (Error Budget) é a consequência direta de um SLO. Ele representa a quantidade de tempo ou o número de eventos em que o serviço pode falhar sem violar o seu SLO. Matematicamente, é 100% - SLO. Por exemplo, um SLO de disponibilidade de 99.9% em um período de 28 dias (aproximadamente 40.320 minutos) concede um error budget de 0.1%, o que equivale a cerca de 40.3 minutos de indisponibilidade total permitida nesse período.

O error budget é uma ferramenta poderosa de gestão. Ele permite que as equipes de engenharia tomem decisões baseadas em dados sobre quando lançar novas features (consumindo o budget com o risco inerente) e quando focar em estabilidade e correções (para preservar ou reabastecer o budget).

Configurando o Ambiente com Prometheus e Grafana

Para nosso tutorial, usaremos Docker Compose para configurar rapidamente um ambiente local com Prometheus e Grafana. Crie um diretório para o projeto e adicione os seguintes arquivos:

docker-compose.yml:

version: '3.7'

services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    volumes:
      - ./prometheus/:/etc/prometheus/
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
    ports:
      - '9090:9090'

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - '3000:3000'
    depends_on:
      - prometheus

prometheus/prometheus.yml:

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # Adicione aqui o target da sua aplicação
  - job_name: 'my-app'
    static_configs:
      - targets: ['host.docker.internal:8080'] # Exemplo para uma app rodando na sua máquina

Execute docker-compose up -d para iniciar os contêineres. Você poderá acessar a UI do Prometheus em http://localhost:9090 e do Grafana em http://localhost:3000 (login padrão: admin/admin).

Definindo e Coletando SLIs com PromQL

O coração da implementação de SLOs é traduzir os indicadores de negócio em queries PromQL (Prometheus Query Language) precisas. Assumiremos que sua aplicação exporta métricas no formato do Prometheus, incluindo uma métrica de histograma para latência e um contador para requisições HTTP.

SLI de Disponibilidade baseado em Taxa de Sucesso

Vamos definir um SLI para a proporção de requisições que não resultam em erro do servidor (HTTP 5xx).

Métricas necessárias: http_requests_total (um contador com labels method, path, e code).

A query PromQL para calcular a taxa de requisições bem-sucedidas (não-5xx) nos últimos 5 minutos para o job `my-app` seria:

sum(rate(http_requests_total{job="my-app", code!~"5.."}[5m]))
/
sum(rate(http_requests_total{job="my-app"}[5m]))

Esta query calcula a taxa de crescimento das requisições não-5xx e a divide pela taxa de crescimento total de requisições, resultando em um rácio entre 0 e 1 que representa a disponibilidade atual.

SLI de Latência baseado em Percentil

Para latência, o ideal é usar um histograma. A métrica http_request_duration_seconds é um histograma que agrupa as durações das requisições em buckets.

Métricas necessárias: http_request_duration_seconds_bucket, http_request_duration_seconds_sum, http_request_duration_seconds_count.

Para calcular o 95º percentil (p95) da latência das requisições nos últimos 5 minutos, usamos a função histogram_quantile:

histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{job="my-app"}[5m])) by (le))

Esta query informa que 95% das requisições foram concluídas em um tempo menor ou igual ao valor retornado.

Otimizando com Recording Rules

Queries de SLO podem se tornar complexas e computacionalmente caras, especialmente em dashboards que são atualizados frequentemente. As Recording Rules no Prometheus permitem pré-calcular essas queries em um intervalo regular, armazenando o resultado como uma nova métrica. Isso melhora drasticamente o desempenho do Grafana.

Crie um arquivo prometheus/rules.yml:

groups:
- name: service_level_indicators
  interval: 1m
  rules:
  - record: job:http_requests:rate5m
    expr: sum(rate(http_requests_total{job="my-app"}[5m])) by (job)

  - record: job:http_successful_requests:rate5m
    expr: sum(rate(http_requests_total{job="my-app", code!~"5.."}[5m])) by (job)

  - record: job:sli_availability:ratio_rate5m
    expr: job:http_successful_requests:rate5m / job:http_requests:rate5m

  - record: job:sli_latency_p95:seconds_rate5m
    expr: histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{job="my-app"}[5m])) by (le, job))

Adicione a seguinte linha no seu prometheus.yml para carregar as regras e reinicie o Prometheus:

rule_files:
  - 'rules.yml'

Agora, você pode usar as métricas pré-calculadas (ex: job:sli_availability:ratio_rate5m) em seus dashboards e alertas, que serão muito mais eficientes.

Visualizando SLOs e Error Budgets no Grafana

Com as métricas sendo coletadas e pré-calculadas, o próximo passo é a visualização.

  1. Adicionar Prometheus como Data Source: No Grafana, vá para Configuration > Data Sources > Add data source, selecione Prometheus e configure a URL (ex: http://prometheus:9090).
  2. Criar um Dashboard de SLO: Crie um novo dashboard e adicione painéis para cada SLO.

Painel de Status do SLO

Use um painel do tipo “Gauge” para mostrar o desempenho atual em relação à meta.

  • Query: Use a recording rule que criamos, por exemplo: job:sli_availability:ratio_rate5m{job="my-app"} * 100
  • Visualização: Configure os thresholds do gauge. Se seu SLO é 99.9%, você pode definir: Base (0), Verde (> 99.9), Amarelo (99.8), Vermelho (< 99.8).

Painel de Error Budget Restante

Este é um dos painéis mais importantes. Ele mostra quanto do seu orçamento de erro ainda resta no período definido (ex: 28 dias).

  • SLO: 99.9% (ou 0.999)
  • Período: 28d
  • Query para Taxa de Erros no Período: 1 - (sum_over_time(job:sli_availability:ratio_rate5m[28d]) / count_over_time(job:sli_availability:ratio_rate5m[28d]))
  • Query para Budget Restante: (1 - 0.999) - (1 - (sum_over_time(job:sli_availability:ratio_rate5m[28d]) / count_over_time(job:sli_availability:ratio_rate5m[28d])))

Multiplique por 100 para exibir em porcentagem e use um painel “Stat” ou “Gauge”.

Painel de Burn Rate do Error Budget

O Burn Rate indica a velocidade com que o error budget está sendo consumido. Um burn rate de 1 significa que o budget será totalmente consumido exatamente no final do período. Um burn rate > 1 indica que o SLO será violado antes do final do período.

Para um SLO de 99.9% (error budget de 0.1%) em 28 dias, a taxa de erro permitida é 0.001. A query para o burn rate sobre a última hora seria:

(1 - job:sli_availability:ratio_rate1h) / (1 - 0.999)

Use um painel “Time series” para plotar o burn rate ao longo do tempo. Isso permite uma detecção precoce de problemas.

Configurando Alertas Proativos com Alertmanager

A visualização é passiva; a ação vem dos alertas. O Alertmanager, integrado ao Prometheus, é usado para gerenciar alertas. A estratégia mais eficaz é alertar sobre o burn rate do error budget, pois é um indicador preditivo de violação do SLO.

Crie um arquivo prometheus/alerting.rules.yml:

groups:
- name: SLOAlerts
  rules:
  - alert: HighErrorBudgetBurn
    expr: job:sli_availability:ratio_rate1h < (1 - (14.4 * (1 - 0.999)))
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "High error budget burn rate for my-app (critical)"
      description: "More than 5% of the 28-day error budget has been consumed in the last hour."

  - alert: SlowErrorBudgetBurn
    expr: job:sli_availability:ratio_rate6h < (1 - (3.6 * (1 - 0.999)))
    for: 30m
    labels:
      severity: warning
    annotations:
      summary: "Slow error budget burn rate for my-app (warning)"
      description: "More than 2% of the 28-day error budget has been consumed in the last 6 hours."

A lógica aqui é baseada em multiplicadores. Por exemplo, 14.4 é um multiplicador que indica que, se a taxa de erro atual se mantiver por 24 horas, consumirá cerca de 5% do budget mensal. Esses alertas são muito mais significativos do que um simples “a disponibilidade caiu para X%”.

Adicione esta regra ao prometheus.yml e configure-o para se comunicar com uma instância do Alertmanager para receber notificações via Slack, PagerDuty, ou outros canais.

Refinamento e Iteração Contínua

A implementação de SLOs não é um projeto único, mas um processo cíclico. A primeira versão dos seus SLOs pode não ser perfeita. É essencial:

  • Revisar Regularmente: Realize reuniões periódicas com stakeholders para revisar o desempenho dos SLOs. Eles ainda refletem a expectativa do usuário? São muito frouxos ou muito rígidos?
  • Analisar Violações: Cada violação de SLO deve acionar um post-mortem. A análise da causa raiz é fundamental para identificar fraquezas sistêmicas e implementar melhorias duradouras.
  • Automatizar e Padronizar: Conforme sua organização amadurece, considere ferramentas que padronizam a definição de SLOs, como o OpenSLO, ou automações que geram dashboards e alertas a partir de uma definição centralizada de SLOs. Isso garante consistência e escalabilidade à sua prática de SRE.

Ao seguir esta abordagem estruturada, você pode transformar a maneira como sua equipe mede e gerencia a confiabilidade, passando de uma postura reativa para uma proativa e orientada por dados, utilizando o poder do ecossistema Prometheus e Grafana.