<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: RaVi</title>
    <description>The latest articles on DEV Community by RaVi (@rafaelvitor).</description>
    <link>https://dev.to/rafaelvitor</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F378939%2Fdff5cfb8-b4ac-4f01-b82d-f5341590386b.jpeg</url>
      <title>DEV Community: RaVi</title>
      <link>https://dev.to/rafaelvitor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rafaelvitor"/>
    <language>en</language>
    <item>
      <title>Distributed Tracing com plugins do OpenTelemetry, Node e Jaeger</title>
      <dc:creator>RaVi</dc:creator>
      <pubDate>Mon, 09 Jan 2023 00:49:24 +0000</pubDate>
      <link>https://dev.to/rafaelvitor/distributed-tracing-com-plugins-do-opentelemetry-node-e-jaeger-22oj</link>
      <guid>https://dev.to/rafaelvitor/distributed-tracing-com-plugins-do-opentelemetry-node-e-jaeger-22oj</guid>
      <description>&lt;p&gt;&lt;a href="https://medium.com/opentelemetry/opentelemetry-is-officially-in-beta-352fa859db10" rel="noopener noreferrer"&gt;No dia 30 de março&lt;/a&gt; foi anunciada a fase beta do OpenTelemetry. O objetivo do projeto é facilitar o rastreamento distribuído através de uma série de ferramentas integradas como descrito no meu &lt;a href="https://dev.totodo:link"&gt;primeiro artigo&lt;/a&gt; sobre o assunto. Entre as metas estabelecidas para o lançamento do beta estava a integração de plugins que permitem instrumentação automática das aplicações, diminuindo de forma significativa o trabalho necessário para implementação. Os repositórios das bibliotecas já funcionais e em desenvolvimento podem ser encontrados na &lt;a href="https://github.com/open-telemetry" rel="noopener noreferrer"&gt;página do projeto no github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Esse artigo trás um exemplo de Distributed Tracing de aplicações Node usando http, &lt;a href="https://dev.tolink"&gt;Express&lt;/a&gt; e &lt;a href="https://dev.tolink"&gt;IORedis&lt;/a&gt; para simular o monitoramento de uma arquitetura de micro serviços usando a API javascript do OpenTelemetry e os plugins de instrumentação automática de cada módulo. Vamos explorar brevemente pedaços de código para ilustrar o funcionamento do sistema e o que é necessário ser feito para ter as informações de execução disponíveis no Jaeger como na imagem: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F2mZ2RMj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F2mZ2RMj.png" alt="Imgur"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Visualização dos spans de um trace na interface do Jaeger&lt;br&gt;

 &lt;/p&gt;

&lt;p&gt;Nossa implementação de exemplo consiste em dois servidores, o primeiro simula uma API que serve de primeiro ponto de contato na comunicação e repassa as requisições para o segundo, que é responsável por buscar os dados necessários acessando o &lt;a href="https://dev.tolink"&gt;redis&lt;/a&gt;. Recomendo muito dar uma olhada no código completo &lt;a href="https://dev.tolink"&gt;aqui&lt;/a&gt; e para rodar basta fazer &lt;code&gt;docker-compose up&lt;/code&gt; ou seguir as instruções para cada serviço. No compose temos os containers de cada serviço e o &lt;a href="https://dev.tolink"&gt;Jaeger&lt;/a&gt; que vai servir como backend e interface para análise dos spans coletados.&lt;/p&gt;

&lt;p&gt;Como uma aplicação de exemplo, o funcionamento é bem simplificado. Ao acessar &lt;code&gt;localhost:3000&lt;/code&gt; pela primeira vez um resultado vazio é retornado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FUlffjf3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FUlffjf3.png" alt="Imgur"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essa rota acessa o middleware e pede os valores para as keys &lt;code&gt;key1&lt;/code&gt;, &lt;code&gt;key2&lt;/code&gt; e &lt;code&gt;key3&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// api.js&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;get /&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;middleware_url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;httpRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middleware_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;resultList&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usamos a rota &lt;code&gt;/set-values&lt;/code&gt; para popular esses valores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// api.js&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/set-values&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testItens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;key3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;testItens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;httpRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middleware_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/set?key=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;value=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e agora ao acessar &lt;code&gt;localhost:3000&lt;/code&gt; obtemos os valores para as chaves solicitadas:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FJOqLS4F.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FJOqLS4F.png" alt="Imgur"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se você rodou o código a partir do repositório completo e fez esses 3 passos já pode visualizar os traces gerados na interface do Jaeger em: &lt;a href="http://localhost:16686" rel="noopener noreferrer"&gt;http://localhost:16686&lt;/a&gt; selecionando o Service &lt;code&gt;api&lt;/code&gt; e clicando em &lt;em&gt;find traces&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F5eE4GKZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F5eE4GKZ.png" alt="Imgur"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isso é possível graças aos plugins do OpenTelemetry. Com a instrumentação automática não é preciso mudar cada parte do código para adicionar o tracing. Os plugins fazem patch dos módulos e escutam as chamadas internas adicionando a passagem de contexto onde é necessário.&lt;/p&gt;

