Explorando o Hyperf: Um guia básico sobre observabilidade

Reinan Gabriel
26 min readJun 3, 2023

--

Introdução a observabilidade — Fonte do autor

Resumo

Nesta publicação, vamos explorar o conceito de observabilidade e como é possível monitorar o comportamento interno de sistemas complexos. Uma vez que através da observabilidade, podemos obter insights valiosos sobre o estado, desempenho e interações dos componentes de um sistema distribuído por meio de seus sinais externos.

Ao contrário de simplesmente verificar o funcionamento de um sistema, a observabilidade vai além, proporcionando uma compreensão profunda de como os diferentes elementos se comportam e se relacionam entre si. Isso envolve a coleta e análise de métricas, registros detalhados, rastreamento de transações e eventos, além da criação de visualizações claras e intuitivas dos dados coletados.

Além disso, destacaremos algumas das principais ferramentas de observabilidade disponíveis, como o Prometheus para monitoramento de infraestrutura, e o Jaeger e o Zipkin para rastreamento distribuído. Essas ferramentas oferecem visibilidade e compreensão do comportamento de sistemas distribuídos, permitindo a identificação de gargalos, solução de problemas e otimização de desempenho.

Se você tem interesse em aproveitar os benefícios da observabilidade e aprofundar seu conhecimento sobre o assunto, recomendamos a leitura desta publicação. Nela, aplicaremos todos esses conceitos em uma aplicação feita em Hyperf, e faremos uma demonstração de como essas informações estão sendo correlacionadas através de um exemplo prático utilizando três microsserviços.

O que é observabilidade

Observabilidade é a capacidade de compreender e monitorar o comportamento interno de um sistema com base em seus sinais externos. É uma abordagem que permite obter visibilidade total e insights sobre o estado, o desempenho e as interações dos componentes de um sistema distribuído.

Diferentemente da simples verificação do funcionamento do sistema, a observabilidade vai além, proporcionando uma compreensão profunda de como os diferentes elementos se comportam e se relacionam entre si. Isso inclui a coleta e análise de métricas, registros (logs) detalhados, rastreamento de transações e eventos, além da criação de visualizações claras e intuitivas dos dados coletados.

Para Matheus de Andrade (2022, p. 17): “observabilidade é a habilidade de medir os estados internos de um sistema examinando suas saídas. Que pode ser entendido como coletar dados dos sistemas e examiná-los com o intuito de entender o seu funcionamento”.

Além dos benefícios mencionados anteriormente, a observabilidade está se tornando uma abordagem amplamente adotada e valorizada no mercado atual. Especificamente, é uma metodologia essencial para lidar com a complexidade dos microsserviços, que se tornaram uma tendência dominante no desenvolvimento de software.

Para Leo Cavalcante (2022): “Observabilidade é a metodologia que o mercado de microsserviços e cloud-native explora para monitorar as aplicações”

Em resumo, a observabilidade é a capacidade de compreender e monitorar um sistema complexo, permitindo uma visão clara do seu estado interno, comportamento e desempenho, facilitando a detecção de problemas, a depuração e a tomada de decisões informadas para melhorar sua eficiência e confiabilidade.

A Origem da Observabilidade: Uma visão histórica sobre seu surgimento

Conforme mencionado por Gerson Neto (2022), é notável que o termo “observabilidade” teve sua origem no trabalho do engenheiro americano Rudolf E. Kálmán em agosto de 1960, conforme mencionado em seu livro “Teoria dos sistemas de controle” (On the general theory of control systems).

Na obra, Kálmán introduziu o conceito de observabilidade como uma propriedade fundamental dos sistemas de controle. Ele descreveu a observabilidade como a capacidade de determinar o estado interno de um sistema com base em suas saídas externas. Em outras palavras, a observabilidade estava relacionada à possibilidade de obter informações precisas sobre o estado oculto de um sistema através da observação de seu comportamento externo.

Para Rudolf E. Kálmán a observabilidade é uma medida de quão bem os estados internos de um sistema podem ser inferidos a partir do conhecimento de suas saídas externas.

Originalmente, o conceito de observabilidade foi aplicado principalmente na área de engenharia elétrica e controle de sistemas. Nessas áreas, era fundamental monitorar e compreender o comportamento de sistemas complexos por meio da observação de sinais externos. Essas ideias foram contribuições significativas e estabeleceram as bases para a aplicação do conceito de observabilidade em diversos outros campos, incluindo o desenvolvimento de software.

Ao longo das décadas seguintes, o conceito de observabilidade evoluiu e foi adaptado para o contexto do desenvolvimento de software. À medida que os sistemas de software se tornaram mais complexos e distribuídos, a observabilidade se tornou um requisito essencial para compreender o comportamento interno desses sistemas por meio de sinais externos.

Em suma, Rudolf E. Kálmán, em seu livro “Teoria dos sistemas de controle, lançou as bases do conceito de observabilidade, estabelecendo sua importância na determinação do estado interno dos sistemas. Sua contribuição foi fundamental para a evolução e aplicação desse conceito no desenvolvimento de software moderno.

Princípios essenciais para um sistema observável

Agora que compreendemos o significado da observabilidade e sua origem, é o momento de aprofundarmos nosso conhecimento sobre os pilares essenciais desse conceito. A observabilidade se fundamenta em três pilares-chave: métricas, logs e rastreamento.

Nesta seção, vamos explorar cada um desses pilares em detalhes, destacando sua relevância na construção de sistemas altamente observáveis.

