Ajude a moldar o futuro das operações de software e compartilhe seu feedback com a pesquisa State of DevOps 2021.

Como usar métricas do Prometheus

Nesta página, você verá os conceitos básicos da criação de métricas do Prometheus para SLIs de disponibilidade e latência. Você verá também exemplos de implementação de como definir SLOs usando métricas do Prometheus.

Conceitos básicos do Prometheus

O Prometheus é uma importante solução de monitoramento de código aberto para métricas e alertas.

O Prometheus é compatível com dados dimensionais com identificadores de chave-valor para métricas, fornece a linguagem de consulta PromQL e é compatível com muitas integrações fornecendo exportadores para outros produtos.

O Prometheus se integra ao Cloud Monitoring usando o coletor do Stackdriver.

Métrica

O Prometheus é compatível com os seguintes tipos de métricas:

  • Contador: um único valor que só pode ser aumentado monotonicamente ou redefinido para 0 na reinicialização.
  • Medidor: um valor numérico único que pode ser definido arbitrariamente.
  • Histograma: um grupo de buckets configuráveis para amostragem de observações e gravação de valores em intervalos, também fornece uma soma de todos os valores observados.
  • Resumo: como um histograma, mas também calcula quantis configuráveis em uma janela de tempo variável.

Para mais informações, consulte Tipos de métricas.

Instrumentação

Para que o Prometheus receba métricas do seu aplicativo, o aplicativo precisa expor um endpoint dedicado (geralmente /metrics) com os valores de métrica disponíveis nele. Para expor esse endpoint, use as bibliotecas de cliente do Prometheus.

Se o aplicativo já gravar métricas em outro destino, como um banco de dados ou um arquivo, será possível criar um exportador do Prometheus para ler os dados e expô-los. Para mais informações, consulte exportadores.

Por fim, você precisa ter um servidor Prometheus em que as métricas sejam armazenadas e uma maneira de ingerir métricas no Cloud Monitoring a partir do servidor. O coletor do Stackdriver tem essa finalidade.

Como criar métricas para SLIs

O aplicativo precisa criar métricas do Prometheus que podem ser usadas como SLIs no Cloud Monitoring:

  • Para SLIs de disponibilidade em contagens de solicitações e erros, comece com as métricas de contador do Promethus.
  • Para SLIs de latência, use as métricas de resumo ou histograma do Promethus.

Métricas para SLIs de disponibilidade

Para expressar um SLI de disponibilidade baseado em solicitação na API Cloud Monitoring, use a estrutura TimeSeriesRatio para configurar uma proporção de solicitações "boas" ou "ruins" para o total solicitações. Essa proporção é usada no campo goodTotalRatio de uma estrutura RequestBasedSli.

O aplicativo precisa criar métricas do Prometheus que podem ser usadas para construir essa proporção. No aplicativo, é preciso criar pelo menos dois dos seguintes itens:

  1. Uma métrica que conta o total de eventos. Use essa métrica no totalServiceFilter da proporção.

    É possível criar um contador do Prometheus que seja incrementado para cada evento.

  2. Uma métrica que conta eventos "ruins". Use essa métrica no badServiceFilter da proporção.

    É possível criar um contador do Prometheus que seja incrementado para cada erro ou outro evento "ruim".

  3. Uma métrica que conta eventos "bons". Use essa métrica no goodServiceFilter da proporção.

    É possível criar um contador do Prometheus que seja incrementado para cada evento bem-sucedido ou "bom".

Em Exemplo de implementação, é criado um contador para o número total de solicitações, nodeRequestsCounter, e um contador para o número de solicitações com falha, nodeFailedRequestsCounter.

Métricas para SLIs de latência

Expresse um SLI de latência baseado em solicitação na API Cloud Monitoring criando uma estrutura DistributionCut. Essa estrutura é usada no campo distributionCut de uma estrutura RequestBasedSli.

O aplicativo precisa criar uma métrica do Prometheus que possa ser usada para criar o valor de corte de distribuição. É possível usar um histograma ou resumo do Promethus para essa finalidade. Para determinar como definir os buckets para medir com precisão se suas respostas se enquadram no SLO, consulte Tipos de métricas na documentação do Prometheus.

Em Exemplo de implementação, é criado um histograma para latências de resposta por caminho, nodeLatenciesHistogram.

Exemplo de implementação

Nesta seção, apresentamos um exemplo que implementa métricas para SLIs de latência e disponibilidade básica usando o Prometheus no Node.js.

Instrumentação

