Monitorando aplicações docker com prometheus e grafana
Para garantir que as aplicações estejam em níveis de desempenho aceitáveis para o seu negócio, é necessário monitorar. Para monitorar, é necessário medir. Pensando nisso, apresento alguns conhecimentos que obtive utilizando essas ferramentas durante o meu dia a dia de desenvolvedor.
Com essas ferramentas, você consegue monitorar desde métricas de sistema, como CPU, Memória e IO do disco, métricas de banco de dados, como quantidade de transações e tempo de resposta das queries e métricas de aplicação, como taxa de ero/sucesso, tempo de resposta, e outras diversas possibilidades que você pode conferir clicando aqui.
Para esse artigo, espero que você tenha o Docker e o docker-compose instalados e configurados em sua máquina. Caso ainda não tenha, recomendo se guiar por esse link e, logo após, continuar sua leitura.
Aplicação
Para exemplificar os recursos apresentados, foi criada uma aplicação simples em nodeJS com métricas padrões e customizadas.
const prometheus = require('prom-client');
Para a instrumentação das métricas foi utilizada a lib “prom-client”. A lista de todas as libs disponíveis para as variadas linguagens você pode encontrar clicando aqui.
Para o envio das métricas padrão da biblioteca, instrumentamos com o código:
const collectDefaultMetrics = prometheus.collectDefaultMetrics;const register = prometheus.register;collectDefaultMetrics({ register });
Para adicionarmos uma métrica incremental/cumulativa, utilizamos o exemplo de quantidade total de requisições, conforme:
const request_total_counter = new prometheus.Counter({ name: 'request_total', help: 'Contador de Requisições', labelNames: ['method', 'statusCode'],});
E acionamos o incremento no momento desejado com o código:
request_total_counter.labels({ method: 'GET', statusCode: statusCode }).inc();
Criamos também uma função para calcular o tempo em milissegundos da requisição, apresentando assim os formatos de histograma (onde visualizamos o tempo de resposta como série temporal) e de percentis (onde visualizamos o tempo de resposta em cada percentual configurado).
const request_time_histogram = new prometheus.Histogram({ name: 'aula_request_time_seconds', help: 'Tempo de Resposta das Requisições', buckets: [10, 20, 30, 40, 50, 60, 70, 80, 90, 100],});
const request_time_summary = new prometheus.Summary({ name: 'aula_summary_request_time_seconds', help: 'Tempo de Resposta das Requisições', percentiles: [0.01, 0.05, 0.5, 0.9, 0.95, 0.99, 0.999],});
Foi utilizada a seguinte função para prover esses dados:
const initialTime = Date.now();await sleep(100 * Math.random());const durationTime = Date.now() - initialTime;request_time_histogram.observe(durationTime); // Adicionando o tempo de resposta da requisição para visualização do histogramarequest_time_summary.observe(durationTime); // Adicionando o tempo de resposta da requisição para visualização dos percentis
Segue o código completo da aplicação abaixo:
Para expor essa aplicação, foi utilizado docker com as seguintes configurações:
Prometheus
O Prometheus será o responsável pela coleta e armazenamento das métricas em seu banco de série temporal (TSDB).
Para a configuração do tempo de intervalo e das aplicações que terão suas métricas coletadas, criamos o arquivo de configuração prometheus.yml.
Para que a ferramenta utilize este arquivo de configuração, a seguinte configuração é realizada no docker-compose.
Grafana
O Grafana será o responsável por exibir as métricas coletadas através de dashboads gráficos, se conectando ao Prometheus como fonte dos dados.
É possível também cadastrar alertas para um monitoramento ativo.
O primeiro passo é adicionar o Grafana ao nosso compose e depois configuramos o Prometheus como fonte de dados (data source).
Após entrar no ambiente do grafana pelo link http://localhost:3000 e configurar o login ao inicializar, iremos adicionar um novo data source.
Com as métricas configuradas, o próximo passo é configurar a exibição. Para isso, iremos subir o container do Grafana e então começar a montar os dashboards.
Para esse estudo, montamos 3 painéis dentro do nosso dashboard, onde demonstramos a taxa de erro da API, a quantidade de requisições por segundo e também mostramos os percentis com o tempo de resposta.
Para configurar a visualização da quantidade de requisições por segundo da sua aplicação, você incluirá um novo painel ao seu dashboard com a seguinte query:
sum(rate(nodemetrics_request_total[1m]))
Para configurar a visualização dos percentis com o tempo de resposta, você incluirá um novo painel ao seu dashboard com a seguinte query (caso deseje visualizar diferentes percentis em seu gráfico, basta adicionar novas queries no mesmo painel e ajustar o valor, que no exemplo está 0.90):
histogram_quantile(0.90, sum(rate(nodemetrics_request_time_histogram_ms_bucket[1m])) by (le))
Para configurar a visualização da taxa de erros da sua aplicação, você incluirá um novo painel ao seu dashboard com a seguint query:
sum(rate(nodemetrics_request_total{statusCode="500"}[1m])) / sum(rate(nodemetrics_request_total[1m]))
Ao final nosso dashboard ficou com a seguinte visualização:
A partir deste exemplo, é possível explorar as mais variadas métricas e criar diferentes possibilidades de visualizações.
Abaixo é possível encontrar alguns links e o código desse e de outros dashboards onde você pode importar diretamente em seu Grafana.
Links e templates
Link de Bibliotecas do Prometheus: https://prometheus.io/docs/instrumenting/clientlibs/
Link de Referência para Criação de Métricas em sua aplicação Node com “prom-client”: https://github.com/siimon/prom-client
Link Extra para Obtendo métricas de seus containers com Google cAdvisor: https://github.com/google/cadvisor
Template Grafana: Node Métrics (Tutorial deste artigo)
Template Grafana: Monitorando seu Docker
Template Grafana: Monitorando suas aplicações .net