Pilares da observabilidade — Fonte do autor
  1. Métricas: As métricas fornecem medidas quantitativas do desempenho e do comportamento dos sistemas. Elas nos permitem monitorar tendências, identificar padrões e tomar decisões baseadas em dados. As métricas podem incluir o uso de recursos, o tempo de resposta, a taxa de erros, a capacidade de processamento e muito mais. Ao coletar e analisar métricas relevantes, podemos identificar gargalos, otimizar o desempenho e dimensionar adequadamente nossos sistemas de acordo com as demandas.
  2. Logs: Os logs são registros detalhados das atividades e eventos que ocorrem em um sistema. Eles fornecem informações cruciais para a depuração e a investigação de problemas. Ao registrar eventos importantes, erros, exceções e outras ocorrências relevantes, os logs nos permitem rastrear a sequência de eventos que levaram a determinado estado ou comportamento. Eles são uma fonte valiosa de informações para entender o contexto e a causa de problemas, facilitando a análise e a resolução de incidentes.
  3. Rastreamento: O rastreamento, também conhecido como tracing, é a capacidade de acompanhar o fluxo de uma transação ou uma solicitação através de vários componentes de um sistema distribuído. Ele fornece uma visão detalhada do caminho que uma solicitação percorre, destacando os tempos gastos em cada etapa e as interações entre os serviços. O rastreamento é particularmente valioso em ambientes complexos, onde várias chamadas de serviço podem estar envolvidas. Com o rastreamento adequado, podemos identificar gargalos, detectar falhas e otimizar a comunicação e o desempenho entre os componentes do sistema.

Benefícios da observabilidade

A observabilidade oferece uma série de benefícios abrangentes. Um sistema com maior capacidade de observação torna-se mais acessível em termos de compreensão geral e detalhada. Além disso, é mais simples de monitorar, mais seguro para atualizar novos códigos e mais fácil de reparar em comparação com um sistema com menor nível de observabilidade.

Aqui estão os principais benefícios que a observabilidade pode proporcionar a você:

  • Detecção e solução proativa de problemas: A observabilidade permite uma visão abrangente dos sistemas em funcionamento, oferecendo insights valiosos sobre o desempenho, a integridade e a eficiência das aplicações. Ao coletar e analisar dados em tempo real, os profissionais de TI podem identificar problemas potenciais antes que eles se tornem críticos, tomando medidas corretivas proativas. Isso resulta em menor tempo de inatividade, maior disponibilidade dos sistemas e maior satisfação do usuário final.
  • Análise e otimização de desempenho: A observabilidade fornece métricas e informações detalhadas sobre o desempenho dos sistemas, permitindo a identificação de gargalos, pontos de estrangulamento e áreas de otimização. Com base nessas informações, as equipes de desenvolvimento e operações podem tomar medidas precisas para melhorar o desempenho, otimizar recursos e aprimorar a experiência do usuário. A análise contínua do desempenho também possibilita a realização de ajustes proativos, evitando problemas futuros.
  • Tomada de decisões embasada em dados: A observabilidade fornece uma base sólida para tomadas de decisões embasadas em dados. Ao coletar informações detalhadas sobre o comportamento dos sistemas, os profissionais de TI têm acesso a dados confiáveis e atualizados, permitindo que eles avaliem o impacto de alterações, implementem estratégias de dimensionamento adequadas e otimizem a infraestrutura de TI. Isso resulta em decisões mais informadas e eficazes, minimizando riscos e maximizando a eficiência operacional.
  • Melhoria da experiência do usuário: A observabilidade desempenha um papel fundamental na garantia de uma experiência do usuário de alta qualidade. Ao monitorar ativamente os sistemas, os profissionais de TI podem identificar e resolver problemas que afetam a experiência dos usuários finais, como tempos de resposta lentos, erros frequentes ou interrupções do serviço. Ao melhorar a confiabilidade e a disponibilidade dos sistemas, a observabilidade contribui para a satisfação do usuário, a fidelização e a reputação positiva da organização.

A observabilidade oferece uma ampla gama de benefícios que podem auxiliar na resolução de diversos problemas. Se você está interessado em explorar os benefícios que a observabilidade pode proporcionar, recomenda-se a leitura da publicação da IBM e do GoCache que aborda esse tema de forma detalhada.

Explorando as Principais Ferramentas de Observabilidade: Uma Visão Abrangente

Nesse tópico, escolhi algumas ferramentas para ilustrar o uso da observabilidade no framework Hyperf. É importante ressaltar que essas não são as únicas opções disponíveis no mercado. No entanto, selecionei as principais ferramentas amplamente utilizadas e disponíveis gratuitamente para demonstração em um ambiente de desenvolvimento utilizando o Docker.

Principais ferramentas para o monitoramento de infraestrutura

O monitoramento de infraestrutura é uma prática essencial para garantir o bom funcionamento de sistemas e serviços. Ao acompanhar de perto o desempenho e o estado da infraestrutura, é possível identificar problemas e otimizar recursos. Abaixo, estão algumas das ferramentas que utilizaremos para visualizar as informações dos recursos utilizados pela nossa aplicação em Hyperf.

Prometheus

Uma das principais ferramentas de observabilidade para o monitoramento de infraestrutura é o Prometheus. Trata-se de um sistema de monitoramento e alerta, capaz de coletar e armazenar métricas sobre a infraestrutura. O Prometheus é altamente escalável e possui uma arquitetura flexível, o que o torna ideal para ambientes distribuídos. Ele permite a coleta de métricas em tempo real, o que possibilita uma visão detalhada do desempenho do sistema. Além disso, o Prometheus oferece recursos avançados, como consultas e alertas personalizados, permitindo uma análise profunda dos dados coletados.

Grafana

Outra ferramenta amplamente utilizada é o Grafana. O Grafana é uma plataforma de visualização de dados que se integra perfeitamente com o Prometheus e outras fontes de dados.

