Observabilidade com Prometheus
Tags: onservability, o11y, prometheus
Published: 2022-10-01 06:53:24

Documentando [minha apresentação](https://speakerdeck.com/mrrandrade/observabilidade-episodio-2-metricas) criada originalmente para o [DevOps Experience conduzido pelo DevOps Heroes](https://www.instagram.com/devopsheroes/?hl=en), aqui vai um resumo sobre métricas no Prometheus!

## Prometheus

Prometheus como solução de monitoramento é uma "cria" interessante: ele não se limita a um conjunto de ferramentas "server-side" - aliás, o principal foco é justamente a [existência](https://github.com/prometheus/client_golang) de [diversas](https://github.com/prometheus/client_python) [bibliotecas](https://github.com/prometheus/client_java) [disponíveis](https://github.com/prometheus/client_rust).

Inclusive ele mesmo "se vende" como solução para implementar whitebox monitoring:

![Prometheus vs Nagions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/54huawhison81g4eshzg.png)

## Tipos de métricas

Como descrito [neste post](https://www.instagram.com/p/CehrmHIuTo5/), Prometheus disponibiliza quatro tipos de métricas para uso na instrumentação da sua aplicação:

* Gauges
* Counters 
* Histograms
* Summaries

Vamos entender como cada uma funciona do ponto de vista de objetivos de monitoração.

## Gauges

Métricas do tipo **Gauge** é um número que representa um "snapshot" do que está sendo observado.  Memória livre, espaço em disco consumido, uso de CPU, temperatura do datacenter, algo que pode aumentar ou diminuir.

A maior parte da monitoração tradicional se encaixa com este tipo de métrica. Elas nos permitem formar simpáticos dashboards para acompanhar ao longo do tempo e gerar alertas caso determinada situação persista por muito tempo:

```
# Consumo de memória (em %)
node_memory_MemAvailable_bytes / 
node_memory_MemTotal_bytes

# Espaço em disco ocupado (em %^)
(1 - node_filesystem_avail_bytes{mountpoint="/mnt/c"}) / 
     node_filesystem_size_bytes{mountpoint="/mnt/c"}
```

![Dashboard](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jay37tz7njrl5ou85nu4.png)

Ambas as métricas acima foram extraídas usando o [Prometheus Node Exporter](https://github.com/prometheus/node_exporter).

Há uma pequena diferença entre as métricas acima.

Como há apenas uma única máquina sendo monitorada, não precisei especificar nenhum **filtro de labels** na consulta. 

Já no espaço em disco, as métricas são exibidas para cada sistema de arquivos:

![Prometheus filesystems](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5pmazie7phgg027e17rb.png)

No caso, no Dashboard, optei por limitar a métrica ao sistema de arquivos "/mnt/c":

```
1 - node_filesystem_avail_bytes{mountpoint="/mnt/c"} /
    node_filesystem_size_bytes{mountpoint="/mnt/c"} 
```

A terceira métrica é mais interessante: CPU. Ampliando o gráfico:

![Consumo de CPU](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fwslk3mf9czrt25y7giu.png)

A máquina conta com 8 CPUs - ou o mais provável, 8 **cores**.

A métrica para recuperar essa informação é muito mais complexa que as anteriores, e você vai perceber que **eu menti** ao colocá-la ao lado das duas outras - porque esta **não** é um **Gauge** - e o próprio Grafana me dedura:

![Selected metric is a counter](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ztmosuwrpt9ztkfj5eiy.png)

Entretanto, ninguém percebeu na apresentação!

Usei de conhecimento arcano em Prometheus para exibir valores que "sobem" e "descem". Aqui estão os recursos necessários para viabilizar o Dashboard como ele apareceu na imagem anterior:

```
# Consumo por CPU
1 - (avg by (cpu) (rate(node_cpu_seconds_total{mode="idle"}[1m])))

# Consumo de CPU agregado 
1 - (avg (rate(node_cpu_seconds_total{mode="idle"}[1m])))
```

Você pode me perguntar: mas por que tão complicado? Não seria bem mais simples coletar um "snapshot" do consumo de cada core em um dado momento e expor esse valor? Por exemplo, no instante da coleta, 4 CPUs estão a 100%, e 4 em 15%.

Mas pense um pouco. Se você acompanha o consumo de um host por uma amostragem em um dado em um dado momento, quão confiável é aquele valor? Especialmente se o intervalo da amostragem for em períodos longos, como 5 minutos?

Existe uma razão para o Prometheus fazer uma tarefa aparentemente simples ("eu só quero uma amostra do consumo de CPU") de maneira tão surrealmente complicada. 

A resposta é uma tríplice combinação de **busca por capacidade de inferência** combinada com a **flexibilidade  e expressividade matemática** e a **simplicidade de para implementar contadores simples** ao instrumentar aplicações.

Já vimos a flexibilidade matemática no exemplo da consulta em PromQL acima. A próxima imagem mostra como a métrica na verdade foi implementada:

![Tempos de CPU](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/93u8wc803602tpktcqxp.png)

Na verdade, há **8** métricas geradas para cada core, descrevendo (por meio de um número) o "tempo de cpu" gasto em cada um dos 8 estados (**idle**, **iowait**, **irq**, **nice**, **softirq**, **steal**, **system** e **user**).

Uma ferramenta poderia optar por fazer uma extração de um momento em particular. Ao fazer do "jeito complicado", o Prometheus delega a decisão de como tratar a métrica do lado do servidor, oferecendo flexibilidade para você isolar e analisar os valores como quiser. 

Se você não entendeu a consulta acima, não se preocupe, vem mais por aí!