Para instrumentar o serviço para expor métricas do Prometheus, faça o seguinte:

  1. Inclua ou importe o cliente do Prometheus:

    Go

    import (
    	"fmt"
    	"log"
    	"math/rand"
    	"net/http"
    	"time"
    
    	"github.com/prometheus/client_golang/prometheus"
    	"github.com/prometheus/client_golang/prometheus/promauto"
    	"github.com/prometheus/client_golang/prometheus/promhttp"
    )
    

    Node.js

    const prometheus = require('prom-client');
    const collectDefaultMetrics = prometheus.collectDefaultMetrics;
    const Registry = prometheus.Registry;
    const register = new Registry();
    collectDefaultMetrics({register});

    Python

    import random
    import time
    
    from flask import Flask
    
    from prometheus_client import (
        Counter,
        generate_latest,
        Histogram,
        REGISTRY,
    )
    
  2. Use o cliente para definir as métricas:

    Go

    // Sets up metrics.
    var (
    	requestCount = promauto.NewCounter(prometheus.CounterOpts{
    		Name: "go_request_count",
    		Help: "total request count",
    	})
    	failedRequestCount = promauto.NewCounter(prometheus.CounterOpts{
    		Name: "go_failed_request_count",
    		Help: "failed request count",
    	})
    	responseLatency = promauto.NewHistogram(prometheus.HistogramOpts{
    		Name: "go_response_latency",
    		Help: "response latencies",
    	})
    )
    

    Node.js

    // total requests - counter
    const nodeRequestsCounter = new prometheus.Counter({
      name: 'node_requests',
      help: 'total requests',
    });
    
    // failed requests - counter
    const nodeFailedRequestsCounter = new prometheus.Counter({
      name: 'node_failed_requests',
      help: 'failed requests',
    });
    
    // latency - histogram
    const nodeLatenciesHistogram = new prometheus.Histogram({
      name: 'node_request_latency',
      help: 'request latency by path',
      labelNames: ['route'],
      buckets: [100, 400],
    });

    Python

    PYTHON_REQUESTS_COUNTER = Counter("python_requests", "total requests")
    PYTHON_FAILED_REQUESTS_COUNTER = Counter("python_failed_requests", "failed requests")
    PYTHON_LATENCIES_HISTOGRAM = Histogram(
        "python_request_latency", "request latency by path"
    )
  3. Defina o endpoint em que as métricas do Prometheus serão expostas (usando o Express):

    Go

    http.Handle("/metrics", promhttp.Handler())

    Node.js

    app.get('/metrics', async (req, res) => {
      try {
        res.set('Content-Type', register.contentType);
        res.end(await register.metrics());
      } catch (ex) {
        res.status(500).end(ex);
      }
    });

    Python

    @app.route("/metrics", methods=["GET"])
    def stats():
        return generate_latest(REGISTRY), 200
    
    
  4. Aumente as métricas do contador corretamente:

    Go

    requestCount.Inc()
    
    // Fails 10% of the time.
    if rand.Intn(100) >= 90 {
    	log.Printf("intentional failure encountered")
    	failedRequestCount.Inc()
    	http.Error(w, "intentional error!", http.StatusInternalServerError)
    	return
    }

    Node.js

    // increment total requests counter
    nodeRequestsCounter.inc();
    // return an error 10% of the time
    if (Math.floor(Math.random() * 100) > 90) {
      // increment error counter
      nodeFailedRequestsCounter.inc();

    Python

    PYTHON_REQUESTS_COUNTER.inc()
    # fail 10% of the time
    if random.randint(0, 100) > 90:
        PYTHON_FAILED_REQUESTS_COUNTER.inc()
  5. Rastreie a métrica de latência corretamente:

    Go

    requestReceived := time.Now()
    defer func() {
    	responseLatency.Observe(time.Since(requestReceived).Seconds())
    }()

    Node.js

    // start latency timer
    const requestReceived = new Date().getTime();
    console.log('request made');
    // increment total requests counter
    nodeRequestsCounter.inc();
    // return an error 10% of the time
    if (Math.floor(Math.random() * 100) > 90) {
      // increment error counter
      nodeFailedRequestsCounter.inc();
      // return error code
      res.send('error!', 500);
    } else {
      // delay for a bit
      sleep.msleep(Math.floor(Math.random() * 1000));
      // record response latency
      const responseLatency = new Date().getTime() - requestReceived;
      nodeLatenciesHistogram.labels(req.route.path).observe(responseLatency);

    Python

    @PYTHON_LATENCIES_HISTOGRAM.time()

Como configurar a ingestão

Depois que o serviço estiver em execução e emitindo métricas em um endpoint, defina as configurações apropriadas para a Extração no Prometheus e o Coletor do Stackdriver para ingerir métricas no Cloud Monitoring.

Essa configuração determina como as métricas do Prometheus são exibidas no Monitoring. Neste exemplo, as métricas do Prometheus são mapeadas da seguinte maneira:

  • nodeRequestCounter torna-se external.googleapis.com/prometheus/total_request_count.
  • nodeFailedRequestCounter torna-se external.googleapis.com/prometheus/error_count.
  • nodeLatenciesHistogram torna-se external.googleapis.com/prometheus/reponse_latency.

O tipo de recurso monitorado associado é k8s_container.

Use essas métricas ingeridas para definir SLIs.

SLIs de disponibilidade

No Cloud Monitoring, você expressa um SLI de disponibilidade baseado em solicitação usando uma estrutura TimeSeriesRatio. O exemplo a seguir mostra um SLO que usa as métricas ingeridas do Prometheus e espera que o serviço tenha uma disponibilidade de 98%, conforme calculado por uma proporção de solicitações inválidas para o total de solicitações em uma janela contínua de 28 dias:

{
 "serviceLevelIndicator": {
   "requestBased": {
     "goodTotalRatio": {
       "totalServiceFilter":
         "metric.type=\"external.googleapis.com/prometheus/total_request_count\"
          resource.type=\"k8s_container\"",
       "badServiceFilter":
         "metric.type=\"external.googleapis.com/prometheus/error_count\"
          resource.type=\"k8s_container\""
     }
   }
 },
 "goal": 0.98,
 "rollingPeriod": "2419200s",
 "displayName": "98% Availability, rolling 28 days"
}

SLIs de latência

No Cloud Monitoring, você expressa um SLI de latência baseado em solicitação usando uma estrutura DistributionCut. O exemplo a seguir mostra um SLO que usa a métrica de latência ingerida do Prometheus e espera que 98% das solicitações sejam concluídas em menos de 500 ms em uma janela contínua de um dia:

{
  "serviceLevelIndicator": {
    "requestBased": {
      "distributionCut": {
        "distributionFilter":
          "metric.type=\"external.googleapis.com/prometheus/response_latency\"
           resource.type=\"k8s_container\"",
        "range": {
          "min": 0,
          "max": 500
        }
      }
    }
  },
  "goal": 0.98,
  "rollingPeriod": "86400s",
  "displayName": "98% requests under 500 ms"
}