Com o Grafana, é possível criar painéis personalizados e intuitivos, exibindo métricas e gráficos em tempo real. Isso facilita a compreensão e a análise dos dados de monitoramento da infraestrutura, possibilitando a detecção rápida de problemas e tendências.

Exemplificação dos painéis do Grafana — Fonte do autor

O Grafana também oferece recursos avançados de alerta, permitindo a configuração de notificações por e-mail, Slack e outros canais, para garantir que problemas críticos sejam prontamente identificados e solucionados.

Principais ferramentas para o rastreamento distribuído

Em sistemas distribuídos complexos, compreender o fluxo das solicitações através de diferentes componentes e serviços pode ser um desafio. É nesse cenário que as ferramentas de rastreamento distribuído desempenham um papel fundamental, permitindo a visibilidade e a compreensão do comportamento do sistema como um todo.

A seguir, apresento algumas das ferramentas que utilizaremos para visualizar as informações de rastreamento distribuído entre nossos microsserviços desenvolvidos em Hyperf.

Jaeger

Uma das ferramentas mais populares de rastreamento distribuído é o Jaeger. O Jaeger é um sistema de código aberto que facilita a rastreabilidade de solicitações complexas em ambientes distribuídos. Ele fornece uma visão detalhada de cada solicitação à medida que atravessa os diferentes serviços e componentes envolvidos.

Exemplificação dos painéis do Jaeger — Fonte do autor

O Jaeger coleta e armazena informações sobre o tempo gasto em cada etapa, as dependências entre os componentes e os eventuais erros ocorridos. Com isso, é possível identificar gargalos de desempenho, compreender a latência e atrasos, além de solucionar problemas de forma mais eficiente.

Zipkin

Outra ferramenta importante é o Zipkin. O Zipkin é outra plataforma de rastreamento distribuído de código aberto que oferece recursos semelhantes ao Jaeger. Ele permite visualizar o fluxo de solicitações em um sistema distribuído, rastreando o tempo gasto em cada serviço e identificando possíveis gargalos ou problemas de desempenho.

Exemplificação dos painéis do Zipkin — Fonte do autor

O Zipkin também oferece a capacidade de pesquisar e analisar rastreamentos específicos, permitindo uma investigação mais detalhada em casos de erros ou comportamentos inesperados.

Principais ferramentas para o gerenciamento e centralização de logs

Em ambientes de TI complexos, onde diversos sistemas e componentes estão em funcionamento, o gerenciamento e a centralização de logs se tornam essenciais para manter a visibilidade e o controle sobre o funcionamento do sistema como um todo. As ferramentas de gerenciamento de logs ajudam a coletar, armazenar e analisar registros de várias fontes, permitindo uma visão unificada e facilitando a identificação de problemas e anomalias.

Abaixo está a ferramenta que escolhi para fornecer uma visualização mais detalhada dos logs gerados pela nossa aplicação em Hyperf.

Graylog

Um ferramenta de destaque é o Graylog, que oferece recursos abrangentes de gerenciamento e centralização de logs. O Graylog permite coletar, armazenar e analisar logs de várias fontes, incluindo aplicativos, servidores e dispositivos de rede. Ele possui uma interface intuitiva, com recursos de pesquisa avançada, filtragem e alertas personalizados.

Exemplificação dos painéis do Graylog — Fonte do autor

O Graylog também oferece recursos de análise de logs em tempo real, permitindo uma visão atualizada do estado do sistema.

Explorando o uso dessas ferramentas em um cenário de exemplo

Antes de começar a configurar essas ferramentas no Hyperf, farei uma breve explicação sobre como elas funcionarão no Hyperf. Para isso, utilizarei uma demonstração que criei para exemplificar o funcionamento e a integração dessas ferramentas.

Embora eu tenha mencionado anteriormente as principais ferramentas de observabilidade, é crucial entender como essas ferramentas se comunicam entre si e como o Hyperf envia informações para elas.

Observe a imagem abaixo:

Exemplificação do fluxo — Fonte do autor

A imagem acima representa uma demonstração que criei de um cenário de exemplo que simula uma API. Ao fazer uma chamada para essa API, as informações percorrem três microsserviços desenvolvidos em Hyperf. Cada um desses serviços se comunica com os outros por meio de chamadas HTTP.

No entanto, esses microsserviços utilizam as técnicas e ferramentas mencionadas anteriormente para criar um ambiente observável. Quando um dos nossos serviços recebe uma requisição, ele envia as informações de trace para o OpenTelemetry, que é responsável por distribuir essas informações para os provedores que configuramos. Na demonstração acima, as informações são enviadas para o ZipKin e o Jaeger.

Com essas duas ferramentas, podemos obter informações sobre o rastreamento distribuído, bem como sobre a latência e o tempo de resposta de cada um dos serviços. Veja o exemplo abaixo, que ilustra o processo de rastreamento distribuído:

No vídeo acima, é apresentada uma demonstração do rastreamento distribuído. Utilizamos a ferramenta Jaeger para visualizar as informações de todo o fluxo da requisição. Com as informações disponíveis, é possível saber o que ocorreu em cada etapa da requisição e quanto tempo foi necessário para processar as informações, desde as chamadas HTTP até as consultas realizadas no banco de dados.

Essas ferramentas facilitam a identificação de problemas de latência em nossos microsserviços. Isso se deve ao fato de que essas ferramentas fornecem informações valiosas sobre o tempo de execução do nosso código, permitindo uma visão detalhada de qual parte do código está impactando no desempenho da aplicação.

Como as informações de trace são correlacionadas entre os diferentes serviços?

Quando nossa aplicação realiza uma requisição HTTP, ela propaga o contexto do trace entre os serviços por meio do cabeçalho. Para garantir uma propagação correta, nossa aplicação segue o modelo de propagação B3.