&lt;p&gt;No topo dos arquivos &lt;code&gt;api.js&lt;/code&gt; e &lt;code&gt;middleware.js&lt;/code&gt; você verá:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createTracer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./tracer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;createTracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O tracer importa as bibliotecas do OpenTelemetry e inicializa o &lt;a href="https://github.com/open-telemetry/opentelemetry-js/tree/master/packages/opentelemetry-node#usage" rel="noopener noreferrer"&gt;&lt;code&gt;NodeTracerProvider&lt;/code&gt;&lt;/a&gt; que precisa ser definido antes do import dos &lt;a href="https://github.com/open-telemetry/opentelemetry-js#plugins" rel="noopener noreferrer"&gt;módulos suportados&lt;/a&gt;. Aqui também é configurado o exporter do Jaeger.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tracer.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;opentelemetry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@opentelemetry/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NodeTracerProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@opentelemetry/node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;JaegerExporter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@opentelemetry/exporter-jaeger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SimpleSpanProcessor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@opentelemetry/tracing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createTracer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NodeTracerProvider&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;exporter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JaegerExporter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jaeger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addSpanProcessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SimpleSpanProcessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exporter&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;opentelemetry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;createTracer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>opentelemetry</category>
      <category>node</category>
      <category>jaeger</category>
      <category>express</category>
    </item>
    <item>
      <title>O que é OpenTelemetry? Distributed Tracing - Observability numa arquitetura de micro serviços</title>
      <dc:creator>RaVi</dc:creator>
      <pubDate>Mon, 18 May 2020 03:32:20 +0000</pubDate>
      <link>https://dev.to/rafaelvitor/o-que-e-opentelemetry-distributed-tracing-observability-numa-arquitetura-de-micro-servicos-3gn5</link>
      <guid>https://dev.to/rafaelvitor/o-que-e-opentelemetry-distributed-tracing-observability-numa-arquitetura-de-micro-servicos-3gn5</guid>
      <description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Single-responsibility_principle" rel="noopener noreferrer"&gt;O Princípio de responsabilidade única&lt;/a&gt;, cunhado por Robert C. Martin, basicamente diz: "junte as coisas que mudam pelo mesmo motivo, e separe as coisas que mudam por motivos diferentes". &lt;/p&gt;

&lt;p&gt;Uma arquitetura de micro serviços exerce muito bem esse princípio e traz uma série de benefícios na capacidade de desenvolver, manter e publicar de forma independente os diferentes componentes de um sistema. O aumento da granularidade traz também alguns pontos negativos e uma preocupação constante ao adotar micro serviços é o aumento da complexidade no monitoramento do sistema e na dificuldade de entender por que algo deu errado, identificar gargalos de performance e ter uma visão macro do funcionamento do sistema.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-651897353889259520-906" src="https://platform.twitter.com/embed/Tweet.html?id=651897353889259520"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-651897353889259520-906');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=651897353889259520&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h3&gt;
  
  
  Distributed Tracing
&lt;/h3&gt;

&lt;p&gt;É aqui que &lt;em&gt;Distributed Tracing&lt;/em&gt; entra, como uma série de técnicas que tem como principal objetivo prover aos desenvolvedores uma maneira de rastrear requisições individuais enquanto elas "pulam" de árvore em arvore numa floresta de micro serviços. Em vez de monitorar entidades ou eventos isolados, &lt;em&gt;Distributed Tracing&lt;/em&gt; nos permite acompanhar &lt;em&gt;traces&lt;/em&gt; de cada componente envolvido. cada &lt;em&gt;trace&lt;/em&gt; é composto de &lt;em&gt;spans&lt;/em&gt; que registram detalhes da interação com um componente.&lt;/p&gt;

