Olá, vamos falar agora de meios de captura de logs, de métricas, de trace, e porque você precisa saber desse processo e caso você precise implementar ou customizar alguma ferramenta de observabilidade, o que você precisa levar em consideração. E aí eu já quero garantir que a gente está pisando no mesmo solo em relação a o quão distante esse componente de coleta e captura precisa estar da aplicação. E aqui, para garantir que a gente está pisando no mesmo solo nesse conceito, talvez para você seja óbvio ou não, é importante a gente pensar, e eu vou trazer dois elementos que suportem isso. O que você precisa se preocupar? Por que precisa estar separada da aplicação? Primeiro, que o processo de captura desses eventos de log métrica, por exemplo, não pode impactar o funcionamento principal da sua aplicação. Como diz o ditado, seria como se o rabo abandonasse o cachorro. Brincadeiras à parte, mas se a como diz o ditado, seria como se o rabo abandonasse o cachorro. Brincadeiras à parte, mas se a ferramenta de log, de observabilidade, de coleta de métricas, impacta o funcionamento, traz bug ou defeito para a sua aplicação, temos algum problema. Porque o que você está buscando entregar para o cliente final, você acaba não conseguindo entregar por conta de uma falha de observabilidade. Isso não é raro de acontecer, então é importante reforçar aqui. Exemplo, o serviço de observabilidade saiu fora do ar e aí o componente de observabilidade acabou tendo algum problema de performance, enfim, a aplicação parou de funcionar como deveria. E aí você vai acabar degradando a performance, enfim, acabar impactando a imagem da empresa que você está entregando o serviço e espero que não, mas pode ter alguma penalidade ali até financeira envolvida. Então é importante considerar isso e por isso que ele tem que estar apartado de alguma forma e a gente vai ver técnicas de como fazer isso, tá? Agora, um outro, por outro lado, se os eventos de log, de métrica, são tão importantes, porque você tem um SLA, um apetite por SLA muito forte, em termos de alta disponibilidade, resiliência da solução que você promete para o cliente, se a aplicação para de funcionar e você tem um forte acoplamento desse componente de coleta e captura, o efeito disso pode ser o inverso. Se a aplicação para de funcionar e os dados que você precisava enviar para a solução, serviço de observabilidade, você acabar perdendo. E aí é ruim, porque você não consegue ter dados suficientes para fazer algum troubleshooting e identificar a causa raiz do porquê que aquele serviço parou de funcionar, porquê que aquela aplicação parou de funcionar. E aí como que a gente resolve isso? Vou mostrar algumas formas de fazer, são alguns patterns arquiteturais, eventualmente pode ser que algum diferente, alguma ferramenta de observabilidade use diferente, ou use um mix dos patterns que eu vou mostrar. Então, vamos começar pelo primeiro. Uma forma mais simples de implementar esse processo é usar uma biblioteca. Tem várias, inclusive eu vou mostrar para vocês algumas já prontas. É sempre importante não reinventar a roda, porque tem muita coisa pronta já, mas eventualmente você vai utilizar uma biblioteca e essa biblioteca vai abstrair para você alguma coisa. Então, por que é importante, por que é relevante o uso disso e reforçar isso, esse conceito dessa biblioteca? Essa LIB, essa biblioteca, ela vai trazer alguns benefícios. Alguns deles, por exemplo, inclui aqui isolamento. Imagina você fazer alguma melhoria de observabilidade, ter que fazer teste unitário para testar aquilo, toda vez que você alterar, ou pior, pensando em padronização e reuso, imagina que você tem dezenas, centenas de aplicações, e precisa implementar o mesmo código várias vezes nas aplicações, de novo, acredito que para você deve ser óbvio isso, mas falando assim, talvez até seja. Mas é importante garantir que a gente está pisando no mesmo terreno nesse conhecimento. Então, um dos patterns é utilizar uma biblioteca que abstrai. E mesmo que você utilize uma biblioteca, agora você precisa levar em consideração o seguinte, aquela biblioteca, por mais que o código esteja isolado da aplicação, do ponto de vista funcional e em relação à implementação, a biblioteca ainda consome recurso daquela máquina, daquele container, daquela aplicação que você está utilizando, que você está subindo. Ela faz parte do seu jar, faz parte do conjunto de binários que você entrega no servidor, então ela vai consumir recurso daquela aplicação que você utiliza. Apesar de você reduzir o acoplamento funcional, existe um acoplamento na implementação, na infraestrutura, porque essa biblioteca faz parte do seu pack de binários que você entrega no servidor. E aí, enfim, essa biblioteca pode ser que ela tenha algumas técnicas para fazer isso. Por exemplo, ela pode enviar diretamente para o serviço de log, que talvez não seja tão bom, porque você vai consumir muito throughput de banda, de rede, vai ter muita latência, pode inclusive degradar a performance da própria aplicação, mas ela pode utilizar, por exemplo, o conceito de buffering, ela represa todo evento de log, de métrica que ela capturar, enfim, de trace que ela capturar, ela represa no disco e memória, e aí é um ponto de atenção, porque ela vai consumir recursos de computacional, mas ela represa e manda um lote de uma vez para o serviço que está de log de métricas aqui, por exemplo. E aí, de novo, a forma de implementar isso vai impactar diretamente no funcionamento da aplicação em geral, porque ela vai consumir eventualmente mais recursos computacional, maisória mais CPU ou se ela não tiver uma técnica de buffer mais throughput de rede aqui de conexão isso precisa ser ponderado tá é caso de uso é bem para log métrica daqui mas enfim são exemplos de implementação e aí como eu falei é se aplicação falhar os logs os dados que estavam presos ali podem acabar se perdendo se ele estiver utilizando o conceito de buffering. Agora, por outro lado, se a biblioteca crash, quebrar, por exemplo, o serviço de métricas ficou indisponível, e aí fez com que a aplicação lib quebrasse, por exemplo, agora ela não consegue tratar, ela não tratou aquele erro, não conseguiu represar os dados, enfim, ela pode acabar comprometendo o funcionamento da aplicação. E é até bom, às vezes, pensar em conceito de buffering, porque nesse caso, se o serviço parar de funcionar, ela consegue represar os dados temporariamente até que o serviço volte a responder. ela consegue represar os dados temporariamente até que o serviço volte a responder. Agora existem outros meios também, o outro conhecido também é o Sitecar, ou seria como se fosse um serviço de proxy aqui. Não é um pattern exclusivo de observabilidade, mas ele pode ser usado para fins de observabilidade. Ele é um pattern arquitetural em que toda requisição que entra para, por exemplo, um serviço externo fazendo solicitação para sua API, ou vice-versa, sua API se comunicando com o serviço externo, seja para acessar uma base de dados, acessar uma fila, um tópico Kafka, essa comunicação passa por um sidecar. Fazendo uma tangente aqui, o pattern de sidecar, ele é conhecido no mundo arquitetural de software, porque é uma forma, por exemplo, de você abstrair a complexidade de um serviço legado, permitir que esse serviço legado se comunique com serviços mais modernos, até que você use, enfim, aplicar técnicas, por exemplo, de estrangulamento, desidratar um serviço legado, enfim, você começa colocando essas peças de camada de anticorrupção e esses componentes de anticorrupção que fazem a tradução do serviço legado, eventualmente, para os componentes mais modernos. Nesse caso, ele pode ser utilizado para a implementação aqui da observabilidade nas aplicações e um caso muito comum é Tracing porque fica bem mais fácil até de toda requisição entra para sua aplicação você registrar aquele evento e jogar no blog é ótimo e melhor ainda se aquela aplicação estiver separada da sua infraestrutura tá daria para utilizar Libs. Por exemplo, mas aqui eu estou falando de um componente que não é apenas uma thread na minha aplicação, ele é um serviço que sobe junto com a minha aplicação, ele pode até não ter um container dedicado para ele ou não, e ele que faz essa comunicação, tá? E aí, de novo, a forma que implementa essa solução, ele pode represar os dados de uma vez, ou pode mandar todos de uma vez, mas o ponto é que ele atua como um proxy da aplicação. E aí, como eu falei, ele pode utilizar um processo separado, dentro do container ou fora do container, e isso garante já, em um pouco, o isolamento da aplicação. Agora, também tem o seu trade-off, também tem o seu ONU aqui. Se esse componente falhar, ele é o ponto único de entrada e de saída de comunicação do seu serviço com o mundo externo. Se ele falhar, eventualmente até o health check que o balanceador fizer a requisição, ele talvez não vai conseguir responder e o balanceador vai entender que aquela aplicação não está saudável. Então, é interessante o uso, é uma forma de usar, mas precisa ser levado isso em consideração. Uma outra forma de captura de eventos é o uso de collectors externos, é o uso de componentes de coletor né é só que indiferente diferente por exemplo dos padrões em que os eventos são capturados e é esse serviço que envia é no caso é por exemplo site cara da biblioteca é e é o cole collector que faz a requisição para a API para coletar esses dados. É diferente agora. Em vez da aplicação disponibilizar, fazer o push do dado para o serviço, e esse serviço que vai enviar externamente, agora é inverso. A aplicação disponibiliza um endpoint, uma rota, e o collector vem buscar esses dados no endpoint. Considerando que você está em um ambiente complexo, que tem vários serviços distribuídos, eventualmente utilizando uma infraestrutura mais complexa como o Kubernetes, e você precisar implementar toda a solução de Service Discovery, fica difícil esse collector saber aonde precisa bater, e onde fazer requisição. Então, a aplicação faz uma notificação para o serviço de collector, dizendo, olha, cheguei na área, vem buscar os dados aqui. E aí ela disponibiliza uma rota de métricas, e o collector que vai buscar nessa rota, por exemplo, e ele coleta as informações necessárias ali, que, enfim, de acordo com os dados que você disponibilizou. Eu vou trazer, não querendo dar spoiler, mas vou falar depois sobre implementação de métricas, vou citar ferramentas como o Prometheus, ou a biblioteca Micrometer no Java, e é um pattern que essa solução utiliza para fazer coleta de métricas e mandar para o serviço aqui, responsável pelas métricas. O outro meio de captura, por exemplo, para logs, um caso de uso para logs, seria a aplicação escrever, de fato, em algum lugar, entre aspas, esse nesse lugar que esse lugar pode diferenciar lá antigamente você não tinha soluções contêinerizadas você precisava subir sua aplicação no mente o Windows ou Linux e precisava implementar solução de login na mão era comum que a aplicação escrevesse os logs numa pasta no disco, conforme ela... Enfim, ela fazia um conteúdo de buffering para saber o que escrevia, e escrevia de uma vez alguns dados lá, e aí você tinha que ter um componente para coletar esses eventos e mandar aqui para o serviço de login. Por exemplo, aqui poderia até, inclusive no Windows, ser o Event Viewer, ou no disco mesmo, um arquivo separado no Linux, de repente na pasta VAR Logs com a pastinha da aplicação e você tem um componente que captura esses logs dessa pasta em ambientes mais atuais, mais modernos que utiliza a Docker de fato o Docker tem, em soluções containerizadas, tem uma área de buffering que ela consegue capturar os eventos de sysout de login de sysout da aplicação e disponibilizar nessa área e ela já implementa um serviço de log driver um componente né que é seguindo ali o padrão open closed né é uma forma que você consegue estender e aí você consegue customizar enfim aí vários provedores ali de login tem um agent customizado que consegue integrar com a solução de container que você utiliza, capturar esses eventos que estão chegando nessa área e mandar para o serviço de login. Então, o Docker é um exemplo muito, muito prático disso.