O B3 é uma especificação para o cabeçalho das requisições em nossa aplicação. Essa especificação define identificadores usados para agrupar uma operação em uma árvore de rastreamento. Esses atributos são propagados durante o processo.

O caso de uso mais comum para a propagação é copiar um contexto de rastreamento de um cliente que envia uma solicitação HTTP para um servidor que a recebe. Nesse caso, o mesmo ID de trace é utilizado, o que significa que o lado do cliente e o lado do servidor de uma operação são unidos em um mesmo nó na árvore de rastreamento.

Aqui está um exemplo de fluxo usando codificação de vários cabeçalhos, assumindo que uma solicitação HTTP carrega o trace propagado:

Exemplificação dos cabeçalhos do B3 — Fonte do autor

Veja o exemplo em uma requisição HTTP feita pelo Hyperf:

Exemplificação dos cabeçalhos de uma solicitação Http usando B3 — Fonte do autor

Monitoramento dos recursos computacionais

Além do rastreamento, outro aspecto de suma importância é o monitoramento dos recursos computacionais em nossos microsserviços. A monitorização das informações de memória e CPU desempenha um papel fundamental na garantia do desempenho e da estabilidade dos sistemas e aplicações. Uma ferramenta amplamente utilizada para essa finalidade é o Grafana.

Ao empregar o Grafana para monitorar as informações de memória e CPU, você adquire insights valiosos sobre a utilização e alocação desses recursos. O Grafana oferece gráficos e painéis altamente personalizáveis. Veja o exemplo abaixo:

Com o Grafana, é possível visualizar de forma clara e intuitiva como esses recursos estão sendo utilizados, identificar tendências, picos de utilização e realizar análises comparativas. Essa visibilidade é essencial para tomar decisões informadas sobre otimização de recursos, identificar gargalos de desempenho e garantir que os microsserviços operem de maneira eficiente.

Outro aspecto crucial é o monitoramento dos logs em nossa aplicação, uma prática indispensável para garantir a segurança, o desempenho e a confiabilidade de sistemas e aplicações.

No ambiente de demonstração, escolhi utilizar a ferramenta Graylog. O Graylog é uma plataforma altamente flexível e escalável para gerenciamento e análise de logs. Ele permite coletar, indexar e analisar logs provenientes de diversas fontes em tempo real, fornecendo uma visão abrangente do estado e da saúde do sistema. Confira o vídeo abaixo, que ilustra a utilização dessa ferramenta:

Como os logs estão integrados ao nosso rastreamento distribuído, eles contêm informações importantes, como o campo traceid, que é um identificador único de uma requisição dentro de nossos microsserviços. Com essa informação, podemos capturar todos os logs gerados durante o ciclo de vida dessa requisição.

O monitoramento dos logs por meio do Graylog oferece diversos benefícios. É possível identificar erros, alertas e eventos relevantes em tempo real, facilitando a detecção de problemas e a tomada de ações corretivas imediatas. Além disso, a análise dos logs permite identificar padrões de comportamento, gargalos de desempenho e tendências, o que auxilia na otimização contínua dos sistemas.

Impacto no Desempenho ao Aplicar Conceitos de Observabilidade no Hyperf

Ao adicionar ferramentas de trace e métricas ao Hyperf, estamos introduzindo uma camada adicional de processamento sobre o código. É importante destacar que essa camada extra provavelmente terá algum impacto no desempenho em comparação com a ausência dela.

No entanto, é crucial compreender o grau desse impacto e como ele afeta a latência das solicitações ao aplicar esses conceitos em um projeto em Hyperf. Para avaliar esse aumento na latência, realizei testes de carga utilizando a ferramenta K6. Abaixo estão as configurações utilizadas nos testes:

import http from 'k6/http';
import {check} from 'k6';

export const options = {
stages: [
{duration: '30s', target: 100},
{duration: '30s', target: 500},
{duration: '30s', target: 1000},
{duration: '30s', target: 1500},
],
userAgent: 'K6/main',
};
export default function () {
const res = http.get('http://app:9501/');
check(res, {
'is status 200': (r) => r.status === 200,
});
};

A seguir, apresento os resultados do teste de carga realizado com as ferramentas de observabilidade ativas no projeto:

Resultados do teste de carga realizado — Fonte do autor

Durante o teste, foram avaliados os tempos de resposta das solicitações e a capacidade do sistema em lidar com a carga.

A seguir, apresento os resultados do teste de carga realizado com as ferramentas de observabilidade desativadas no projeto:

Resultados do teste de carga realizado — Fonte do autor

Os resultados demonstraram o impacto da introdução das ferramentas de observabilidade no desempenho do projeto Hyperf.

Com a ativação das ferramentas de observabilidade, observou-se um aumento na latência das solicitações. Essa camada adicional de processamento impacta o tempo de resposta, refletindo em um leve aumento na latência das requisições. No entanto, é importante ressaltar que esse impacto pode variar dependendo das características específicas do projeto e das configurações utilizadas.

Esses resultados oferecem um insight preliminar sobre o desempenho ao adicionar as ferramentas de observabilidade ao projeto. Para obter uma compreensão mais abrangente do impacto de desempenho das ferramentas de observabilidade em uma aplicação, recomendo a leitura da publicação intitulada “Optimizing OpenTelemetry’s Span Processor for High Throughput and Low CPU Costs”.

Nessa publicação, são realizados testes de desempenho em um ambiente de computação em nuvem, avaliando a latência e o consumo de recursos computacionais. Ao explorar esse estudo, você terá uma visão mais abrangente do impacto das ferramentas de observabilidade dentro de uma aplicação, incluindo informações sobre como otimizar o processamento de spans do OpenTelemetry para obter alta capacidade de processamento e baixo consumo de CPU.