&lt;p&gt;São possibilidades desbloqueadas ao adotar alguma forma de Distributed Tracing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Saber exatamente o caminho percorrido para uma determinada solicitação.&lt;/li&gt;
&lt;li&gt;Mensurar a latência de cada componente ao longo do caminho.&lt;/li&gt;
&lt;li&gt;Identificar qual serviço gera uma falha ou um gargalo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conceitos chave de Distributed Tracing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trace&lt;/strong&gt;: Registro de uma atividade através de um sistema distribuído. Uma árvore ou um &lt;a href="https://pt.wikipedia.org/wiki/Grafos_ac%C3%ADclicos_dirigidos" rel="noopener noreferrer"&gt;Grafo acíclico dirigido&lt;/a&gt; de &lt;em&gt;spans&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spans&lt;/strong&gt;: Representam um segmento nomeado e contínuo de processamento em um &lt;em&gt;trace&lt;/em&gt;. Tem relações causais ou de Pai-Filho com outros spans.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jaegertracing.io%2Fimg%2Fspans-traces.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jaegertracing.io%2Fimg%2Fspans-traces.png" alt="spans e traces no jaeger"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Spans e traces, fonte: &lt;a href="https://www.jaegertracing.io/docs/1.17/architecture/" rel="noopener noreferrer"&gt;Documentação do Jaeger&lt;/a&gt;&lt;br&gt;

 &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Span root&lt;/strong&gt;: Primeiro &lt;em&gt;span&lt;/em&gt; num &lt;em&gt;trace&lt;/em&gt;. geralmente tem a duração exata ou aproximada de todo o trace. Na imagem, o &lt;em&gt;span&lt;/em&gt; A é o &lt;em&gt;span root&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context propagation&lt;/strong&gt;: Base do processo de &lt;em&gt;Tracing&lt;/em&gt;. Como o rastro distribuído atravessa mais de um serviço, informações únicas de identificação são necessárias em todos os caminhos que a requisição pode tomar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tracer interface&lt;/strong&gt;: Provê os meios para criar e interagir com spans.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fopentelemetry.io%2Fimg%2Flogos%2Fopentelemetry-horizontal-color.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fopentelemetry.io%2Fimg%2Flogos%2Fopentelemetry-horizontal-color.png" alt="opentelemetry"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenTracing, OpenCensus e, finalmente, OpenTelemetry
&lt;/h3&gt;

&lt;p&gt;Até um passado não tão distante, dois projetos de instrumentação de &lt;em&gt;Distributed Tracing&lt;/em&gt; competiam. O &lt;strong&gt;OpenCensus&lt;/strong&gt; começou no Google como uma plataforma de &lt;em&gt;Observability&lt;/em&gt; interna com participação da forte da Microsoft que começou a contribuir e ajudar a guiar o avanço do projeto logo após sua abertura para open source no &lt;a href="https://github.com/census-instrumentation" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. Já o &lt;strong&gt;OpenTracing&lt;/strong&gt;, apoiado pela [Cloud Native Computing Foundation (CNCF)],(&lt;a href="https://www.cncf.io/" rel="noopener noreferrer"&gt;https://www.cncf.io/&lt;/a&gt;) consiste em uma &lt;a href="https://opentracing.io/specification/" rel="noopener noreferrer"&gt;especificação semântica&lt;/a&gt; que tem como meta a definição de uma API de &lt;em&gt;tracing&lt;/em&gt; padronizada.&lt;/p&gt;

&lt;p&gt;Reconhecendo a dificuldade de adoção da tecnologia trazida pela divisão da comunidade e pela falta de um padrão único de implementação, as lideranças dos dois projetos &lt;a href="https://www.cncf.io/blog/2019/05/21/a-brief-history-of-opentelemetry-so-far/" rel="noopener noreferrer"&gt;se uniram&lt;/a&gt; para criar o OpenTelemetry que entrou oficialmente em beta &lt;a href="https://medium.com/opentelemetry/opentelemetry-is-officially-in-beta-352fa859db10" rel="noopener noreferrer"&gt;no dia 30 de março.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O projeto reúne os pontos fortes do OpenCensus e do OpenTracing para prover um conjunto único de APIs específicas de linguagens, SDKs, agentes e outros componentes que podem ser usados para coletar &lt;em&gt;traces&lt;/em&gt; distribuídos, métricas e metadados relacionados nas aplicações. Como descrito no post de lançamento, muito da utilidade do OpenTelemetry vem da integração com bibliotecas HTTP e RPC e clientes de armazenamento, permitindo a captura de dados de observação das aplicações com esforço muito reduzido.&lt;/p&gt;

&lt;p&gt;O lançamento do beta do OpenTelemetry é um passo importante para a popularização da prática de &lt;em&gt;Distributed Tracing&lt;/em&gt;. Novas funcionalidades continuarão sendo adicionadas e agora com colaboradores de bibliotecas se adaptando as APIs do OpenTelemetry e usuários finais integrando OpenTelemetry aos seus serviços, o nível de maturidade da tecnologia só tende a crescer.&lt;/p&gt;

&lt;p&gt;Para mais detalhes de como o OpenTelemetry funciona, com um exemplo de implementação, &lt;a href="https://dev.to/rafaelvitor/distributed-tracing-com-plugins-do-opentelemetry-node-e-jaeger-56pl-temp-slug-6297147?preview=fc08e16d7af87180fc480b87758ce1f45a49374a769e1b30595e1d24b90d544db087e66577d3658fb5a89e3e327828739e379fe5bd5f0b181f4c9073"&gt;clique aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opentelemetry</category>
      <category>opentracing</category>
      <category>microservices</category>
      <category>distributedsystems</category>
    </item>
  </channel>
</rss>
