Antes da gente avançar sobre o conceito de métricas, inclusive até fazer um hands-on de dashboards utilizando o Grafana, é importante entendermos alguns conceitos sobre o Permit, sobre alguns tipos de métricas, inclusive boas práticas sobre o uso dessas métricas. O Permit trabalha basicamente com três métricas. A primeira é o counter, que é apenas um contador. Ele é um número, uma métrica que ao longo do tempo, cronologicamente, é uma métrica que apenas aumenta, apenas cresce ou ela reseta o estado inicial. Por exemplo, o número de requisições e taxa de erros é um exemplo de implementação desse tipo de métrica. Se você tem uma aplicação rodando, faz sentido que você mensure a quantidade de requisições que aquela aplicação teve, ou aquele agrupamento teve, por exemplo, se você precisar, por exemplo, calcular a velocidade com que essas métricas estão crescendo, você pode usar uma função complementar que vai calcular basicamente a diferença, a distância de um ponto até o anterior. Por exemplo, no minuto, aqui na 15h50 teve uma mensuração, às quinze e quarenta e cinco teve outra aqui, então um menos o outro, cê consegue saber a distância e tem uma média ali de taxa de crescimento, tá? Mas em linhas gerais, o contador, o é apenas um número que cresce geralmente e ou ele pode ser resetado. Já o gauge ele é sim uma métrica que pode oscilar cada vez que você tira um uma foto desse dessa métrica ela pode estar em um número abaixo ou acima do que você tinha mensurado anteriormente exemplo disso por exemplo é inclui consumo de CPU em percentagem ou consumo de memória, quantidade de memória em bytes ou megabytes consumidas. A temperatura, por exemplo, é uma outra métrica que pode diminuir ou crescer de acordo com o momento que você tira a foto daquela métrica. E o terceiro e importante também é o histograma. O histograma é uma forma de representar a distribuição de frequência de dados em intervalos que são chamados de buckets. Um exemplo real do histograma seria, supondo que você tem uma população de pessoas dentro de uma sala, dentro de algum local, de algum ambiente, e você quer, por exemplo, classificar aquelas pessoas por grupos de idades. De repente, um grupo de pessoas X vai ter idades de, sei lá, de 1 ano a 10 anos. Outro grupo de pessoas vai ter de 11 anos a 20 anos. O terceiro grupo de 21 anos a 30 e assim por diante. E aí na hora de você mensurar, você pode chegar à conclusão de que você tem 30 pessoas de 31 anos a 40 e 5 pessoas de 51 anos a 60 e assim por diante. anos a 60 e assim por diante. Então, você pode concluir que determinados grupos de idades de pessoas têm mais ou menos incidência ou frequência naquele ambiente. Porém, o Promissos trabalha de forma um pouquinho diferente quando se trata de histograma. Supondo aqui que você tem um exemplo de total de requisições trabalha de forma um pouquinho diferente quando se trata de histograma. Supondo aqui que você tem um exemplo de total de requisições e você quer medir a latência dessas requisições. Supondo que você teve 275 requisições, dos quais 30 requisições retornaram dentro de 25 milissegundos ou em torno de 25 milissegundos, ou até, melhor dizendo, 25 milissegundos ou em torno de 25 milissegundos né ou até melhor dizendo 25 milissegundos e lá sem requisições retornaram até 100 milissegundos ou celades de 51 a 100 milissegundos 40 requisições retornaram até 200 milissegundos até que você tem aqui em cinco requisições que retornaram até 200 milissegundos até que você tem aqui cinco requisições que retornaram dentro de um segundo e meio porém o promissos trabalha de forma cumulativa ele não não tem essa esse formato aqui como da esquerda ele tem um formato mais da direita de forma cumulativa então você tem 275 requisições o último estágio se vai ter 275 requisições é e como é cumulativo ele só representa de forma que o primeiro grupo de números aqui de frequência somado ao segundo e consequentemente o terceiro e etc. Por exemplo, na primeira mensuração de 25 milissegundos, você identificou que 30 requisições retornaram dentro desse tempo. Porém, você tem 100 requisições que retornaram de 0 a 50 milissegundos. Você tem 200 requisições que retornaram de 0 a 100 milissegundos. Até, por exemplo, 270 requisições que retornaram de 0 a 100 milissegundos até por exemplo 270 requisições que retornaram de 0 até 800 milissegundos observe que é basicamente uma somatória por exemplo o o terceiro elemento aqui o terceiro grupo é basicamente a somatória do primeiro, mais o segundo, mais o terceiro. O último elemento é a somatória de todos. Então, se você precisa saber determinado grupo, bastaria você subtrair esses valores. É dessa forma que o Prometheus representa histogramas. E é importante você saber desses conceitos porque você pode criar suas próprias métricas. Além das que a gente já viu, você pode criar métricas customizadas e a implementação vai utilizar alguma variação de counter, de gaudi ou de histograma. se você acessar a aplicação e acessar aqui Actuator Promittals, você vai perceber que tem as métricas HTTP Server Requests, elas são básicas, elas tem aqui, por exemplo, a quantidade de requisições, com o count, o tempo que levou, enfim, a soma do tempo que levou aquelas requisições, etc. Se eu consultar, por exemplo, no Promitt de que eu vou calar as requisições etc a seu consultar por exemplo no promissos eu vou ter também a mesma informação para se buscar e que tipo server request caldo por exemplo eu vou ter basicamente as informações de quantidade de aquisição é isso eu buscar e por tempo de E se eu buscar por tempo, por exemplo, o Max, eu vou ter uma informação bastante simplificada, ou seja, sem o detalhe que a gente gostaria de ter, por exemplo, para saber se esse tempo de requisição está bom ou ruim. Então, o que a gente pode fazer? Então o que a gente pode fazer? Utilizar a configuração de SLO para montar um histograma para essa métrica especificamente. Então como que nós vamos fazer? Eu vou copiar essa configuração onde eu determino quais são os buckets em milissegundos que essa métrica xdip server request vai ter e aí por conta disso estou utilizando o service level objective para essa configuração de distribution eu vou copiar você pode configurar com outros formatos como percentis etc eu vou então na aplicação na application.yaml vou colocar assim mesmo sem organizar para a gente ver o resultado eu vou reinicializar a aplicação e quando ela inicia vou pausar o vídeo para não ficar muito longo pronto aplicação terminou de inicializar, eu vou acessar novamente o o aqui no da aplicação e vou dar um agora observe que eu consigo visualizar um outro uma outra métrica que chamada com sufixo e esse ele representa aquela configuração que eu fiz, ou seja, quantidade de requisições feitas que retornaram dentro de 25 milissegundos, 50 milissegundos, 100 milissegundos, 200 milissegundos, 400 milissegundos, 800 milissegundos e 1,5 segundo. Então, conforme eu for atualizando a página aqui, você consegue visualizar que os dados vão se alterando. E aí, como que eu leio essas métricas aqui? Nenhuma requisição levou menos do que 25 milissegundos. requisição levou menos do que 25 milissegundos. Porém, 25 requisições levaram até 50 milissegundos. 25, e aí você faz a subtração, 48 menos 25 requisições levaram 100 milissegundos. E isso não se altera até algumas requisições, pelo menos uma que aparentemente tá levou mais do que um segundo e meio para retornar tá é assim que funciona essa configuração vamos vamos dar uma olhada agora nessa mesma métrica lá na interface do promíteros o e aqui eu tenho a mesma visualização obviamente obviamente com os dados se atualizando. Vou fazer umas requisições em outras rotas, aqui aleatoriamente, só para a gente ver o reflexo disso na aplicação, no Prometheus. Enfim, apenas para teste, vamos rodar novamente, e observe que agora tenho outras rotas, então por exemplo a rota de orders e ele vai sempre agrupar pela configuração mais granular eu tenho a URI orders com método post e para essa combinação, e o status code 201 e para essa combinação eu tenho o histograma, os buckets específicos. Então observe que eu tive algumas requisições, por exemplo, uma requisição retornou em menos de, enfim, até 25 milissegundos, porém uma, então 2 menos 1 subtrai aqui, uma outra requisição levou 50 milissegundos e até até o último é a melhor até 800 milissegundos onde eu tive mais uma requisição que levou 800 milissegundos. Então, se eu continuar chamando, obviamente, os dados vão se alterando e atualizando. Vamos executar de novo. E agora eu tive... Pronto, aumentou aqui agora eu tive uma configuração muito parecida ainda, né? só subiu a quantidade de requisições eu tive três requisições que levou 25 milissegundos uma que levou 50 milissegundos e apenas uma que levou 800 milissegundos lembrando que a configuração de histograma pro promete-se ela é cumulativa por isso que eu tenho cinco requisições porque eu fiz um total de cinco requisições para rota de ordens que retornou do método post retornou 201 e das 5 requisições 3 retornaram dentro de 25 milissegundos 4 menos 3 1, 1 retornou em 50 milissegundos, como não teve nenhuma alteração, vou até o final eu sei que 1 das 5 levou 800 milissegundos bom, mesmo assim talvez você queira implementar métricas customizadas das 5 levou 800 milissegundos. Bom, mesmo assim, talvez você queira implementar métricas customizadas, mesmo após ter verificado a disponibilidade de uma vasta opção de métricas já disponíveis. Para isso, você precisa implementar ou incorporar a biblioteca Micrometer Core. implementar ou incorporar a biblioteca micrometer core essa biblioteca ela vai ter as classes, objetos, os bins necessários para você implementar as métricas customizadas. Então vamos começar informando aqui no .xml embaixo aqui do actuator uma questão de organização em cima do micrometer registry e agora precisamos implementar o de fato a configuração do do do método bom e e agora no passo 2 na classe que você deseja obter as métricas customizadas, você precisa incorporar o MeterRegistry. O MeterRegistry é o que você utiliza para registrar as métricas e ele que guarda aquela informação da aplicação e disponibiliza na rota de Prometheus a mesma rota que o Prometheus, o serviço, vem buscar e obter. a mesma rota que o Prometheus, o serviço vem buscar e obter. Então vamos começar incorporando essa classe, esse objeto na classe que nós vamos trabalhar, e vamos trabalhar na classe de OrderController, que é o controller que recepciona todas as requisições referentes à solicitação de produtos, por exemplo. Então, vamos começar a incorporar essa classe lá no método. Vou colocar no construtor. Vou declarar aqui mais acima para ser utilizado por toda a classe. mais acima para ser utilizado por toda a classe e vamos atribuir aqui pronto agora eu consigo utilizar o metaregistry para registrar novos novas métricas seguindo para o passo 3 vamos fazer dois exercícios básicos. Vamos utilizar um counter e um gaud. Para implementar um counter, lembrando que o counter é aquela métrica que apenas cresce, que incrementa. Você não determina o valor dela, você registra e vai incrementando conforme for necessário, conforme ocorrer as interações. Então, para isso, vamos criar na classe um counter e aí vamos monitorar aqui a quantidade de requisições feitas na rota de solicitação de novos produtos, de orders, a rota de novas solicitações. Talvez o exemplo não seja o mais rico aqui que a gente possa implementar, até porque você poderia, já tem métricas, melhor dizendo, específicas ali por rota, por acesso, mas apenas para mostrar a implementação aqui. Então vamos começar criando na classe esse contador vou criar como final e vou chamar de counter counter novas solicitacoins aí na classe de post orders que é onde nós criamos a order ah bom, e aí no construtor vamos declarar e construir esse counter vamos copiar esse trecho aqui que aí eu tenho a estrutura para a criação do counter. O counter basicamente começa com a classe counter.builder, o nome da métrica que você vai criar, possíveis tags, a descrição daquela métrica que explica sobre aquela métrica, e o método registry que de fato vai vincular esse counter com o middle registry aqui em cima. Então vamos começar configurando o nosso counter no construtor ainda. Ele vai se chamar counter novas solicitações e o nome é importante que seja um nome distinto das métricas já existentes vou começar como app custom e vou chamar de novas solicitar coins não vou informar nenhuma técnica aqui por enquanto e vou na descrição colocar na descrição colocar quantidade de novas solicitações realizadas com isso falta apenas uma coisa que é na rota de post eu vou colocar até no final da rota de post vou colocar lá no final chamando o método increment e esse increment que vai enviar para o meteredistry que nós registramos lá em cima na classe e ele vai ser atualizado a cada X tempo, enfim. E aí, para ficar mais organizado, deixa eu colocar um comentário aqui de métricas. Vamos subir a aplicação agora e vamos visualizar essa métrica no Promises. a aplicação agora e vamos visualizar essa métrica no Prometheus. Vou pausar o vídeo aqui, enquanto a aplicação sobe, já voltamos. Bom, a aplicação subiu, vamos agora conferir a nossa nova métrica. Vou copiar o nome da métrica aqui, vou no Insomnia, solicitar novas orders vou fazer duas solicitações vamos acessar a rota do Prometheus refresh e pesquisar pela métrica observe que agora aparece uma métrica aqui o app custom novas solicitações total e aqui o valor 2 vamos olhar como é que está agora no Prometheus essa métrica. Vou dar um refresh aqui. Vou filtrar por app, custom, novas solicitações, enter. E aparece também dois. Vou fazer mais três requisições. Vamos executar e foi. executar e foi. Lembrando que nós configuramos a aplicação para o Prometheus para vir a cada 3 segundos buscar as métricas. Então, eventualmente pode vai ter um delay de alguns segundos até que esse dado seja refletido de fato no Prometheus. Por exemplo, aqui apareceu 10 10 depois 14 como você observou então tem esse dele de 3 segundos e e vamos criar agora um gaudi é para a gente monitorar a quantidade de produtos solicitados, ou seja, a quantidade de produtos no carrinho de compra, vamos dizer assim. E esse valor pode variar em relação ao tempo. Enfim, apenas um exercício da métrica, do tipo da métrica GAUD, para você visualizar como que isso funcionaria. Vamos começar primeiro incluindo o atributo da classe Atomic Integer. Esse atributo não tem relação direta com o Gaudi, enfim, com a métrica, mas em vez de criar um int ou um big int especificamente para controlar esse valor, é interessante aqui utilizar o Atomic Integer porque ele suporta um contexto multi-thread, ele permite acesso concorrente de forma controlada, enfim, sem que isso gere impacto para a aplicação. vou chamar esse atomic integer aqui de gaud value e vamos apelidar de quantidade produtos bom, agora vamos construir o gaud em si no construtor da classe vamos incluir essa configuração embaixo aqui da configuração do count, e aqui ele começa pedindo o nome da métrica, vamos chamar também appCustom, e agora de quantidade produtos. O segundo parâmetro ele pede um um supplier que é basicamente um método, uma função você poderia por exemplo passar da seguinte forma poderia passar assim e colocar aqui um valor você poderia simplesmente passar também assim ou simplesmente chamar uma função você poderia simplesmente passar também assim ou simplesmente chamar uma função como nós criamos o atomic integer e ele tem um método get podemos simplesmente passar assim vamos chamar de gaudi valor gaudi velho e quantidade de produtos dois pontos dois pontos e get e aí esse get já é umodo, uma função que vai retornar o que precisamos. Só um detalhe aqui, vamos já inicializar esse gaudi também. Vou incluir aqui a inicialização desse atomic integer. Pronto, agora, e aí faltou a descrição claro né então vamos explicar que que é esse gaude vamos chamar de quantidade de produtos adquiridas quantidade de produtos nas solicitações de compra. Bom, e o que falta agora para esse GAUD? Precisamos agora pegar esse valor do Atomic Integer e alterar o valor especificamente, de acordo com a quantidade de itens solicitados aqui no new order. Vamos olhar para, aqui olhando para o insomnia, vamos pegar na relação de itens que tem aqui, vamos pegar essa quantidade que está aqui, somar com essa outra quantidade, e aí vai dar a quantidade de itens totais. Então já tem, então isso vai dar, vamos incluir aqui o incremento no new order, né? Então no new order vamos incluir a soma de itens aqui de quantidade que vai ser passada aqui na requisição. Dentro de itens eu tenho esse atributo quantidade, eu preciso somar todos os itens de quantidade que tiver nessa lista. Como que a gente faria isso? Vou incluir aqui embaixo o gal de produtos, isso aqui 7. E aí ele precisa de um valor. Como que eu vou chegar nesse valor? Eu vou pegar o item da requisição que tá vindo aqui, order.getItems até aqui eu peguei a quantidade de itens que tá que tá vindo aqui eu vou converter isso em string e aí eu quero até fazer um disclaimer um disclaimer aqui tô fazendo uma contagem aqui eventualmente complexa cuidado com esse tipo de implementação que pode afetar a performance da sua aplicação bom feito string eu vou mapear eu vou mapear para eu capturar aqui o de cada item aqui vou capturar o item de quantidade então eu posso fazer por exemplo é item por exemplo e um get quantity ou eu posso simplesmente fazer a classe order.getItem.getQuantity. Depois que eu fizer o mapeamento, agora eu preciso chamar uma função reduce. Essa função reduce vai pegar cada item de quantidade e somar eu posso por exemplo fazer integer dois pontos são e é ainda não terminou porque eu reduzo ele pode retornar um valor pode dar um erro pode retornar um nulo. Então, nesse caso, eu vou fazer e vou retornar um valor zero aqui por caso ele tiver algum problema. Então, só recapitulando, eu pego o que tá vindo na requisição, pego a relação de que é basicamente esse que tá dentro de aqui, itero sobre ele, converto em string para que eu itere sobre esses dados. Para cada item eu vou capturar o order item. O order item é basicamente a estrutura desse item aqui desserializada. Dentro de order, na classe de order, você tem a relação de itens aqui. dentro de order na classe de order você tem um e o a relação de itens aqui o que é basicamente da classe order item eu converto é pega o atributo quantit de cada item e faço reduce e aí ele vai somando item por item, quantity por quantity que está na requisição e caso dê problema ele vai retornar zero. E aí eu vou setar nesse valor GaudValue e esse GaudValue vai propagar essa alteração pro meterRegistry e no final vai aparecer na tela do Prometheus, no actuator Prometheus. Vamos rodar novamente a aplicação, desta vez deixa eu pegar o nome da métrica que criamos, de Cloud, esperar a aplicação subir, pronto subiu, vamos atualizar aqui, ou melhor, vamos fazer novas requisições. Eu fiz uma apenas, então, preciso visualizar naquela métrica 18 itens, certo? 10 mais 8. Atualizei e pesquisei, agora tenho 18 itens aqui. Vamos alterar esses valores. Se eu colocar, por exemplo, um item, agora eu preciso visualizar nove, quantidade desse, um mais esse oito, nove. Então, veio nove aqui também. Vamos olhar aqui no Prometheus para facilitar também. Vamos pesquisar a métrica. Deixa eu dar um atualizar. Vamos pesquisar a métrica. Total. Não. deixa eu dar um atualizar, vamos pesquisar a métrica total, não, produtos, isso, não tem nenhum sufixo, pesquisei, apareceu, tem nove itens, vamos mudar a quantidade de itens, vou diminuir esse para 1 também, agora tem que aparecer 2 e assim sucessivamente. Então, observe que o valor vai se atualizando. Agora tenho 4 itens. Bom, considerando que essa métrica que a gente está buscando, ela se altera em relação ao tempo, talvez você esteja se perguntando, como que eu faço para pegar o histórico do valor dessa métrica? Por exemplo, eu fiz uma atualização no horário x, ele trouxe um valor. Eu fiz uma refresh, consultei novamente, trouxe outro valor como que eu sei o histórico desse valor, de repente, pra quando eu colocar num gráfico, eu conseguir plotar essas alterações é possível? sim, o Prometheus tem essa configuração, assim essa função de range vector selectors, essa configuração aqui, essa carry esse modo de fazer carry só lembrando, essa documentação está aqui essa essa quer esse modo de fazer quer só lembra essa documentação está aqui no prometeu.com e o assunto aqui é que a rain basics ou fundamento de querem e essa função range vector select as permite você passar aqui a bracket sou colchetes e nesse colchete você pode passar um intervalo de tempo aqui por exemplo está fazendo uma uma uma filtro pelo request total aplicando um filtro aqui job promete-se aqui tá utilizando o ranger vector selectors o que que significa né esse ranger vector selectors permite aqui que você colete samples ou amostragem de dados voltando no tempo a partir do instante corrente e aí você sempre utiliza geralmente aqui de forma sintática sempre um time duration e aí mais informações tem aqui no link como que você pode informar, mas basicamente você pode informar o valor o número e o sufixo referente à duração que você quer capturar. Se você quer capturar o histórico em anos, em semanas, em dias, em horas, você coloca o valor e acrescenta o sufixo. Então, se eu quiser pegar por exemplo, o histórico desse app, custom quantidade de produtos no tempo, eu coloco um valor, supondo que eu queira, por exemplo, os últimos 10 minutos, então, M e entra. E aí ele vai trazer o histórico para mim. Por que o valor se repete? Lembrando que o Prometheus vem aqui na tela da aplicação para consultar a informação a cada 3 segundos então a cada 3 segundos ele vai consultar a informação e a informação não mudou então se eu fizer por exemplo novas requisições aqui vamos colocar agora valores maiores aqui por exemplo 88 itens mais 115 itens aqui ele vai somar e agora vou consultar lá embaixo, já já ele vai atualizar, vamos ver se ele atualizou agora, lá embaixo ele trouxe, ele teve duas leituras inclusive, então a cada 3 segundos ele está lendo o mesmo valor, vamos atualizar novamente, o mesmo valor vamos atualizar novamente vamos vamos diminuir agora para 83 aqui vamos aumentar isso aqui para 2115 vamos atualizar de novo e ele vai trazer agora o valor muito maior 2198 eu posso colocar configurações diferentes aqui por exemplo também posso colocar por exemplo quero dos últimos 10 segundos ela vai trazer os últimos 10 segundos último um minuto e assim por diante tá vamos fazer também com a outra métrica que nós tínhamos criado é porque são novas solicitações e vamos visualizar o valor dessa métrica no tempo não teve as solicitações total vamos visualizar aqui 10 segundos não mudou o valor né então é os últimos 10 segundos tá igual vamos fazer nova aquisição e agora trouxe 7 lá e aí ele vai sumindo porque eu não tô fazendo muitas requisições