Com base nessas informações, é possível tomar medidas adequadas para otimizar o desempenho, se necessário, buscando um equilíbrio entre a observabilidade e a eficiência do sistema.

É fundamental considerar que os benefícios da observabilidade, como o monitoramento aprimorado, a depuração mais eficiente e a capacidade de identificar gargalos no sistema, geralmente superam os pequenos aumentos na latência. Através dos dados obtidos nos testes de carga, é possível tomar decisões embasadas sobre a implementação e ajustes necessários nas ferramentas de observabilidade, garantindo um bom desempenho do projeto Hyperf em ambientes de produção.

Repositório contendo todas as configurações do cenário de exemplo

O ambiente de demonstração completo mencionado anteriormente está disponível no meu repositório do Github. Você pode instalar esse ambiente em sua máquina usando o Docker.

O processo de configuração e instalação é simples e rápido, e está documentado no repositório do Gitlab. Se você estiver interessado em explorar mais essas ferramentas, sugiro que dê uma olhada no repositório e siga as instruções para instalar em sua máquina.

Iniciando a configuração das ferramentas de observabilidade no Hyperf: Introdução e requisitos iniciais

Chegou o tão esperado momento de dar o primeiro passo na configuração das ferramentas de observabilidade em nosso projeto Hyperf. O primeiro requisito é ter um projeto em Hyperf. Caso você não saiba como criar um projeto em Hyperf, sugiro que leia minha publicação que aborda o processo de criação de um novo projeto em Hyperf. Você pode acessar o link a seguir para ler o artigo completo:

Com esse pré-requisito atendido, estaremos prontos para avançar para a configuração das ferramentas de observabilidade em nosso projeto Hyperf.

Configurando métricas no Hyperf: Monitorando o desempenho do seu projeto

Para começar a configurar as métricas em seu projeto, o primeiro passo é instalar a biblioteca hyperf/metric. Para isso, execute o seguinte comando dentro do container de sua aplicação Hyperf:

composer require hyperf/metric

Em seguida, execute o comando abaixo para criar o arquivo de configuração para essa biblioteca:

php bin/hyperf.php vendor:publish hyperf/metric

Após executar o comando acima, acesse o arquivo config/autoload/metric.php e substitua o conteúdo do arquivo pelas configurações abaixo:

<?php

declare(strict_types=1);

use Hyperf\Metric\Adapter\Prometheus\Constants;

use function Hyperf\Support\env;

return [
'default' => env('METRIC_DRIVER', 'prometheus'),
'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true),
'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true),
'default_metric_interval' => env('DEFAULT_METRIC_INTERVAL', 5),
'metric' => [
'prometheus' => [
'driver' => Hyperf\Metric\Adapter\Prometheus\MetricFactory::class,
'mode' => Constants::SCRAPE_MODE,
'namespace' => env('APP_NAME', 'skeleton'),
'scrape_host' => env('PROMETHEUS_SCRAPE_HOST', '0.0.0.0'),
'scrape_port' => env('PROMETHEUS_SCRAPE_PORT', '9502'),
'scrape_path' => env('PROMETHEUS_SCRAPE_PATH', '/metrics'),
],
],
];

Após configurar o arquivo anteriormente mencionado, é necessário ativar o middleware para habilitar a função de coleta de métricas. Siga as instruções abaixo para fazer isso:

  1. Abra o arquivo config/autoload/middlewares.php.
  2. Adicione o middleware de acordo com o exemplo abaixo:
<?php

declare(strict_types=1);

return [
'http' => [
\Hyperf\Metric\Middleware\MetricMiddleware::class,
],
];

Com essas configurações, você estará pronto para começar a utilizar a métrica em seu projeto Hyperf.

Após concluir as configurações, é recomendado que você inicie sua aplicação Hyperf e faça uma chamada CURL para o endpoint que configuramos anteriormente. Isso permitirá que você verifique se as métricas estão funcionando corretamente e se sua aplicação está exportando os dados adequadamente. Veja um exemplo de como realizar essa validação:

Dentro do seu container do Hyperf, execute o seguinte comando para iniciar a aplicação:

php ./bin/hyperf.php start

Abra uma nova aba no terminal e execute o seguinte comando dentro do container do Hyperf:

curl 0.0.0.0:9502/metrics -vvv

Esse comando enviará uma solicitação ao endpoint de métricas, permitindo que você verifique se as métricas estão sendo geradas corretamente e se sua aplicação está exportando os dados. Se as configurações foram realizadas com sucesso, você receberá um status code 200 como resposta.

Dessa forma, você poderá validar o funcionamento das métricas e garantir que seu aplicativo Hyperf esteja monitorando e registrando o desempenho adequadamente.

Configurando métricas no Hyperf: Iniciando a configuração do OpenTelemetry Collector

Agora que nossa aplicação está gerando métricas, precisamos configurar o OpenTelemetry para fazer a leitura dessas métricas e exportá-las para os provedores que iremos configurar. O primeiro passo é criar um arquivo de configuração para o OpenTelemetry Collector.

Siga as instruções abaixo para criar o arquivo config.yaml dentro da pasta docker/collector. Caso a pasta não exista, crie-a.

  1. Crie o arquivo config.yaml e adicione o seguinte conteúdo:
receivers:
prometheus:
config:
scrape_configs:
- job_name: 'otel-hyperf-metrics'
metrics_path: '/metrics'
scrape_interval: 5s
static_configs:
- targets: [ 'app:9502' ]

exporters:
prometheus:
endpoint: '0.0.0.0:9502'
namespace: otel
send_timestamps: true
metric_expiration: 180m
resource_to_telemetry_conversion:
enabled: false

service:
pipelines:
metrics:
receivers: [ prometheus ]
exporters: [ prometheus ]

