Olá, vamos para a fase 2 aqui do hands-on. Quero começar trazendo aqui um conjunto de passo a passo para a gente conseguir instrumentar a nossa aplicação. E neste vídeo, especificamente, a gente vai apenas fazer a instrumentação necessária da aplicação, de forma que eu consiga garantir que os logs de saída estejam no formato apropriado para integrar a ferramenta de observabilidade. E aí, independente de qual vai ser, se vai ser o Splunk, enfim, ou Elasticsearch, ou alguma ferramenta, alguma outra. E aí, a ideia nesse vídeo aqui é explicar essa instrumentação lá no lado da aplicação, e nos próximos a gente vai fazer uma implementação. Vou mostrar como subir aqui um ambiente onde a gente vai ter a aplicação de coleta de log, de visualização integrada e a aplicação integrada a ela, gerando os eventos de log. É um passo a passo simples, tá? passo a passo simples, tá? Primeira coisa que a gente precisa ter na classe que vai utilizar a observabilidade, ela precisa implementar a interface aqui do SLF4J. Como é que é feita essa implementação? A gente tem um objeto log e utiliza um conceito de singletool aqui, onde eu chamo a interface logfactory, getlogger, ele vai pegar a instância ali, enfim, vai ter um reaproveitamento de dados aqui de elementos em memória e aí eu digo o nome da classe que esse log vai estar relacionado por que eu informo o nome da classe? no log de saída eu posso dizer da onde part No log de saída, eu posso dizer de onde partiu aquele evento de log, de qual classe, isso facilita, por exemplo, o troubleshooting, fica mais fácil reduzir o raio de busca, se eu identificar algum erro, ou alguma mensagem que não faz muito sentido, entender na hora de fazer o troubleshooting, facilita muito eu encontrar a classe, de repente, em uma aplicação monolítica, que tem várias classes. Então, eu uso esse componente. Um dos motivos é esse, eletificar a classe no monolog. Vamos olhar na aplicação. Nós já estamos fazendo isso. E aí, essa implementação utiliza o SLF4J, só que eu estou utilizando o Lombok, não sei se você usa, conhece, eu particularmente gosto, traz uma boa produtividade, mas resumindo, o Lombok apenas faz aquilo que você faria, só que de forma automatizada, em tempo de compilação, ele gera os artefatos de objetos de campos, de métodos por exemplo, os getters, setters que você teria que implementar na mão sem ele talvez você já conheça usa ou não, então acho que é importante te garantir que está pisando no mesmo solo de conhecimento, então tem aqui o Project Lombok, tem um plugin, a ideia é que você precisa instalar também, e aqui eu estou fazendo referência aqui usando o SLF4J, exemplo na classe OrderController aqui. Mas na prática, quando eu compilar, eu posso mostrar aqui, por exemplo, na pasta target, classes, store, e entrar aqui, por exemplo, order e controller, você vai perceber que ele gerou pra gente uma linha que tem o logger como estático aqui, logger factory, get logger e o order controller, que é o nome da classe que ele vai utilizar. Repare também que o logger factory ele pertence a interface SLF4J. Buscar aqui é para mostrar. SLF4J faz parte da interface. Então esse objeto está utilizando a interface do SLF4J. Então eu estou utilizando o Lombok, ele está gerando para a gente. Outro ponto interessante é que é interessante que esse objeto esteja estático na classe, porque aí você garante que toda a instância daquela classe, você tem um reuso do ou seja, se você tiver várias instâncias da mesma classe, é menos um objeto que vai ser instanciado, seja menos espaço de memória que você vai ocupar. Isso é interessante. Então, então eu estou utilizando esse pattern aqui de singleton para classe o segundo passo implementar de fato os logs que você precisa visualizar depois o legal da interface dessa level4j é que ela permite fazer bastante coisa legal. Por exemplo, eu tenho uma mensagem aqui, e eu consigo interpolar argumentos nessa mensagem. Então, login, info, mensagem de login, parâmetro, e aí eu estou dizendo, vou receber um parâmetro, e aí ele é inteligente o suficiente, tem na sua implementação o mecanismo de interpolar o conteúdo que vem nesse argumento dentro desse ponto exatamente. Eu posso ter múltiplos argumentos também, por exemplo, login mensagem, e eu tenho parâmetro 1, ele vai cair aqui parâmetro 2 vai cair aqui e aí a ordem que eu passar nos argumentos ele vai cair aqui você pode utilizar outros elementos como o debug aqui, eu estou fazendo um exemplo de uso de debug mais apropriado para o debug, que aí eu estou fazendo um exemplo de uso de debug mais apropriado para o debug que aí eu estou dizendo olha agora estou somando dois números aí eu estou passando exatamente a forma o número mais outro número igual ao número x e aí estou passando a ordem dos valores v1 vai pra cá v2 é pra cá e v3 vai aqui e por fim você pode ter o log de erro, onde você consegue ter a mensagem e interpolar a exceção aqui também. Tem outros elementos, por exemplo, aqui tem no SLF4J tem o log, por exemplo, o log warn. Então, não é nem nenhum erro, é um erro informacional, né? Então você pode utilizar também, se alguma coisa não tiver muito legal. Exemplo, você fez um acesso ao connection pool ou está acessando alguma informação e você tem uma e aí você percebe que algum dado que deveria vir preenchido não está vindo e você pode ter uma regra e logar um ordem ali, dizendo, olha, estou sentindo falta do campo X. Até aqui, deixa eu mostrar que já está implementado no código. Aqui, então, eu tenho, por exemplo, na classe de logger, eu já tenho isso implementado aqui. Por exemplo, no getOrders, eu estou logando como info a quantidade de elementos retornados na requisição no caso de order por id, eu estou informando o id da requisição no info e eu estou usando o log debug para eu dizer o objeto para eu mostrar o objeto que está sendo retornado naquela requisição eu vou explicar mais a frente, mas existe uma hierarquia de log então uma vez que eu determino o debug mas lá na saída eu determinar que o log é info o log máximo é info é isso que eu estou dizendo, o log level máximo ele começa do aí depende da ordem do conceito, mas ponto é se eu disser que eu vou logar só loginfo, ele vai logar logs error, warn e info e pronto. Ou seja, eu não preciso mexer no meu código, mas lá na saída ele vai simplesmente ignorar esses eventos, vai largar, vai deixar cair no caminhão mesmo, e não vai enviar para a ferramenta de observabilidade. Eu não preciso tirar o log debug, eu apenas mexo na configuração que a gente vai ver mais à frente. O ponto é que se eu disser também log debug, aí esses eventos vão começar a aparecer, e aí tem que ver o interesse. De novo, revisitando as nossas boas práticas, as boas práticas do Browse, é importante levar em consideração do ponto de vista de segurança e privacidade de dados. Aqui como é teste, eu estou apenas mostrando o uso. O orders, new order aqui, que é a rota de post para cadastrar uma nova ordem, ela já é um pouquinho mais complicadinha, então tem bastante log. Por exemplo, eu tenho um login, assim que a requisição chega, eu tenho um login, se caso, por exemplo, como é um carrinho de compras e o cliente está passando uma lista sem itens, ou seja, uma requisição sem itens, eu preciso dizer, olha, não tem itens cadastrados, aí eu posso logar essa informação e como debug eu posso colocar os dados da requisição que vieram e eu retorno uma exceção que vai para o cliente que tá fazendo a requisição depois eu vou trazer como que a gente pode logar de forma centralizada esses eventos de exception utilizando o Spring Controller, o REST o conceito de Advice no Spring aqui determina status comum, progress por default, aqui eu vou fazendo outro log debug dizendo, olha, a partir de agora eu vou fazer um cálculo, vou calcular o preço total, e por que eu faço esse processo? Eu faço duas coisas aqui. Primeiro é, eu preciso na lista que ele passa de produtos, que na requisição aqui abriu em somnia pra mostrar, ele faz uma requisição passando o ID do produto e a quantidade. Aí eu validei se essa lista não tá em branco. E se o... E aí eu consulto pelo produto, porque aqui ele pode passar um produto incorreto que não existe. Então, eu já faço duas consultas e já mato dois coelhos aqui. Primeiro, eu consulto o produto e valido se ele existe, se não existiu, eu retorno uma exceção. E se ele existe, eu consulto o valor do produto. E aí eu faço o cálculo, pego o valor do produto, aí eu tenho produto, quantidade, pega o valor do produto eu tenho produto quantidade produto quantidade eu pego o valor do produto multiplico pela quantidade e aí eu vou sumando tudo no final onde eu defino o cálculo preço aqui é fazer uma tangente é claro que sempre a minha nação de venta numa calça apartada de piso não a beliliou uma camada e não não é que sagonal mas aqui é importante é a minha minha objetiva que é buscar a simplicidade que a gente focar apenas na implementação da observabilidade aqui no final depois que ele fez o cálculo eu uso de bug para dizer olha vou gravar isso aqui na base ele gravou ele retorna que objeto objeto gravado eu faço outro devolver 19 a salvou com sucesso e o retorno é se eu tiver por exemplo é que aqui é um cruz simples mas é importante frisar que eu tenho muito mais logo de bugs do que login foco é imagina se eu tivesse habilitando eu tivesse recebendo por exemplo milhares de requisições no minuto imagina por minuto a cada 10 minutos imagina o quanto de eventos de log que eu não estaria acumulando enviando para o serviço então é tem que ser usado com parcimônia e correto entendimento mesmo para a rota aqui de cancelamento tá eu tenho log de bug para rota de cancelamento com order, tem o log também pra roda de complete. Pô, e como que eu trato esses eventos de exceção aqui? Tá fora do escopo, mas tá fora do escopo do objetivo aqui, mas a gente pode tratar os eventos utilizando o conceito de advice. Aqui, por exemplo, em config, eu o REST controller advice e esse REST controller advice ele captura qualquer evento que está subindo para a camada de controller ele captura os eventos e diz, ah, chegou um evento de customer not found? Chegou. Então ele vai ser direcionado para esse método. E aqui no método eu tenho um log error. Log error de mensagem, logError, ou no caso, quando, por exemplo, a ordem, a solicitação veio com itens inválidos, ou sem itens na lista, ou quando o produto não existe, logErrorMessage e eu crio uma mensagem de saída. Então, até aqui está implementando até a etapa 2. Aqui a gente conseguiu atingir até a etapa 2, por enquanto. E aí, para demonstrar, por exemplo, se eu abrir aqui e fizer uma requisição post de um produto válido, eu reiniciei a aplicação, então ele vai reiniciar o computador, vou fazer mais outro para ter. Aqui tem o ID3. reiniciei a aplicação que ele vai iniciar o computador fazer mais outro para bater aqui até o ar de três se eu vier na aplicação agora e abrir aqui por exemplo os blogs exaltam que estão aqui em lá ele vai mostrar aqui para gente é por exemplo e cadê aqui ó request new order request new order e só os debug não estão saindo porque não está validado por padrão para sair logo que debug só login fazer uma nova requisição vou fazer uma requisição por id agora get por id que é isso de baixo aqui o aí de dois a la request for the baia de se eu fizer uma questão de um produto inválido por exemplo produto ordem 222 fazer erro não pode encontrar a ordem e aquele vai dizer ó os notifiais ordem 222 e a exceção aqui no detalhe, could not find order 222, está aqui, a stack trace, legal? O log não é o melhor, vamos melhorar a partir de agora.