· 6 min de leitura

Observabilidade com Hyperf e OpenTelemetry

No PicPay, para melhorar a escalabilidade de nossas aplicações feitas em PHP, nós utilizamos a _Swoole_ como _runtime_ de alta-performance tornando as aplicações assíncronas e n...

No PicPay, para melhorar a escalabilidade de nossas aplicações feitas em PHP, nós utilizamos a Swoole como runtime de alta-performance tornando as aplicações assíncronas e não-bloqueantes.

Começar a utilizar a Swoole trouxe alguns desafios, um deles é o da observabilidade, vamos entender mais a frente.

Photo by Davyn Ben on Unsplash

Observabilidade

Observabilidade é a metodologia que o mercado de microsserviços e cloud-native explora para monitorar as aplicações, saber como os recursos estão sendo utilizados, se a aplicação está entregando o que ela se propõe fazer e se tiverem erros, e como identificá-los.

Para isso, são definidos três pilares (e talvez um quarto):

Métricas

Métricas são medidas de avaliação quantitativa comumente usadas para comparar e acompanhar o desempenho ou a produção. Quantas vezes aconteceu.

Traces

Conjunto de Spans, são a coleção de lugares por onde o clico de vida de uma transação passou. Onde aconteceu.

Logs

Informações sobre qual era o atual contexto no momento que algo aconteceu durante o clico de vida de uma transação. O que aconteceu.

Eventos?

É cada vez mais comum separar logs de eventos e muitas pessoas veem como o quarto pilar da observabilidade. Eventos são informações sobre regras de negócio. Dados personalizados sobre a experiência de um determinado fluxo de dados. A maior diferença para os logs é que aqui não ficam dados sobre infraestrutura.

Hyperf

Hyperf é o framework web que adotamos para as aplicações PHP em Swoole. Os pontos que nos levaram a utilizá-lo foi por ele ter corrotinas como cidadãs de primeira-classe. O Hyperf foi feito para a Swoole, ele não foi adaptado para a Swoole como seria com outros frameworks de mercado como Laravel, SymfonyLaminas.

Todos os componentes dentro dele estão preparados para trabalhar com corrotinas usando pool de conexões, evitando estado global utilizando os contextos das corrotinas e evitando ao máximo memory-leaks já que agora a memória do processo não vai ser limpa a cada requisição e com isso também vem o cuidado de não fazer os dados de um requisição afetar a outra.

Resumidamente, o Hyperf está preparado para trabalhar da forma stateful que é totalmente o contrário da forma stateless do PHP-FPM tradicional.

Feito para microsserviços

Outro ponto muito legal que corroborou com nossa escolha, é a forma como o foco do Hyperf fica em microsserviços. Ele não se preocupa com coisas como views e sessões, coisas que são mais utilizadas na construção de sites.

No lugar, o Hyperf entrega componentes que foram pensados em microsserviços e no mundo cloud, coisas como: circuit-break, rate-limit, service-discovery, remote-config, gRPC etc.

E, claro, junto desses componentes cloud-native focados em microsserviços, tem os componentes para Observabilidade.

Problemas com APMs

Geralmente a observabilidade de aplicações é feita de forma trivial através de APMs. O provedor do serviço de monitoramento, por exemplo o New Relic, fornece um APM que pode ser adicionado ao servidor para rodar junto com a aplicação e ele faz a instrumentação do que está acontecendo.

Os APMs fazem isso utilizando uma técnica chamada Monkey Patch, essa técnica é uma forma de adicionar comportamento em tempo de execução. Quando você chama o cURL através das funções curl_, por exemplo, na verdade você tá chamando a biblioteca da New Relic que, por sua vez, chama a cURL padrão do PHP, mas no meio disso adiciona o comportamento que faz a instrumentação.

A Swoole tem uma feature chamada Runtime Hooks, que faz com que recursos atuais do PHP, como o cURL, PDO, Redis etc funcionem de forma assíncrona, dentro de seu event-loop e a Swoole faz isso utilizando a mesma técnica de Monkey Patch, sobrescrevendo as funções nativas do PHP para adicionar esse comportamento novo.

Aí vem o problema: duas extensões, cada uma querendo fazer o monkey patch, a sobrescrita das mesmas funções nativas do PHP. Elas entram em conflito e no fim nenhuma funciona.

OpenTelemetry

Uma das formas que encontramos para resolver esse problema com os APMs foi fazer a instrumentação utilizando o próprio PHP ao invés de APMs. Deu super certo, funcionou, felizmente a New Relic tem uma API REST, na verdade APIs REST que são exatamente 1:1 para os pilares, uma API para métricas, para traces e para eventos. Fazíamos a instrumentação de forma manual e enviávamos os dados para essas APIs.

O problema disso é que houve muita mistura entre código de regras de negócio e código de instrumentação, as classes e o métodos ganhavam mais linhas de coisas que não tinham relação direta.

De qualquer forma, foi por meio dessa ideia de instrumentar com o PHP que descobrimos o OpenTelemetry.

O projeto OTel é a fusão dos projetos OpenTracing e OpenCencus, ou seja, já existiam iniciativas para Observabilidade utilizando formatos abertos. O OpenTelemetry juntou essa galera para uma fundação e organização.

Já existiam projetos para o PHP de OpenTracing que geravam formatos abertos como Jaeger e StatsD e esses projetos forma herdados no OpenTelemetry. Essa foi a peça que faltava pra encaixar o ecossitema de observabilidade que já funcionava muito bem ao OpenTelemetry, por meio do seu componente de Collector, foi a peça que encaixou esses formatos abertos com o New Relic.

Lembra que o Hyperf é todo focado em microsserviços, inclusive na parte de Observabilidade? Então, ele mesmo já provê dois componentes chamados hyperf/trace e hyperf/metric que servem justamente para fazer a instrumentação das aplicações em Hyperf e exportá-las para formatos abertos.

Instrumentação com AOP

Um ponto bem legal sobre a instrumentação para evitar aquele problema de ter ela misturada com regras de negócio e código que faz outras coisas, é que o Hyperf utiliza uma técnica chama AOP, de Aspect Oriented Programming, ela é uma forma de implementar Monkey Patch (lembra dele?), ou seja, a gente consegue adicionar comportamento (no caso de instrumentação) em classes, métodos e funções, sem de fato alterar o código delas.

Só que dessa vez, esse monkey patch feito com AOP fornecido pelo Hyperf, é feito com o próprio PHP, não temos o problema de conflito com o monkey patch feito pela Swoole para deixar os componentes do PHP não-bloqueantes.

Recomendo bastante darem uma lida na técnica: https://en.wikipedia.org/wiki/Aspect-oriented_programming

Conclusão

Aplicação feita com Hyperf

É instrumentada e exporta os dados em formatos abertos, como JaegerStatsD.

OpenTelemetry Collector

Por ser a junção do OpenTracing com o OpenCensus, herda a possibilidade de receber formatos abertos (como Jaeger e Statsd) e tem suporte da própria New Relic para exportar os dados para sua plataforma.

New Relic

Super parceira do projeto, apoia a iniciativa e vem dando cada vez mais suporte para receber os dados que foram gerados pelos componentes do OpenTelemetry.