2. Em seguida, faça uma configuração adicional no arquivo docker-compose.yml. Acesse o arquivo e adicione as seguintes configurações para o serviço collector:

collector:
image: otel/opentelemetry-collector-contrib:0.39.0
volumes:
- './docker/collector/config.yaml:/etc/otel/config.yaml'
networks:
- back-tier
ports:
- '4317:4317'

A seguir, vamos adicionar a criação da rede back-tier no arquivo docker-compose.yml e configurar o serviço da sua aplicação Hyperf para utilizar essa rede.

Dessa forma, estaremos configurando o coletor do OpenTelemetry para nossa aplicação Hyperf. Essas etapas iniciais permitirão que o OpenTelemetry faça a leitura das métricas geradas e as envie para os provedores configurados.

3. Em seguida adicione a criação da rede back-tier no arquivo docker-compose.yml:

networks:
back-tier:
driver: bridge

4. Em seguida, localize as configurações do serviço da sua aplicação Hyperf no mesmo arquivo docker-compose.yml e adicione a configuração para utilizar a rede back-tier:

services:
app:
...
networks:
- back-tier

Essa configuração vinculará o serviço da sua aplicação Hyperf à rede back-tier que acabamos de criar. Isso permitirá a comunicação adequada entre os componentes do OpenTelemetry Collector. Certifique-se de salvar as alterações no arquivo docker-compose.yml após adicioná-las.

Configurando métricas no Hyperf: Iniciando a configuração do Prometheus

Agora vamos configurar o Prometheus para receber as informações enviadas pelo OpenTelemetry. Siga as etapas abaixo:

  1. Crie o arquivo de configuração prometheus.yml dentro da pasta docker/prometheus.
  2. Adicione o seguinte conteúdo ao arquivo prometheus.yml:
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
monitor: 'poc-hyperf-observability'

scrape_configs:
- job_name: 'hyperf-metrics'
metrics_path: '/metrics'
scrape_interval: 5s
static_configs:
- targets: ['collector:9502']

Essa configuração permite que o Prometheus leia as métricas coletadas pelo OpenTelemetry. Observe que estamos definindo o targets para apontar para o container que foi configurado anteriormente.

3. Adicione o serviço do Prometheus ao arquivo docker-compose.yml:

services:
prometheus:
image: prom/prometheus:v2.36.2
volumes:
- './docker/prometheus/:/etc/prometheus/'
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
- '--web.console.templates=/usr/share/prometheus/consoles'

4. Crie o volume prometheus_data adicionando o seguinte trecho ao arquivo docker-compose.yml:

volumes:
...
prometheus_data: {}

Atenção faça as alterações necessárias para adequar as configurações do seu arquivo.

Certifique-se de salvar todas as alterações no arquivo prometheus.yml e docker-compose.yml. Com essas configurações, o Prometheus estará pronto para receber as métricas do OpenTelemetry.

Configurando métricas no Hyperf: Iniciando a configuração do Grafana

Vamos fazer a configuração do Grafana. Siga as etapas abaixo:

  1. Crie os diretórios necessários:
docker/grafana
docker/grafana/provisioning
docker/grafana/provisioning/datasources
docker/grafana/provisioning/dashboards

2. Crie o arquivo config.monitoring na pasta raiz de configuração do Grafana. Adicione o seguinte conteúdo ao arquivo:

GF_SECURITY_ADMIN_PASSWORD=secret
GF_USERS_ALLOW_SIGN_UP=false

3. Crie o arquivo datasource.yml na pasta docker/grafana/provisioning/datasources. Adicione o seguinte conteúdo ao arquivo:

# config file version
apiVersion: 1

# list of datasources that should be deleted from the database
deleteDatasources:
- name: Prometheus
orgId: 1

# list of datasources to insert/update depending
# whats available in the database
datasources:
# <string, required> name of the datasource. Required
- name: Prometheus
# <string, required> datasource type. Required
type: prometheus
# <string, required> access mode. direct or proxy. Required
access: proxy
# <int> org id. will default to orgId 1 if not specified
orgId: 1
# <string> url
url: http://prometheus:9090
# <string> database password, if used
password:
# <string> database user, if used
user:
# <string> database name, if used
database:
# <bool> enable/disable basic auth
basicAuth: false
# <string> basic auth username, if used
basicAuthUser:
# <string> basic auth password, if used
basicAuthPassword:
# <bool> enable/disable with credentials headers
withCredentials:
# <bool> mark as default datasource. Max one per org
isDefault: true
# <map> fields that will be converted to json and stored in json_data
jsonData:
graphiteVersion: "1.1"
tlsAuth: false
tlsAuthWithCACert: false
# <string> json object of data that will be encrypted.
secureJsonData:
tlsCACert: "..."
tlsClientCert: "..."
tlsClientKey: "..."
version: 1
# <bool> allow users to edit datasources from the UI.
editable: true

4. Crie o arquivo dashboard.yml na pasta docker/grafana/provisioning/dashboards. Adicione o seguinte conteúdo ao arquivo:

apiVersion: 1

providers:
- name: 'Prometheus'
orgId: 1
folder: ''
type: file
disableDeletion: false
editable: true
options:
path: /etc/grafana/provisioning/dashboards

5. Crie o arquivo grafana.json na pasta docker/grafana/provisioning/dashboards. Acesse o link fornecido para obter o conteúdo desse arquivo e cole-o no arquivo recém-criado.

6. Adicione o serviço do Grafana ao arquivo docker-compose.yml:

grafana:
image: grafana/grafana
user: "472"
depends_on:
- prometheus
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
- ./docker/grafana/provisioning/:/etc/grafana/provisioning/
env_file:
- ./docker/grafana/config.monitoring
networks:
- back-tier
restart: always

7. Crie o volume grafana_data adicionando o seguinte trecho ao arquivo docker-compose.yml:

volumes:
...
grafana_data: {}

Atenção faça as alterações necessárias para adequar as configurações do seu arquivo.

Certifique-se de salvar todos os arquivos criados nas respectivas pastas. Com essas configurações, o Grafana estará pronto para ser utilizado.

Configurando tracer no Hyperf: Rastreando as informações da sua aplicação

Para começar a configurar o tracer em seu projeto, o primeiro passo é instalar a biblioteca do hyperf/tracer. Para isso, execute o seguinte comando dentro do container de sua aplicação Hyperf:

composer require hyperf/tracer

Em seguida, execute o comando abaixo para criar o arquivo de configuração para essa biblioteca:

php bin/hyperf.php vendor:publish hyperf/tracer

Após executar o comando acima, acesse o arquivo config/autoload/opentracing.php e substitua o conteúdo do arquivo pelas configurações abaixo:

<?php

declare(strict_types=1);

use Zipkin\Samplers\BinarySampler;

use function Hyperf\Support\env;

return [
'default' => env('TRACER_DRIVER', 'zipkin'),
'enable' => [
'guzzle' => env('TRACER_ENABLE_GUZZLE', true),
'redis' => env('TRACER_ENABLE_REDIS', true),
'db' => env('TRACER_ENABLE_DB', true),
'method' => env('TRACER_ENABLE_METHOD', false),
'exception' => env('TRACER_ENABLE_EXCEPTION', true),
],
'tracer' => [
'zipkin' => [
'driver' => Hyperf\Tracer\Adapter\ZipkinTracerFactory::class,
'app' => [
'name' => env('APP_NAME', 'skeleton'),
'ipv4' => '127.0.0.1',
'ipv6' => null,
'port' => 9501,
],
'options' => [
'endpoint_url' => env('ZIPKIN_ENDPOINT_URL', 'http://collector:9412/api/v2/spans'),
'timeout' => env('ZIPKIN_TIMEOUT', 1),
],
'sampler' => BinarySampler::createAsAlwaysSample(),
],
],
'tags' => [
'http_client' => [
'http.url' => 'http.url',
'http.method' => 'http.method',
'http.status_code' => 'http.status_code',
],
'redis' => [
'arguments' => 'arguments',
'result' => 'result',
],
'db' => [
'db.query' => 'db.query',
'db.statement' => 'db.statement',
'db.query_time' => 'db.query_time',
],
'exception' => [
'class' => 'exception.class',
'code' => 'exception.code',
'message' => 'exception.message',
'stack_trace' => 'exception.stack_trace',
],
'request' => [
'path' => 'request.path',
'method' => 'request.method',
'header' => 'request.header',
],
'coroutine' => [
'id' => 'coroutine.id',
],
'response' => [
'status_code' => 'response.status_code',
],
],
];

Após configurar o arquivo anteriormente mencionado, é necessário ativar o middleware para habilitar a função de coleta de informações. Siga as instruções abaixo para fazer isso:

  1. Abra o arquivo config/autoload/middlewares.php.
  2. Adicione o middleware de acordo com o exemplo abaixo:
<?php

declare(strict_types=1);

return [
'http' => [
\Hyperf\Tracer\Middleware\TraceMiddleware::class,
],
];

Com essas configurações, você estará pronto para começar a utilizar a tracer em seu projeto Hyperf.

Após concluir as configurações do Hyperf, será necessário atualizar as configurações do OpenTelemetry Collector para receber e propagar as informações para o Zipkin e Jaeger. Para fazer isso, siga as instruções abaixo:

  1. Acesse o arquivo docker/collector/config.yaml.
  2. Adicione uma nova configuração para os receivers. Veja o exemplo abaixo:
receivers:
...
zipkin:
endpoint: :9412

3. Em seguida, configure os exporters adicionando as seguintes informações ao arquivo de configuração:

exporters:
...
zipkin:
endpoint: "http://zipkin:9411/api/v2/spans"
jaeger:
endpoint: jaeger:14250
tls:
insecure: true

4. Após realizar as configurações acima, adicione a seguinte configuração para configurar os exportadores e receptores do trace:

exporters:
...
service:
pipelines:
...
traces:
receivers: [zipkin]
exporters: [zipkin, jaeger]

Após realizar as configurações anteriores para as métricas e trace. Seu arquivo ficará semelhante a este:

receivers:
zipkin:
endpoint: :9412
prometheus:
config:
scrape_configs:
- job_name: 'otel-hyperf-metrics'
metrics_path: '/metrics'
scrape_interval: 5s
static_configs:
- targets: [ 'app:9502' ]

exporters:
zipkin:
endpoint: "http://zipkin:9411/api/v2/spans"
jaeger:
endpoint: jaeger:14250
tls:
insecure: true
prometheus:
endpoint: '0.0.0.0:9502'
namespace: otel
send_timestamps: true
metric_expiration: 180m
resource_to_telemetry_conversion:
enabled: false

service:
pipelines:
traces:
receivers: [zipkin]
exporters: [zipkin, jaeger]
metrics:
receivers: [ prometheus ]
exporters: [ prometheus ]

Certifique-se de adicionar as configurações no local apropriado do arquivo de configuração existente. Com essa configuração, você estará pronto para receber as informações de trace do Hyperf e enviá-las tanto para o Zipkin quanto para o Jaeger através do OpenTelemetry Collector.

Agora que as configurações necessárias no OpenTelemetry foram feitas, é preciso adicionar os dois serviços ao arquivo docker-compose. Siga as instruções abaixo para adicionar os serviços:

  1. Acesse o arquivo docker-compose.
  2. Adicione os seguintes serviços abaixo das configurações existentes:
 zipkin:
image: openzipkin/zipkin-slim
networks:
- back-tier
ports:
- '9411:9411'
jaeger:
image: jaegertracing/all-in-one:latest
networks:
- back-tier
ports:
- "16686:16686"

Certifique-se de adicionar os serviços no local apropriado do arquivo docker-compose existente.

Com essas adições, você terá os serviços Zipkin e Jaeger em execução no ambiente Docker, prontos para receber e visualizar as informações de trace do OpenTelemetry. Lembre-se de salvar as alterações feitas no arquivo docker-compose antes de executar o ambiente Docker.

Melhorando a integração dos logs no Hyperf: Adicionando suporte para correlação com informações de rastreamento

As configurações padrão de logs no Hyperf possuem integração limitada com outros sinais de observabilidade, tornando os logs pouco correlacionados com as informações de rastreamento. Para solucionar esse problema, são necessárias algumas configurações adicionais no projeto.

  1. Faça a criação do arquivo app/Processor/TraceLogMessageProcessor.php
  2. Adicione o seguinte conteúdo ao arquivo:
<?php

namespace App\Processor;

use Hyperf\Context\ApplicationContext;
use Hyperf\Context\Context;
use Monolog\LogRecord;
use OpenTracing\Span;
use OpenTracing\Tracer;
use const OpenTracing\Formats\TEXT_MAP;

class TraceLogMessageProcessor
{
public function __invoke(LogRecord $record): LogRecord
{
$root = Context::get('tracer.root');

if ($root instanceof Span) {
$context = [];

$container = ApplicationContext::getContainer();
$tracer = $container->get(Tracer::class);

$tracer->inject($root->getContext(), TEXT_MAP, $context);
$record['extra']['opentracing-context'] = $context;
}

return $record;
}

}

3. Em seguida, acesse o arquivo config/autoload/logger.php e adicione a seguinte configuração:

<?php

declare(strict_types=1);

return [
'default' => [
'handler' => [
'class' => Monolog\Handler\ErrorLogHandler::class,
'constructor' => [
'messageType' => Monolog\Handler\ErrorLogHandler::OPERATING_SYSTEM,
'level' => env('APP_ENV') === 'prod'
? Monolog\Logger::INFO
: Monolog\Logger::DEBUG,
],
],
'formatter' => [
'class' => env('APP_ENV') === 'prod'
? Monolog\Formatter\JsonFormatter::class
: Monolog\Formatter\LineFormatter::class,
],
'PsrLogMessageProcessor' => [
'class' => Monolog\Processor\PsrLogMessageProcessor::class,
],
'processors' => [
new \App\Processor\TraceLogMessageProcessor(),
],
],
];

Com essas alterações, a integração dos logs no Hyperf será aprimorada, permitindo uma melhor correlação com as informações de rastreamento.

Observação: A configuração do código acima foi inspirada em uma configuração disponível no Github para o Opentracing. No entanto, para melhorar a funcionalidade, é possível fazer uma adaptação que utilize diretamente a span atual em vez de sempre utilizar a span global.

Acesso ao repositório no Github: Documentação e configurações de exemplo

No meu repositório no Github, você encontrará todas as configurações mencionadas anteriormente, as quais foram validadas e disponibilizadas por mim. Caso enfrente algum problema com as configurações fornecidas acima, é altamente recomendado que você verifique o repositório de modelo para obter informações atualizadas e detalhadas sobre as configurações.

Além disso, no repositório, você encontrará uma documentação abrangente que descreve os processos de configuração e explica como acessar os recursos relevantes. Mesmo se você não tiver dúvidas específicas sobre as configurações, é recomendado que você consulte a documentação para obter informações sobre como acessar e visualizar os serviços e as informações associadas.

Para acessar o repositório mencionado, basta clicar no seguinte link: ReinanHS/poc-hyperf-observability

Observabilidade no banco de dados

Existem várias maneiras de aumentar a observabilidade no seu banco de dados utilizando ferramentas específicas no contexto do Hyperf. Essas ferramentas permitem uma visão mais detalhada do que está acontecendo nas suas consultas SQL. Se você está interessado no assunto, recomendo a leitura da publicação abaixo:

Conclusão

Espero que esta publicação tenha fornecido uma visão inicial sobre os conceitos de observabilidade e como eles podem ser aplicados em um projeto Hyperf. As tecnologias mencionadas ao longo desta publicação são importantes e amplamente utilizadas no mercado, mas é importante ressaltar que existem outras tecnologias disponíveis.

Nesta publicação, selecionei algumas tecnologias que considerei relevantes e que podem ser utilizadas localmente por meio do Docker. Caso tenha se interessado pelo assunto, sugiro que leia as referências utilizadas para escrever este conteúdo, pois grande parte do conhecimento compartilhado foi extraído dessas fontes confiáveis.

A observabilidade é um tema amplo e em constante evolução, e é fundamental estar atualizado com as melhores práticas e as novidades do setor. Ao explorar as referências recomendadas, você poderá aprofundar ainda mais seu conhecimento e descobrir outras abordagens e tecnologias relevantes.

Lembre-se de que as ferramentas observabilidade são bastante poderosas para monitorar, depurar e otimizar seu projeto Hyperf, e espero que você possa aplicar esses conceitos de forma eficaz em seus próprios projetos.

Referências

Esta publicação foi embasada em algumas referências bibliográficas, que foram fundamentais para a construção do conteúdo apresentado. Recomendamos a leitura dessas referências, a fim de obter uma compreensão mais aprofundada do tema abordado neste artigo. Ao consultar essas fontes, você terá acesso a informações adicionais e poderá explorar aspectos específicos da observabilidade com mais detalhes.

--

--