# Observabilidade de Aplicações (APM)

# Introdução à Observabilidade de Aplicações

### O que é a Observabilidade de Aplicações?

  
Observabilidade de Aplicações permite entender um sistema externamente, possibilitando fazer perguntas sobre ele **sem precisar conhecer seu funcionamento interno**. Além disso, facilita a solução de problemas desconhecidos e imprevistos . A observabilidade ajuda a responder à pergunta: **“Por que isso está acontecendo?”**

Para fazer perguntas sobre um sistema, é necessário que sua aplicação esteja devidamente **instrumentada**. Isso significa que o código da aplicação ou algum componente intimamente ligado à aplicação como o Application Server, máquina virtual da linguagem da aplicação ou intepretador de comandos da linguagem devem emitir **sinais**, como **rastreamentos** (*traces*), **métricas** e **logs**. Uma aplicação está bem instrumentada quando os desenvolvedores não precisam adicionar mais instrumentação para investigar problemas, pois já possuem todas as informações necessárias.

O Priax, além de possuir mecanismos de instrumentação próprios pode é compatível com mecanismos consagrados do mercado como **OpenTelemetry, Jaeger ou Opensearch APM.** Todos esses mecanismos são usados para instrumentar o código da aplicação e tornar um sistema observável.

### Telemetria, métricas e confiabilidade de Aplicações

**Telemetria** se refere aos dados emitidos por um sistema e seu comportamento. Esses dados podem ser apresentados na forma de **rastreamentos**, **métricas** e **logs**.

A **confiabilidade** responde à pergunta: **“O serviço está fazendo o que os usuários esperam que ele faça?”**. Por exemplo, um sistema pode estar disponível 100% do tempo, mas, se ao clicar em **"Adicionar ao Carrinho"** para incluir um par de sapatos pretos, o sistema não adicionar sempre os sapatos pretos, ele é considerado **não confiável**.

**Métricas** são agregações ao longo do tempo de dados numéricos sobre sua infraestrutura ou aplicação. Exemplos incluem:

- Taxa de erro do sistema
- Uso da CPU
- Taxa de solicitações de um serviço

**SLI** (*Service Level Indicator*) é uma medida do comportamento de um serviço. Um bom SLI mede o serviço **do ponto de vista dos usuários**. Um exemplo de SLI é a velocidade de carregamento de uma página web.

**SLO** (*Service Level Objective*) é a forma como a **confiabilidade** é comunicada dentro da organização ou para outras equipes, vinculando um ou mais SLIs ao **valor de negócio**.

### Entendendo o Rastreamento Distribuído

O **rastreamento distribuído** permite observar solicitações conforme elas se propagam por sistemas distribuídos e complexos. Ele melhora a visibilidade sobre a saúde de uma aplicação ou sistema e ajuda a depurar comportamentos difíceis de reproduzir localmente.

O rastreamento distribuído é **essencial para sistemas distribuídos**, que frequentemente apresentam problemas não determinísticos ou complexos demais para serem reproduzidos em um ambiente local.

Para entender o rastreamento distribuído, é importante conhecer seus principais componentes: **logs**, **spans** e **traces**.

#### Logs

Um **log** é uma mensagem com carimbo de tempo emitida por serviços ou componentes. Diferente dos rastreamentos, os logs não estão necessariamente associados a uma solicitação ou transação específica. Eles estão presentes em praticamente todo software e foram amplamente utilizados por desenvolvedores e operadores para entender o comportamento dos sistemas.

**Exemplo de log:**

```bash
I, [2021-02-23T13:26:23.505892 #22473]  INFO -- : [6459ffe1-ea53-4044-aaa3-bf902868f730] Started GET "/" for ::1 at 2021-02-23 13:26:23 -0800

```

No entanto, os logs **não são suficientes** para rastrear a execução do código, pois geralmente carecem de informações contextuais, como o local de origem da chamada.

Os logs se tornam muito mais úteis quando são incluídos como parte de um **span** ou quando estão correlacionados a um **trace** e um **span**.

#### Spans

Um **span** representa uma **unidade de trabalho** ou uma operação. Ele rastreia operações específicas de uma solicitação, fornecendo uma visão detalhada do que ocorreu durante sua execução.

Um span inclui:

- **Nome**
- **Dados temporais**
- **Mensagens de log estruturadas**
- **Metadados (Atributos)** que fornecem mais informações sobre a operação rastreada.

#### **Atributos de Span**

Os **atributos** são metadados associados a um span.

<table border="1" id="bkmrk-chave-valor-http.req" style="border-collapse: collapse; width: 100%; height: 387.36px;"><colgroup><col style="width: 50.0596%;"></col><col style="width: 50.0596%;"></col></colgroup><tbody><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px; width: 131pt;" width="175">**<span style="background-color: rgb(255, 255, 255); color: rgb(35, 111, 161);">Chave</span>**</td><td class="xl65" style="width: 200pt; height: 29.7969px;" width="267">**<span style="background-color: rgb(255, 255, 255); color: rgb(35, 111, 161);">Valor</span>**</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">http.request.method</td><td class="xl65" style="height: 29.7969px;">GET</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">network.protocol.version</td><td class="xl65" style="height: 29.7969px;">1.1</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">url.path</td><td class="xl65" style="height: 29.7969px;">/webshop/articles/4</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">url.query</td><td class="xl65" style="height: 29.7969px;">?s=1</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">server.address</td><td class="xl65" style="height: 29.7969px;">example.com</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">server.port</td><td class="xl65" style="height: 29.7969px;">8080</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">url.scheme</td><td class="xl65" style="height: 29.7969px;">https</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">http.route</td><td class="xl65" style="height: 29.7969px;">/webshop/articles/:article\_id</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">http.response.status\_code</td><td class="xl65" style="height: 29.7969px;">200</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">client.address</td><td class="xl65" style="height: 29.7969px;">192.0.2.4</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">client.socket.address</td><td class="xl65" style="height: 29.7969px;">192.0.2.5 (o cliente passa por um proxy)</td></tr><tr style="height: 29.7969px;"><td align="left" height="20" style="height: 29.7969px;">user\_agent.original</td><td class="xl65" style="height: 29.7969px;">Mozilla/5.0 (Windows NT 10.0; Win64; ...)</td></tr></tbody></table>

### Rastreamentos Distribuídos

Um **rastreamento distribuído** (*trace*) registra os caminhos percorridos por solicitações (feitas por uma aplicação ou usuário final) enquanto atravessam **arquiteturas multi-serviço**, como aplicações baseadas em microsserviços ou serverless.

Um trace é composto por um ou mais **spans**:

- O **span raiz** representa o início e o fim de uma solicitação.
- Os spans filhos fornecem um **contexto detalhado** sobre o que ocorre durante a solicitação.

Sem rastreamento, identificar a causa raiz de problemas de desempenho em sistemas distribuídos pode ser desafiador. O rastreamento **simplifica a depuração** e facilita o entendimento de sistemas complexos, detalhando o que acontece com uma solicitação enquanto ela se propaga pelo sistema.

Muitos backends de observabilidade visualizam os **traces** como diagramas de cascata (*waterfall diagrams*), que demonstram a relação entre spans pai e filhos, representando relações **hierárquicas** e **aninhadas**.

### Propagação de Contexto

**Entenda o conceito que viabiliza o Rastreamento Distribuído.**

Com a **propagação de contexto**, os **sinais** podem ser correlacionados entre si, independentemente de onde são gerados. Embora não se limite apenas ao rastreamento, a propagação de contexto permite que os **rastreamentos** construam informações causais sobre um sistema que está distribuído de forma arbitrária entre processos e limites de rede.

Para entender a propagação de contexto, é necessário conhecer dois conceitos principais: **contexto** e **propagação**.

#### Contexto

O **contexto** é um objeto que contém as informações necessárias para que os serviços emissores e receptores, ou unidades de execução, possam **correlacionar um sinal com outro**.

Por exemplo: se o **serviço A** chama o **serviço B**, um **span** do serviço A, cujo **ID** está presente no contexto, será utilizado como **span pai** para o próximo span criado no serviço B. O **ID do rastreamento** (*trace ID*) também será incluído no contexto e utilizado para o próximo span criado no serviço B. Isso significa que esse novo span fará parte do **mesmo rastreamento** que o span do serviço A.

#### Propagação

A **propagação** é o mecanismo responsável por **mover o contexto** entre serviços e processos. Ela **serializa** ou **desserializa** o objeto de contexto e fornece as informações relevantes para que o contexto seja transferido de um serviço para outro.

Geralmente, a propagação é gerenciada automaticamente pelas **bibliotecas de instrumentação** e é **transparente** para o usuário. No entanto, caso seja necessário realizar a propagação de contexto **manualmente**, você pode utilizar a **API de Propagadores** (*Propagators API*) de cada biblioteca de instrumentação.

# Sinais e Métricas das Aplicações

### **Tipos de Sinais** 

**Conheça as categorias de telemetria suportadas pelo Priax e bibliotecas de instrumentação compatíveis:**

O objetivo de uma biblioteca de instrumentação é **coletar, processar e exportar sinais**. Sinais são **saídas do sistema** que descrevem a atividade subjacente do sistema operacional e das aplicações em execução em uma plataforma. Um **sinal** pode representar algo que você deseja medir em um ponto específico no tempo, como a **temperatura** ou o **uso de memória**, ou um evento que percorre os componentes de um sistema distribuído e que você gostaria de rastrear.

Com o Priax você pode **agrupar diferentes sinais** para observar o funcionamento interno de uma mesma tecnologia sob diferentes perspectivas.

Atualmente, o **Priax** é capaz de exibir, detalhar, quantificar e detalhar as seguintes categorias de sinais:

- **Rastreamentos** (*traces*)
- **Métricas**
- **Logs**
- **Baggage**

<div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn" id="bkmrk-"><div class="flex-col gap-1 md:gap-3"><div class="flex max-w-full flex-col flex-grow"><div class="min-h-8 text-message flex w-full flex-col items-end gap-2 whitespace-normal break-words text-start [.text-message+&]:mt-5" data-message-author-role="assistant" data-message-id="8524677b-84a3-4a2f-b276-51dea347beca" data-message-model-slug="gpt-4o" dir="auto"><div class="flex w-full flex-col gap-1 empty:hidden first:pt-[3px]">  
</div></div></div></div></div>### **Rastreamentos (Traces)**

**O caminho de uma solicitação através da sua aplicação.**

Os **rastreamentos** nos dão uma **visão geral** do que acontece quando uma solicitação é feita a uma aplicação. Seja sua aplicação um monólito com um único banco de dados ou uma complexa malha de serviços, **os rastreamentos são essenciais para entender o “caminho” completo que uma solicitação percorre** na sua aplicação.

Vamos explorar isso com três unidades de trabalho representadas como **Spans** (faixas de execução):

> **Observação**  
> Os exemplos de JSON a seguir não representam um formato específico, especialmente o **OTLP/JSON**, que é mais detalhado.

##### 1. Span Hello:  


```json
{  
  "name": "hello",  
  "context": {  
    "trace_id": "5b8aa5a2d2c872e8321cf37308d69df2",  
    "span_id": "051581bf3cb55c13"  
  },  
  "parent_id": null,  
  "start_time": "2022-04-29T18:52:58.114201Z",  
  "end_time": "2022-04-29T18:52:58.114687Z",  
  "attributes": {  
    "http.route": "some_route1"  
  },  
  "events": [  
    {  
      "name": "Guten Tag!",  
      "timestamp": "2022-04-29T18:52:58.114561Z",  
      "attributes": { "event_attributes": 1 }  
    }  
  ]  
}
```

Este é o **span raiz**, indicando o início e o fim da operação inteira. Observe que ele tem um campo **trace\_id**, mas **não tem parent\_id**, o que o caracteriza como a raiz do rastreamento.

##### 2. Span *hello-greetings:* 

```json
{
  "name": "hello-greetings",
  "context": {
    "trace_id": "5b8aa5a2d2c872e8321cf37308d69df2",
    "span_id": "5fb397be34d26b51"
  },
  "parent_id": "051581bf3cb55c13",
  "start_time": "2022-04-29T18:52:58.114304Z",
  "end_time": "2022-04-29T22:52:58.114561Z",
  "attributes": {
    "http.route": "some_route2"
  },
  "events": [
    {
      "name": "hey there!",
      "timestamp": "2022-04-29T18:52:58.114561Z",
      "attributes": {
        "event_attributes": 1
      }
    },
    {
      "name": "bye now!",
      "timestamp": "2022-04-29T18:52:58.114585Z",
      "attributes": {
        "event_attributes": 1
      }
    }
  ]
}
```

Este span encapsula tarefas específicas, como exibir saudações, e seu **parent\_id** é o ID do span raiz *hello*. Ele compartilha o mesmo **trace\_id**, indicando que faz parte do mesmo rastreamento.

##### 3. Span *hello-salutations*:

```json
{  
  "name": "hello-salutations",  
  "context": {  
    "trace_id": "5b8aa5a2d2c872e8321cf37308d69df2",  
    "span_id": "93564f51e1abe1c2"  
  },  
  "parent_id": "051581bf3cb55c13",  
  "start_time": "2022-04-29T18:52:58.114492Z",  
  "end_time": "2022-04-29T18:52:58.114631Z",  
  "attributes": {  
    "http.route": "some_route3"  
  },  
  "events": [  
    {  
      "name": "hey there!",  
      "timestamp": "2022-04-29T18:52:58.114561Z"  
    }  
  ]  
}
```

Este span representa a **terceira operação** neste rastreamento e, assim como o anterior, é um **filho do span raiz (*hello*)**. Isso também o torna um **irmão** do span *hello-greetings*

Esses três blocos de JSON compartilham o mesmo **trace\_id** e utilizam o **parent\_id** para representar a hierarquia. Isso cria o **rastreamento completo**!

Uma observação importante é que cada **Span** se assemelha a um **log estruturado**, com contexto, correlação e hierarquia embutidos. Contudo, esses “logs estruturados” podem vir de diferentes **processos, serviços, VMs ou datacenters**, permitindo que o rastreamento represente uma **visão ponta a ponta** de qualquer sistema.

#### Detalhamento de uma span

Uma **span** representa uma **unidade de trabalho** ou operação e inclui:

- **Nome**
- **ID do Span pai** (vazio para spans raiz)
- **Timestamps de início e fim**
- **Contexto do Span**
- **Atributos**
- **Eventos**
- **Links**
- **Status do Span**

**Exemplo de span:**

```json
{
  "name": "/v1/sys/health",
  "context": {
    "trace_id": "7bba9f33312b3dbb8b2c2c62bb7abe2d",
    "span_id": "086e83747d0e381e"
  },
  "parent_id": "",
  "start_time": "2021-10-22 16:04:01.209458162 +0000 UTC",
  "end_time": "2021-10-22 16:04:01.209514132 +0000 UTC",
  "status_code": "STATUS_CODE_OK",
  "status_message": "",
  "attributes": {
    "net.transport": "IP.TCP",
    "net.peer.ip": "172.17.0.1",
    "net.peer.port": "51820",
    "net.host.ip": "10.177.2.152",
    "net.host.port": "26040",
    "http.method": "GET",
    "http.target": "/v1/sys/health",
    "http.server_name": "mortar-gateway",
    "http.route": "/v1/sys/health",
    "http.user_agent": "Consul Health Check",
    "http.scheme": "http",
    "http.host": "10.177.2.152:26040",
    "http.flavor": "1.1"
  },
  "events": [
    {
      "name": "",
      "message": "OK",
      "timestamp": "2021-10-22 16:04:01.209512872 +0000 UTC"
    }
  ]
}
```

##### **Contexto do Span**

Os spans podem ser aninhados, como é indicado pela presença de um **ID de span pai**: os spans filhos representam suboperações. Isso permite que os spans capturem com mais precisão o trabalho realizado em uma aplicação. O span pai terá um trace\_Id idêntico ao seu filho indicando portanto que atende a uma mesma requisição ao sistema.

O contexto do span é um objeto imutável presente em todos os spans que contém as seguintes informações:

- **Trace ID**: identifica o trace ao qual o span pertence.
- **Span ID**: identifica o próprio span.
- **Trace Flags**: uma codificação binária com informações sobre o trace.
- **Trace State**: uma lista de pares chave-valor que podem conter informações específicas de fornecedores.

##### **Atributos**

Os atributos são pares chave-valor usados para adicionar metadados a um span, permitindo capturar informações sobre a operação monitorada.

Por exemplo, se um span acompanha a operação de adicionar um item ao carrinho de compras em um sistema de e-commerce, você pode registrar o **ID do usuário**, o **ID do item** e o **ID do carrinho**.

- Você pode adicionar atributos durante ou após a criação de um span.
- É recomendável adicionar os atributos no momento da criação para que possam ser aproveitados pelo SDK na amostragem. Caso precise adicionar valores posteriormente, atualize o span.

**Regras para atributos:**

- As **chaves** devem ser strings não nulas.
- Os **valores** devem ser uma string, booleano, número (ponto flutuante ou inteiro) ou um array desses tipos.

Além disso, existem **Atributos Semânticos**, que são convenções padronizadas para nomes de atributos comuns. Utilizar nomes semânticos facilita a padronização de metadados entre sistemas.

##### **Eventos do Span**

Um **evento do span** pode ser visto como uma **mensagem de log estruturada** (ou anotação) associada a um span. Geralmente é usado para marcar um ponto singular e significativo no tempo durante a duração de um span.

**Exemplo prático em um navegador web:**

1. **Carregamento da página** → O span é mais apropriado, pois acompanha uma operação com início e fim.
2. **Página se torna interativa** → Um evento do span é mais adequado, pois representa um ponto específico no tempo.

**Quando usar eventos do span versus atributos?**  
Se o **timestamp** específico for relevante, use um **evento do span**. Caso contrário, use **atributos**.

##### **Links do Span**

Os **links** permitem associar um span a um ou mais spans, indicando uma relação causal.

Por exemplo, em um sistema distribuído, algumas operações são rastreadas por um trace. Em resposta a essas operações, uma nova tarefa pode ser enfileirada para execução assíncrona. Para associar o trace da operação subsequente ao trace original, criamos um **link de span**.

Links são opcionais, mas são uma maneira eficaz de relacionar spans de diferentes traces.

##### **Status do Span**

Cada span possui um status com três valores possíveis:

1. **Unset**: (padrão) indica que a operação foi concluída sem erros.
2. **Error**: indica que ocorreu algum erro, como um HTTP 500 em um servidor.
3. **Ok**: explicitamente definido pelo desenvolvedor para marcar o span como bem-sucedido.

> **Nota:** Quando não houver um status **Ok** para spans que concluíram sem erros, considera-se um evento bem sucedido, pois o valor padrão **Unset** já cobre esse caso. **Ok** é usado para deixar explícito que um span é considerado bem-sucedido, sem ambiguidades.

##### **Tipo do Span (Span Kind)**

Ao criar um span, ele pode ser classificado como **Client**, **Server**, **Internal**, **Producer** ou **Consumer**. O tipo de span informa ao backend de rastreamento como o trace deve ser montado.

- **Client**: Representa uma chamada remota síncrona de saída, como uma solicitação HTTP ou consulta ao banco de dados.
- **Server**: Representa uma chamada remota síncrona recebida, como uma solicitação HTTP ou RPC.
- **Internal**: Representa operações que não cruzam limites de processo (ex: chamadas de funções locais ou middlewares).
- **Producer**: Representa a criação de uma tarefa a ser processada de forma assíncrona (ex: inserção em uma fila).
- **Consumer**: Representa o processamento de uma tarefa criada por um producer. Pode ser iniciado muito tempo após o término do span do producer.

Se o tipo não for especificado, ele é considerado **Internal**.

<div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn" id="bkmrk--1"><div class="flex-col gap-1 md:gap-3"><div class="flex max-w-full flex-col flex-grow"><div class="min-h-8 text-message flex w-full flex-col items-end gap-2 whitespace-normal break-words text-start [.text-message+&]:mt-5" data-message-author-role="assistant" data-message-id="50484df2-531e-4273-9bc2-9a5451f6ec6c" data-message-model-slug="gpt-4o" dir="auto"><div class="flex w-full flex-col gap-1 empty:hidden first:pt-[3px]"><div class="markdown prose w-full break-words dark:prose-invert light">---

</div></div></div></div></div></div>### **Métricas**

Uma métrica é uma medida de um serviço capturada em tempo de execução. O momento em que a medição é registrada é conhecido como um **evento de métrica**, que inclui não apenas o valor medido, mas também o horário da captura e os metadados associados.

Métricas de aplicação e requisição são indicadores importantes de disponibilidade e desempenho. Métricas personalizadas podem oferecer insights sobre como os indicadores de disponibilidade impactam a experiência do usuário ou o negócio. Os dados coletados podem ser utilizados para alertar sobre interrupções ou para acionar decisões de escalonamento automático durante períodos de alta demanda.

Para compreender como as métricas funcionam quando se utiliza as bibliotecas de instrumentação compatíveis com o Priax, vamos analisar os componentes principais que ajudam na instrumentação do código.

#### **Provedor de Meter (Meter Provider)**

O **Meter Provider** é uma fábrica de **Meters**. Em aplicações, geralmente é inicializado uma única vez e seu ciclo de vida corresponde ao ciclo de vida da aplicação. A inicialização de um Meter Provider também envolve a configuração de **Recursos** e **Exportadores**. Esse é, normalmente, o primeiro passo ao configurar métricas no Priax. Em alguns SDKs compatíveis, um Meter Provider global já é inicializado automaticamente.

#### **Meter**

Um **Meter** é responsável por criar instrumentos de métrica que capturam medições sobre um serviço em tempo de execução. Os **Meters** são criados a partir de **Meter Providers**.

#### **Exportador de Métricas (Metric Exporter)**

Os **Exportadores de Métricas** enviam dados de métricas para um consumidor. Esse consumidor pode ser uma saída padrão (para depuração durante o desenvolvimento), o **Priax utiliza o Opentelemetry Collector**, ou qualquer backend de código aberto ou proprietário de sua escolha.

#### **Instrumentos de Métrica (Metric Instruments)**

No Priax, as medições são capturadas por **instrumentos de métrica**, definidos pelos seguintes atributos:

- **Nome**
- **Tipo**
- **Unidade** (opcional)
- **Descrição** (opcional)

O nome, a unidade e a descrição são definidos pelo desenvolvedor ou por convenções semânticas para métricas comuns, como requisições e processos.

Os **tipos de instrumentos compatíveis** incluem:

- **Counter**: Valor acumulado ao longo do tempo (ex.: um odômetro, que só aumenta).
- **Counter Assíncrono**: Similar ao Counter, mas coletado uma vez por exportação, útil quando você tem acesso apenas ao valor agregado.
- **UpDownCounter**: Valor acumulado que pode aumentar ou diminuir (ex.: o tamanho de uma fila).
- **UpDownCounter Assíncrono**: Similar ao UpDownCounter, mas coletado uma vez por exportação.
- **Gauge**: Mede um valor atual no momento da leitura (ex.: marcador de combustível de um carro). É síncrono.
- **Gauge Assíncrono**: Similar ao Gauge, mas coletado uma vez por exportação.
- **Histogram**: Agrega valores no lado do cliente, como latências de requisições. Útil para estatísticas de valores, como quantas requisições levaram menos de 1s.

#### **Agregação**

Além dos instrumentos de métrica, a **agregação** é um conceito importante. A agregação combina uma grande quantidade de medições em estatísticas exatas ou estimadas sobre eventos de métrica em uma janela de tempo. O protocolo OTLP transporta essas métricas agregadas.

A API do Priax fornece uma agregação padrão para cada instrumento, que pode ser personalizada usando **Views**. O objetivo do projeto Priax é fornecer agregações padrão que sejam compatíveis com ferramentas de visualização e backends de telemetria.

Diferentemente do rastreamento de requisições, que captura o ciclo de vida de uma requisição, as métricas fornecem informações estatísticas em agregados. Exemplos de uso incluem:

- Total de bytes lidos por um serviço, por tipo de protocolo.
- Total de bytes lidos e bytes por requisição.
- Duração de chamadas de sistema.
- Tamanhos de requisição para identificar tendências.
- Uso de CPU ou memória de um processo.
- Valores médios de saldo em contas.
- Quantidade atual de requisições ativas.

#### **Views**

As **Views** oferecem flexibilidade para personalizar a saída de métricas pelo SDK. É possível:

- Escolher quais instrumentos de métrica serão processados ou ignorados.
- Configurar a agregação e os atributos a serem reportados nas métricas.

#### **Suporte por Linguagem**

O suporte às implementações específicas da API e do SDK de Métricas, por linguagem, está conforme a tabela abaixo:

<table border="1" id="bkmrk-linguagem-status-c%2B%2B" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 50.0596%;"></col><col style="width: 50.0596%;"></col></colgroup><tbody><tr><td class="xl65" height="40" style="height: 30.0pt; width: 48pt;" width="64"><span style="color: rgb(35, 111, 161);">Linguagem</span></td><td class="xl65" style="width: 48pt;" width="64"><span style="color: rgb(35, 111, 161);">Status</span></td></tr><tr><td align="left" class="xl66" height="20" style="height: 15.0pt; width: 48pt;" width="64">C++</td><td align="left" class="xl66" style="width: 48pt;" width="64">Estável</td></tr><tr><td align="left" class="xl66" height="20" style="height: 15.0pt; width: 48pt;" width="64">C#/.NET</td><td align="left" class="xl66" style="width: 48pt;" width="64">Estável</td></tr><tr><td align="left" class="xl66" height="60" style="height: 45.0pt; width: 48pt;" width="64">Erlang/Elixir</td><td align="left" class="xl66" style="width: 48pt;" width="64">Em desenvolvimento</td></tr><tr><td align="left" class="xl66" height="20" style="height: 15.0pt; width: 48pt;" width="64">Go</td><td align="left" class="xl66" style="width: 48pt;" width="64">Estável</td></tr><tr><td align="left" class="xl66" height="20" style="height: 15.0pt; width: 48pt;" width="64">Java</td><td align="left" class="xl66" style="width: 48pt;" width="64">Estável</td></tr><tr><td align="left" class="xl66" height="40" style="height: 30.0pt; width: 48pt;" width="64">JavaScript</td><td align="left" class="xl66" style="width: 48pt;" width="64">Estável</td></tr><tr><td align="left" class="xl66" height="20" style="height: 15.0pt; width: 48pt;" width="64">PHP</td><td align="left" class="xl66" style="width: 48pt;" width="64">Estável</td></tr><tr><td align="left" class="xl66" height="20" style="height: 15.0pt; width: 48pt;" width="64">Python</td><td align="left" class="xl66" style="width: 48pt;" width="64">Estável</td></tr><tr><td align="left" class="xl66" height="60" style="height: 45.0pt; width: 48pt;" width="64">Ruby</td><td align="left" class="xl66" style="width: 48pt;" width="64">Em desenvolvimento</td></tr><tr><td align="left" class="xl66" height="20" style="height: 15.0pt; width: 48pt;" width="64">Rust</td><td align="left" class="xl66" style="width: 48pt;" width="64">Beta</td></tr><tr><td align="left" class="xl66" height="60" style="height: 45.0pt; width: 48pt;" width="64">Swift</td><td align="left" class="xl66" style="width: 48pt;" width="64">Em desenvolvimento</td></tr></tbody></table>

### **Logs**

Um **log** é um registro textual com marcação de tempo, podendo ser estruturado (recomendado) ou não estruturado, acompanhado de metadados opcionais. Entre todos os sinais de telemetria, os logs possuem o maior legado, já que a maioria das linguagens de programação inclui capacidades de logging nativas ou bibliotecas amplamente utilizadas.

---

### **Logs de Aplicação no Priax**

O Priax não define uma API ou SDK específicos para criar logs. Em vez disso, os logs no Priax são aqueles já existentes, oriundos de frameworks de logging ou componentes de infraestrutura. Os SDKs e bibliotecas de instrumentação compatíveis com o Priax e a autoinstrumentação utilizam diversos componentes para correlacionar automaticamente logs com traces.

O suporte da biblioteca de instrumentação Priax para logs é projetado para ser totalmente compatível com sistemas existentes, oferecendo ferramentas para adicionar contexto adicional aos logs e manipulá-los em um formato comum, independentemente da origem.

Nas aplicações, os logs são criados usando qualquer biblioteca ou funcionalidade nativa de logging. Ao adicionar autoinstrumentação ou ativar um SDK de instrumentação compatível com o Priax, os logs são correlacionados automaticamente existentes com quaisquer traces e spans ativos, encapsulando o corpo do log com seus respectivos IDs.

---

### **Suporte por Linguagem**

As bibliotecas de instrumentação atualmente compatíveis com o Priax suportam o envio de logs para as seguintes linguagens de programação:

<table id="bkmrk-linguagem-status-c%2B%2B-1"><thead><tr><th>**Linguagem**</th><th>**Status**</th></tr></thead><tbody><tr><td>C++</td><td>Estável</td></tr><tr><td>C#/.NET</td><td>Estável</td></tr><tr><td>Erlang/Elixir</td><td>Em desenvolvimento</td></tr><tr><td>Go</td><td>Beta</td></tr><tr><td>Java</td><td>Estável</td></tr><tr><td>JavaScript</td><td>Em desenvolvimento</td></tr><tr><td>PHP</td><td>Estável</td></tr><tr><td>Python</td><td>Em desenvolvimento</td></tr><tr><td>Ruby</td><td>Em desenvolvimento</td></tr><tr><td>Rust</td><td>Beta</td></tr><tr><td>Swift</td><td>Em desenvolvimento</td></tr></tbody></table>

---

### **Logs Estruturados, Não Estruturados e Semi-Estruturados**

#### **Logs Estruturados**

Logs estruturados seguem um formato consistente e legível por máquina, como JSON.

**Exemplo em aplicação:**

```json
{
  "timestamp": "2024-08-04T12:34:56.789Z",
  "level": "INFO",
  "service": "autenticacao-usuario",
  "mensagem": "Login do usuário bem-sucedido",
  "contexto": {
    "userId": "12345",
    "ipAddress": "192.168.1.1"
  }
}
```

<div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950" id="bkmrk--5"></div>#### **Logs Não Estruturados**

Logs não estruturados não seguem um formato consistente. Apesar de serem mais legíveis para humanos, são difíceis de processar em larga escala.

**Exemplo:**  
`[ERRO] 2024-08-04 12:45:23 - Falha ao conectar ao banco de dados. Timeout.`

#### **Logs Semi-Estruturados**

Logs semi-estruturados utilizam padrões consistentes, mas com formatações variadas entre sistemas.

**Exemplo:**  
`2024-08-04T12:45:23Z level=ERROR service=autenticacao-usuario action=login mensagem="Senha inválida"`

### **Baggage**

Informações contextuais propagadas entre sinais.

O **Baggage** representa informações contextuais que são mantidas junto ao contexto. O Baggage é uma estrutura de chave-valor que permite a propagação de dados arbitrários ao lado do contexto.

Com o Baggage, é possível transmitir dados entre serviços e processos, tornando essas informações acessíveis para serem adicionadas a traces, métricas ou logs nos serviços subsequentes.

#### **Para que serve o Baggage**

O Baggage é ideal para incluir informações que estão disponíveis no início de uma requisição, mas que precisam ser acessadas em estágios posteriores. Exemplos incluem:

- Identificação de Contas
- IDs de Usuários
- IDs de Produtos
- IPs de origem

Propagar essas informações usando o Baggage possibilita análises mais detalhadas na telemetria. Por exemplo, incluir um ID de Usuário em um span que monitora uma chamada ao banco de dados facilita responder perguntas como: *“Quais usuários estão enfrentando as chamadas mais lentas ao banco de dados?”*. Também é possível registrar informações de uma operação downstream e incluir o mesmo ID de Usuário nos dados de log.

#### **Considerações de segurança do Baggage**

Itens sensíveis no Baggage podem ser compartilhados com recursos não intencionais, como APIs de terceiros. Isso ocorre porque instrumentações automáticas incluem o Baggage na maioria das requisições de rede do seu serviço.

Especificamente, o Baggage e outras partes do contexto de trace são enviados em cabeçalhos HTTP, ficando visíveis para quem inspecionar o tráfego da rede. Se o tráfego estiver restrito à sua rede interna, esse risco pode não se aplicar, mas é importante lembrar que serviços downstream podem propagar o Baggage para fora da sua rede.

Além disso, não há verificações de integridade embutidas para garantir que os itens do Baggage sejam de sua origem. Por isso, tome cuidado ao acessá-los.

#### **O Baggage não é o mesmo que atributos**

Uma diferença importante é que o Baggage é um armazenamento separado de chave-valor, e não está associado diretamente aos atributos de spans, métricas ou logs, a menos que seja adicionado explicitamente.

Para adicionar entradas do Baggage como atributos, é necessário ler os dados do Baggage e incluí-los manualmente como atributos em spans, métricas ou logs.

Como um dos usos comuns do Baggage é adicionar dados como atributos de spans em um trace inteiro, várias linguagens oferecem **Baggage Span Processors** que automaticamente adicionam dados do Baggage como atributos na criação de spans.

# Instrumentação com Bibliotecas OpenTelemetry

O envio de sinais para o Priax pode ser realizado através de instrumentação própria, alterando o código da aplicação a ser observada sem inserir componentes de terceiros à sua infraestrutura. Este processo, no entanto pode ser custoso e levar algum tempo. Para que se possa acelerar esse processo, recomendamos, apesar de não ser a única opção, as bibliotecas e SDKs open-source do OpenTelemetry. Tais bibliotecas seguem os padrões OpenTracing e se tornaram a mais difundida solução de instrumentação para o mercado de Observabilidade.

**Como o OpenTelemetry facilita a instrumentação**  
Para tornar um sistema observável, é necessário instrumentá-lo: ou seja, o código dos componentes do sistema deve emitir traces, métricas e logs.

Com o OpenTelemetry, você pode instrumentar seu código de duas maneiras principais:

1. **Soluções baseadas em código**  
    Utilizando APIs e SDKs oficiais disponíveis para a maioria das linguagens de programação.
2. **Soluções sem código**  
    Ideais para casos em que você não pode ou não deseja modificar o aplicativo que precisa de telemetria.

### Soluções baseadas em código

Essas soluções permitem uma telemetria mais profunda e detalhada, gerada diretamente pela sua aplicação. Elas utilizam a API do OpenTelemetry para produzir telemetria personalizada, complementando as informações coletadas por soluções sem código.

### Soluções sem código

Perfeitas para começar rapidamente ou quando o aplicativo não pode ser modificado. Essas soluções oferecem uma telemetria rica baseada em bibliotecas utilizadas ou no ambiente em que a aplicação está sendo executada. Elas fornecem dados sobre o que está acontecendo nas "bordas" da aplicação, como interações externas e dependências.

> **Nota**: É possível usar ambas as abordagens ao mesmo tempo para maximizar a observabilidade.

---

### Benefícios adicionais do OpenTelemetry

O OpenTelemetry vai além de oferecer soluções com e sem código. Ele também inclui os seguintes recursos:

- **Bibliotecas compatíveis:** Bibliotecas podem usar a API do OpenTelemetry como dependência, sem impactar aplicações que não importem o SDK.
- **Sinais flexíveis:** Para cada tipo de sinal (traces, métricas, logs), existem várias formas de criá-los, processá-los e exportá-los.
- **Correlação de sinais:** Com a propagação de contexto integrada, é possível correlacionar sinais, independentemente de onde foram gerados.
- **Recursos e Escopos de Instrumentação:** Permitem agrupar sinais por diferentes entidades, como o host, sistema operacional ou cluster Kubernetes.
- **Padrões e especificações:** Cada implementação de linguagem do OpenTelemetry segue os requisitos e expectativas definidos pela especificação oficial.
- **Convenções semânticas:** Fornecem um esquema de nomenclatura comum para padronizar métricas, logs e traces entre diferentes bases de código e plataformas.

### Formas de Instrumentação

#### Instrumentação sem código

A instrumentação sem código adiciona as capacidades da API e SDK do OpenTelemetry à sua aplicação, geralmente por meio de uma instalação de agente ou algo semelhante a um agente. Os mecanismos específicos variam conforme a linguagem, incluindo manipulação de bytecode, monkey patching ou eBPF, para injetar chamadas à API e ao SDK do OpenTelemetry diretamente na aplicação.

##### Como funciona

Normalmente, a instrumentação sem código adiciona suporte para bibliotecas que sua aplicação utiliza. Isso significa que requisições e respostas, chamadas a bancos de dados, chamadas de filas de mensagens, entre outros, serão instrumentados automaticamente. No entanto, o código da sua aplicação geralmente não é instrumentado. Para isso, é necessário utilizar **instrumentação baseada em código**.

Além disso, a instrumentação sem código permite configurar as bibliotecas de instrumentação e os exportadores que serão carregados.

##### Configuração

Você pode configurar a instrumentação sem código por meio de variáveis de ambiente e outros mecanismos específicos da linguagem, como propriedades do sistema ou argumentos passados para métodos de inicialização. Para começar, é necessário apenas configurar o **nome do serviço** para identificá-lo no backend de observabilidade escolhido.

Outras opções de configuração incluem:

- Configuração específica para fontes de dados.
- Configuração de exportadores.
- Configuração de propagadores.
- Configuração de recursos.

##### Suporte de linguagens para instrumentação automática

A instrumentação automática está disponível para as seguintes linguagens:

- .NET
- Go
- Java
- JavaScript
- PHP
- Python

Para realizar a instrumentação de sua aplicação, utilizando o método Zero Code, siga as [instruções da página do OpenTelemetry.](https://opentelemetry.io/docs/zero-code/)

### Instrumentação Baseada em Código

A instrumentação baseada em código permite criar telemetria personalizada diretamente no código da sua aplicação. Abaixo estão os passos essenciais para configurar essa abordagem:

#### 1. Importar a API e o SDK do OpenTelemetry

- **Serviços:** Dependem da API e do SDK do OpenTelemetry.
- **Bibliotecas:** Apenas dependem da API.

Para mais detalhes sobre a API e o SDK, consulte a [especificação do OpenTelemetry](https://opentelemetry.io/docs/specs/otel/).

#### 2. Configurar a API do OpenTelemetry

- **Fornecedores de Tracer e Meter:**
    
    
    - Crie um **TracerProvider** para gerar traços.
    - Crie um **MeterProvider** para gerar métricas.
- **Nomeação:**
    
    
    - Use um nome que identifique o componente sendo instrumentado.
    - Exemplo: para uma biblioteca, use algo como `com.example.myLibrary`.
    - Inclua uma versão no formato **semver** (ex.: `semver:1.0.0`).

#### 3. Configurar o SDK do OpenTelemetry

- **Exportação de dados:** Configure o SDK para exportar telemetria a um backend de análise.
- **Opções específicas da linguagem:** Verifique as opções de ajuste disponíveis para a sua linguagem.

A configuração pode ser feita programaticamente, por meio de arquivos de configuração ou outros mecanismos.

#### 4. Criar Dados de Telemetria

- **Traços e Métricas:**
    - Gere traços e eventos de métricas com os objetos `Tracer` e `Meter`.
- **Bibliotecas de Instrumentação:**
    - Use bibliotecas de instrumentação disponíveis para suas dependências.
    - Consulte o repositório ou registro da sua linguagem para obter mais informações.

#### 5. Exportar Dados de Telemetria

- **Métodos de Exportação:**
    - **Exportação no processo:**
        
        
        - Importe e use **exportadores** para traduzir os objetos de telemetria do OpenTelemetry em formatos apropriados para ferramentas de análise (ex.: Jaeger ou Prometheus).
    - **Exportação via OTLP e Collector:**
        
        
        - Use o **protocolo OTLP** para enviar dados ao OpenTelemetry Collector, que pode atuar como um proxy, sidecar ou processo separado.
        - O Collector encaminha os dados para ferramentas de análise.

Para realizar a instrumentação de sua aplicação, utilizando o método baseado em código siga as [instruções da página do OpenTelemetry.](https://opentelemetry.io/docs/concepts/instrumentation/code-based/)

### Instrumentação de Bibliotecas

A instrumentação nativa de bibliotecas com OpenTelemetry oferece uma experiência aprimorada tanto para desenvolvedores quanto para usuários finais, eliminando a necessidade de expor e documentar hooks personalizados. Aqui está como funciona e os benefícios associados:

#### Como Adicionar Instrumentação Nativa

- **Instrumentação via Hooks ou *dynamic runtime patching*:**  
    OpenTelemetry fornece bibliotecas de instrumentação para várias linguagens, que tipicamente utilizam hooks de bibliotecas ou *dynamic runtime patching* do código.

#### Vantagens da Instrumentação Nativa

1. **Melhoria na Observabilidade e Experiência do Usuário:**
    
    
    - Remove a necessidade de hooks personalizados, facilitando a integração.
    - APIs do OpenTelemetry são fáceis de usar e consistentes para os usuários finais.
2. **Telemetria Consistente e Correlação Aprimorada:**
    
    
    - Traços, logs e métricas provenientes do código da biblioteca e da aplicação são correlacionados, criando uma visão coesa dos eventos.
    - Convenções comuns garantem uniformidade entre tecnologias, bibliotecas e linguagens.
3. **Extensibilidade e Ajustes Fáceis:**
    
    
    - Sinais de telemetria podem ser ajustados (filtrados, processados, agregados) para atender a diferentes cenários de consumo.
    - OpenTelemetry oferece extensibilidade bem documentada para personalização.

Para realizar a instrumentação de sua aplicação, utilizando as bibliotecas nativas OpenTelemetry, siga as [instruções da página do OpenTelemetry.](https://opentelemetry.io/docs/concepts/instrumentation/libraries/)

### Instrumentação com Kubernetes Operator

A instrumentação de aplicações que rodam em workloads Kubernetes é facilitada pelo Opentelemetry Kubernetes Operator que é uma implementação de um Operador Kubernetes que gerencia coletores e a auto-instrumentação das cargas de trabalho usando bibliotecas de instrumentação do OpenTelemetry.

#### Introdução

O Operador OpenTelemetry é uma implementação de um Operador Kubernetes.

O operador gerencia:

- **Coletor OpenTelemetry**
- **Auto-instrumentação das cargas de trabalho** (pods) usando bibliotecas de instrumentação do OpenTelemetry

#### Início Rápido

Para instalar o operador em um cluster existente, certifique-se de ter o **cert-manager** instalado e execute:

```bash
kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/latest/download/opentelemetry-operator.yaml

```

Assim que a implantação do `opentelemetry-operator` estiver pronta, crie uma instância do Coletor OpenTelemetry (otelcol) como o exemplo abaixo:

```bash
kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: simplest
spec:
  config: |
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    processors:

    exporters:
      # NOTA: Antes da versão v0.86.0, use `logging` ao invés de `debug`.
      debug:

    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: []
          exporters: [debug]
EOF
```

Para mais opções de configuração e para configurar a injeção de auto-instrumentação das cargas de trabalho usando as bibliotecas de instrumentação do OpenTelemetry, continue lendo [aqui](https://github.com/open-telemetry/opentelemetry-operator/blob/main/README.md).

### **Injeção de Auto-instrumentação**

**Configurar Instrumentação Automática**  
Para gerenciar a instrumentação automática, o operador precisa ser configurado para identificar quais pods instrumentar e qual instrumentação automática usar nesses pods. Isso é feito por meio do **CRD de Instrumentação**.

A criação correta do recurso de Instrumentação é fundamental para que a instrumentação automática funcione. Certifique-se de que todos os endpoints e variáveis de ambiente estejam configurados corretamente.

### **.NET**

O seguinte comando criará um recurso básico de Instrumentação configurado especificamente para serviços .NET:

```bash
kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"
EOF

```

Por padrão, o recurso de Instrumentação para serviços .NET usa OTLP com o protocolo HTTP/Protobuf. O endpoint configurado deve ser capaz de receber OTLP via HTTP/Protobuf, como no exemplo: `http://demo-collector:4318`.

#### **Excluindo bibliotecas de instrumentação**

Se você não quiser usar determinadas bibliotecas, configure as variáveis de ambiente `OTEL_DOTNET_AUTO_[SIGNAL]_[NAME]_INSTRUMENTATION_ENABLED=false`.

Exemplo:

```yaml
dotnet:
  env:
    - name: OTEL_DOTNET_AUTO_TRACES_GRPCNETCLIENT_INSTRUMENTATION_ENABLED
      value: false
    - name: OTEL_DOTNET_AUTO_METRICS_PROCESS_INSTRUMENTATION_ENABLED
      value: false
```

### **Java**

O seguinte comando criará um recurso básico de Instrumentação para serviços Java:

```bash
kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"
EOF
```

Por padrão, a instrumentação Java usa OTLP com HTTP/Protobuf.

#### **Excluindo bibliotecas de instrumentação**

Para desativar bibliotecas específicas:

- Use `OTEL_INSTRUMENTATION_[NAME]_ENABLED=false`.
- Para desativar todas por padrão e ativar somente algumas:

```
OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED=false
OTEL_INSTRUMENTATION_[NAME]_ENABLED=true
```

<div class="flex-shrink-0 flex flex-col relative items-end" id="bkmrk--1"><div><div class="pt-0"><div class="gizmo-bot-avatar flex h-8 w-8 items-center justify-center overflow-hidden rounded-full"><div class="relative p-1 rounded-sm flex items-center justify-center bg-token-main-surface-primary text-token-text-primary h-8 w-8"><svg class="icon-md" fill="none" height="41" role="img" viewbox="0 0 41 41" width="41" xmlns="http://www.w3.org/2000/svg"><text x="-9999" y="-9999"></text><path d="M37.5324 16.8707C37.9808 15.5241 38.1363 14.0974 37.9886 12.6859C37.8409 11.2744 37.3934 9.91076 36.676 8.68622C35.6126 6.83404 33.9882 5.3676 32.0373 4.4985C30.0864 3.62941 27.9098 3.40259 25.8215 3.85078C24.8796 2.7893 23.7219 1.94125 22.4257 1.36341C21.1295 0.785575 19.7249 0.491269 18.3058 0.500197C16.1708 0.495044 14.0893 1.16803 12.3614 2.42214C10.6335 3.67624 9.34853 5.44666 8.6917 7.47815C7.30085 7.76286 5.98686 8.3414 4.8377 9.17505C3.68854 10.0087 2.73073 11.0782 2.02839 12.312C0.956464 14.1591 0.498905 16.2988 0.721698 18.4228C0.944492 20.5467 1.83612 22.5449 3.268 24.1293C2.81966 25.4759 2.66413 26.9026 2.81182 28.3141C2.95951 29.7256 3.40701 31.0892 4.12437 32.3138C5.18791 34.1659 6.8123 35.6322 8.76321 36.5013C10.7141 37.3704 12.8907 37.5973 14.9789 37.1492C15.9208 38.2107 17.0786 39.0587 18.3747 39.6366C19.6709 40.2144 21.0755 40.5087 22.4946 40.4998C24.6307 40.5054 26.7133 39.8321 28.4418 38.5772C30.1704 37.3223 31.4556 35.5506 32.1119 33.5179C33.5027 33.2332 34.8167 32.6547 35.9659 31.821C37.115 30.9874 38.0728 29.9178 38.7752 28.684C39.8458 26.8371 40.3023 24.6979 40.0789 22.5748C39.8556 20.4517 38.9639 18.4544 37.5324 16.8707ZM22.4978 37.8849C20.7443 37.8874 19.0459 37.2733 17.6994 36.1501C17.7601 36.117 17.8666 36.0586 17.936 36.0161L25.9004 31.4156C26.1003 31.3019 26.2663 31.137 26.3813 30.9378C26.4964 30.7386 26.5563 30.5124 26.5549 30.2825V19.0542L29.9213 20.998C29.9389 21.0068 29.9541 21.0198 29.9656 21.0359C29.977 21.052 29.9842 21.0707 29.9867 21.0902V30.3889C29.9842 32.375 29.1946 34.2791 27.7909 35.6841C26.3872 37.0892 24.4838 37.8806 22.4978 37.8849ZM6.39227 31.0064C5.51397 29.4888 5.19742 27.7107 5.49804 25.9832C5.55718 26.0187 5.66048 26.0818 5.73461 26.1244L13.699 30.7248C13.8975 30.8408 14.1233 30.902 14.3532 30.902C14.583 30.902 14.8088 30.8408 15.0073 30.7248L24.731 25.1103V28.9979C24.7321 29.0177 24.7283 29.0376 24.7199 29.0556C24.7115 29.0736 24.6988 29.0893 24.6829 29.1012L16.6317 33.7497C14.9096 34.7416 12.8643 35.0097 10.9447 34.4954C9.02506 33.9811 7.38785 32.7263 6.39227 31.0064ZM4.29707 13.6194C5.17156 12.0998 6.55279 10.9364 8.19885 10.3327C8.19885 10.4013 8.19491 10.5228 8.19491 10.6071V19.808C8.19351 20.0378 8.25334 20.2638 8.36823 20.4629C8.48312 20.6619 8.64893 20.8267 8.84863 20.9404L18.5723 26.5542L15.206 28.4979C15.1894 28.5089 15.1703 28.5155 15.1505 28.5173C15.1307 28.5191 15.1107 28.516 15.0924 28.5082L7.04046 23.8557C5.32135 22.8601 4.06716 21.2235 3.55289 19.3046C3.03862 17.3858 3.30624 15.3413 4.29707 13.6194ZM31.955 20.0556L22.2312 14.4411L25.5976 12.4981C25.6142 12.4872 25.6333 12.4805 25.6531 12.4787C25.6729 12.4769 25.6928 12.4801 25.7111 12.4879L33.7631 17.1364C34.9967 17.849 36.0017 18.8982 36.6606 20.1613C37.3194 21.4244 37.6047 22.849 37.4832 24.2684C37.3617 25.6878 36.8382 27.0432 35.9743 28.1759C35.1103 29.3086 33.9415 30.1717 32.6047 30.6641C32.6047 30.5947 32.6047 30.4733 32.6047 30.3889V21.188C32.6066 20.9586 32.5474 20.7328 32.4332 20.5338C32.319 20.3348 32.154 20.1698 31.955 20.0556ZM35.3055 15.0128C35.2464 14.9765 35.1431 14.9142 35.069 14.8717L27.1045 10.2712C26.906 10.1554 26.6803 10.0943 26.4504 10.0943C26.2206 10.0943 25.9948 10.1554 25.7963 10.2712L16.0726 15.8858V11.9982C16.0715 11.9783 16.0753 11.9585 16.0837 11.9405C16.0921 11.9225 16.1048 11.9068 16.1207 11.8949L24.1719 7.25025C25.4053 6.53903 26.8158 6.19376 28.2383 6.25482C29.6608 6.31589 31.0364 6.78077 32.2044 7.59508C33.3723 8.40939 34.2842 9.53945 34.8334 10.8531C35.3826 12.1667 35.5464 13.6095 35.3055 15.0128ZM14.2424 21.9419L10.8752 19.9981C10.8576 19.9893 10.8423 19.9763 10.8309 19.9602C10.8195 19.9441 10.8122 19.9254 10.8098 19.9058V10.6071C10.8107 9.18295 11.2173 7.78848 11.9819 6.58696C12.7466 5.38544 13.8377 4.42659 15.1275 3.82264C16.4173 3.21869 17.8524 2.99464 19.2649 3.1767C20.6775 3.35876 22.0089 3.93941 23.1034 4.85067C23.0427 4.88379 22.937 4.94215 22.8668 4.98473L14.9024 9.58517C14.7025 9.69878 14.5366 9.86356 14.4215 10.0626C14.3065 10.2616 14.2466 10.4877 14.2479 10.7175L14.2424 21.9419ZM16.071 17.9991L20.4018 15.4978L24.7325 17.9975V22.9985L20.4018 25.4983L16.071 22.9985V17.9991Z" fill="currentColor"></path></svg></div></div></div></div></div>**Configurar Instrumentação Automática**  
Para gerenciar a instrumentação automática, o operador precisa ser configurado para identificar quais pods instrumentar e qual instrumentação automática usar nesses pods. Isso é feito por meio do **CRD de Instrumentação**.

A criação correta do recurso de Instrumentação é fundamental para que a instrumentação automática funcione. Certifique-se de que todos os endpoints e variáveis de ambiente estejam configurados corretamente.

<div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn" id="bkmrk--2"><div class="flex-col gap-1 md:gap-3"><div class="flex max-w-full flex-col flex-grow"><div class="min-h-8 text-message flex w-full flex-col items-end gap-2 whitespace-normal break-words text-start [.text-message+&]:mt-5" data-message-author-role="assistant" data-message-id="98ca316b-db86-407f-98c5-d3fc454e0a1e" data-message-model-slug="gpt-4o" dir="auto"><div class="flex w-full flex-col gap-1 empty:hidden first:pt-[3px]"><div class="markdown prose w-full break-words dark:prose-invert light">---

</div></div></div></div></div></div>### **.NET**

O seguinte comando criará um recurso básico de Instrumentação configurado especificamente para serviços .NET:

<div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn" id="bkmrk-bash-copy-code-kubec"><div class="flex-col gap-1 md:gap-3"><div class="flex max-w-full flex-col flex-grow"><div class="min-h-8 text-message flex w-full flex-col items-end gap-2 whitespace-normal break-words text-start [.text-message+&]:mt-5" data-message-author-role="assistant" data-message-id="98ca316b-db86-407f-98c5-d3fc454e0a1e" data-message-model-slug="gpt-4o" dir="auto"><div class="flex w-full flex-col gap-1 empty:hidden first:pt-[3px]"><div class="markdown prose w-full break-words dark:prose-invert light"><div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none">bash</div><div class="sticky top-9 md:top-[5.75rem]"><div class="absolute bottom-0 right-2 flex h-9 items-center"><div class="flex items-center rounded bg-token-sidebar-surface-primary px-2 font-sans text-xs text-token-text-secondary dark:bg-token-main-surface-secondary"><span class="" data-state="closed"><button aria-label="Copy" class="flex gap-1 items-center select-none py-1"><svg class="icon-sm" fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor" fill-rule="evenodd"></path></svg>Copy code</button></span></div></div></div><div class="overflow-y-auto p-4" dir="ltr">`kubectl apply -f - <<<span class="hljs-string">EOFapiVersion: opentelemetry.io/v1alpha1kind: Instrumentationmetadata:  name: demo-instrumentationspec:  exporter:    endpoint: http://demo-collector:4318  propagators:    - tracecontext    - baggage  sampler:    type: parentbased_traceidratio    argument: "1"EOF</span>`</div></div></div></div></div></div></div></div>Por padrão, o recurso de Instrumentação para serviços .NET usa OTLP com o protocolo HTTP/Protobuf. O endpoint configurado deve ser capaz de receber OTLP via HTTP/Protobuf, como no exemplo: `http://demo-collector:4318`.

#### **Excluindo bibliotecas de instrumentação**

Se você não quiser usar determinadas bibliotecas, configure as variáveis de ambiente `OTEL_DOTNET_AUTO_[SIGNAL]_[NAME]_INSTRUMENTATION_ENABLED=false`.

Exemplo:

<div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn" id="bkmrk-yaml-copy-code-dotne"><div class="flex-col gap-1 md:gap-3"><div class="flex max-w-full flex-col flex-grow"><div class="min-h-8 text-message flex w-full flex-col items-end gap-2 whitespace-normal break-words text-start [.text-message+&]:mt-5" data-message-author-role="assistant" data-message-id="98ca316b-db86-407f-98c5-d3fc454e0a1e" data-message-model-slug="gpt-4o" dir="auto"><div class="flex w-full flex-col gap-1 empty:hidden first:pt-[3px]"><div class="markdown prose w-full break-words dark:prose-invert light"><div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none">yaml</div><div class="sticky top-9 md:top-[5.75rem]"><div class="absolute bottom-0 right-2 flex h-9 items-center"><div class="flex items-center rounded bg-token-sidebar-surface-primary px-2 font-sans text-xs text-token-text-secondary dark:bg-token-main-surface-secondary"><span class="" data-state="closed"><button aria-label="Copy" class="flex gap-1 items-center select-none py-1"><svg class="icon-sm" fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor" fill-rule="evenodd"></path></svg>Copy code</button></span></div></div></div><div class="overflow-y-auto p-4" dir="ltr">`<span class="hljs-attr">dotnet:</span>  <span class="hljs-attr">env:</span>    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">OTEL_DOTNET_AUTO_TRACES_GRPCNETCLIENT_INSTRUMENTATION_ENABLED</span>      <span class="hljs-attr">value:</span> <span class="hljs-literal">false</span>    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">OTEL_DOTNET_AUTO_METRICS_PROCESS_INSTRUMENTATION_ENABLED</span>      <span class="hljs-attr">value:</span> <span class="hljs-literal">false</span>`</div></div>---

</div></div></div></div></div></div>### **Java**

O seguinte comando criará um recurso básico de Instrumentação para serviços Java:

<div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn" id="bkmrk-bash-copy-code-kubec-1"><div class="flex-col gap-1 md:gap-3"><div class="flex max-w-full flex-col flex-grow"><div class="min-h-8 text-message flex w-full flex-col items-end gap-2 whitespace-normal break-words text-start [.text-message+&]:mt-5" data-message-author-role="assistant" data-message-id="98ca316b-db86-407f-98c5-d3fc454e0a1e" data-message-model-slug="gpt-4o" dir="auto"><div class="flex w-full flex-col gap-1 empty:hidden first:pt-[3px]"><div class="markdown prose w-full break-words dark:prose-invert light"><div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none">bash</div><div class="sticky top-9 md:top-[5.75rem]"><div class="absolute bottom-0 right-2 flex h-9 items-center"><div class="flex items-center rounded bg-token-sidebar-surface-primary px-2 font-sans text-xs text-token-text-secondary dark:bg-token-main-surface-secondary"><span class="" data-state="closed"><button aria-label="Copy" class="flex gap-1 items-center select-none py-1"><svg class="icon-sm" fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor" fill-rule="evenodd"></path></svg>Copy code</button></span></div></div></div><div class="overflow-y-auto p-4" dir="ltr">`kubectl apply -f - <<<span class="hljs-string">EOFapiVersion: opentelemetry.io/v1alpha1kind: Instrumentationmetadata:  name: demo-instrumentationspec:  exporter:    endpoint: http://demo-collector:4318  propagators:    - tracecontext    - baggage  sampler:    type: parentbased_traceidratio    argument: "1"EOF</span>`</div></div></div></div></div></div></div></div>Por padrão, a instrumentação Java usa OTLP com HTTP/Protobuf.

#### **Excluindo bibliotecas de instrumentação**

Para desativar bibliotecas específicas:

<div class="group/conversation-turn relative flex w-full min-w-0 flex-col agent-turn" id="bkmrk-use-otel_instrumenta-1"><div class="flex-col gap-1 md:gap-3"><div class="flex max-w-full flex-col flex-grow"><div class="min-h-8 text-message flex w-full flex-col items-end gap-2 whitespace-normal break-words text-start [.text-message+&]:mt-5" data-message-author-role="assistant" data-message-id="98ca316b-db86-407f-98c5-d3fc454e0a1e" data-message-model-slug="gpt-4o" dir="auto"><div class="flex w-full flex-col gap-1 empty:hidden first:pt-[3px]"><div class="markdown prose w-full break-words dark:prose-invert light">- Use `OTEL_INSTRUMENTATION_[NAME]_ENABLED=false`.
- Para desativar todas por padrão e ativar somente algumas: <div class="contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950"><div class="flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none">bash</div><div class="sticky top-9 md:top-[5.75rem]"><div class="absolute bottom-0 right-2 flex h-9 items-center"><div class="flex items-center rounded bg-token-sidebar-surface-primary px-2 font-sans text-xs text-token-text-secondary dark:bg-token-main-surface-secondary"><span class="" data-state="closed"><button aria-label="Copy" class="flex gap-1 items-center select-none py-1"><svg class="icon-sm" fill="none" height="24" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M7 5C7 3.34315 8.34315 2 10 2H19C20.6569 2 22 3.34315 22 5V14C22 15.6569 20.6569 17 19 17H17V19C17 20.6569 15.6569 22 14 22H5C3.34315 22 2 20.6569 2 19V10C2 8.34315 3.34315 7 5 7H7V5ZM9 7H14C15.6569 7 17 8.34315 17 10V15H19C19.5523 15 20 14.5523 20 14V5C20 4.44772 19.5523 4 19 4H10C9.44772 4 9 4.44772 9 5V7ZM5 9C4.44772 9 4 9.44772 4 10V19C4 19.5523 4.44772 20 5 20H14C14.5523 20 15 19.5523 15 19V10C15 9.44772 14.5523 9 14 9H5Z" fill="currentColor" fill-rule="evenodd"></path></svg>Copy code</button></span></div></div></div><div class="overflow-y-auto p-4" dir="ltr">`OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED=<span class="hljs-literal">false</span>OTEL_INSTRUMENTATION_[NAME]_ENABLED=<span class="hljs-literal">true</span>`</div></div>

---

</div></div></div></div></div></div>### **Node.js**

O seguinte comando criará um recurso básico de Instrumentação para serviços Node.js:

```bash
kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4317
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"
EOF
```

Por padrão, a instrumentação Node.js usa OTLP com gRPC.

#### **Gerenciar bibliotecas de instrumentação**

- Para ativar bibliotecas específicas:

```yaml
nodejs:
  env:
    - name: OTEL_NODE_ENABLED_INSTRUMENTATIONS
      value: http,nestjs-core
```

- Para desativar específicas:

```yaml
nodejs:
  env:
    - name: OTEL_NODE_DISABLED_INSTRUMENTATIONS
      value: fs,grpc
```

### **Python**

O seguinte comando criará um recurso básico de Instrumentação para serviços Python:

```bash
kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: python-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"
EOF
```

Por padrão, Python usa OTLP com HTTP/Protobuf.

#### **Logs em Python**

Para ativar a instrumentação automática de logs:

```yaml
python:
  env:
    - name: OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED
      value: 'true'
```

#### **Excluindo bibliotecas de instrumentação**

Defina `OTEL_PYTHON_DISABLED_INSTRUMENTATIONS` com os pacotes a serem excluídos.

### **Go**

Para serviços Go, crie o recurso básico de Instrumentação:

```bash
kubectl apply -f - <<EOF
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators:
    - tracecontext
    - baggage
  sampler:
    type: parentbased_traceidratio
    argument: "1"
EOF
```

A instrumentação Go usa um agente eBPF em um sidecar, que requer permissões elevadas.

Adicione anotações para ativar a instrumentação automática:

```yaml
instrumentation.opentelemetry.io/inject-go: 'true'
instrumentation.opentelemetry.io/otel-go-auto-target-exe: '/path/to/executable'
```

### **Habilitar Instrumentação Automática**

Adicione anotações ao seu deployment para ativar a instrumentação automática:

- .NET: `instrumentation.opentelemetry.io/inject-dotnet: "true"`
- Java: `instrumentation.opentelemetry.io/inject-java: "true"`
- Node.js: `instrumentation.opentelemetry.io/inject-nodejs: "true"`
- Python: `instrumentation.opentelemetry.io/inject-python: "true"`
- Go: `instrumentation.opentelemetry.io/inject-go: "true"`

# Ingestão de Dados e Backend de Armazenamento

O Priax suporta diferentes backends de armazenamento para Traces, Logs e Métricas coletados e podendo trabalhar com Opensearch, ou Elasticsearch. Para que os dados sejam injetados nessas bases de dados, utilizamos o OpenTelemetry Collector, e pode ser combinado ou não com outras tecnologias de transporte e transformação de dados como o Data Prepper e o Kafka.

Apresentaremos aqui os conceitos básicos do Collector e cenários práticos de implantação para utilização destas tecnologias com o Priax.

### Data Collector

O Collector oferece uma implementação independente de fornecedor para receber, processar e exportar dados de telemetria. Ele elimina a necessidade de operar e manter múltiplos agentes/coletores. O Collector funciona com escalabilidade aprimorada e suporta formatos de dados de observabilidade de código aberto (por exemplo, Jaeger, Prometheus, Fluent Bit, etc.), enviando para um ou mais backends de código aberto ou comerciais. O agente Collector local é o destino padrão para o qual as bibliotecas de instrumentação exportam seus dados de telemetria.

**Objetivos**

- **Usabilidade**: Configuração padrão prática, suporta protocolos populares, funciona e coleta dados imediatamente.
- **Desempenho**: Altamente estável e eficiente sob diferentes cargas e configurações.
- **Observabilidade**: Um exemplo de serviço observável.
- **Extensibilidade**: Personalizável sem necessidade de alterar o código principal.
- **Unificação**: Base de código única, implantável como agente ou coletor, com suporte para rastros, métricas e logs.

Em abbientes de desenvolvimento ou testes e para ter resultados rápido com a observabilidade de maneira pontual é possível enviar seus dados diretamente de sua aplicação para um backend. Em ambientes de produção, no entanto, recomendamos usar um coletor junto com seus serviços, pois ele permite que o serviço descarregue dados rapidamente, realize cache quando necessário e, além disso, o coletor pode lidar com tarefas adicionais, como tentativas de reenvio, agrupamento, criptografia ou até mesmo filtragem de dados sensíveis.

O Collector facilita a unificação de dados, visto que suporta diversas formas de ingestão (Receivers) e diversas formas de exportação de dados (Exporters). Abaixo podemos ver como o Collector trabalha e como ele pode ser utilizado para enviar dados para os Backends de Armazenamento compatíveis com o Priax.

[![image.png](https://docs.app.priax.io/uploads/images/gallery/2024-12/scaled-1680-/weWimage.png)](https://docs.app.priax.io/uploads/images/gallery/2024-12/weWimage.png)

Como se pode observar o Collector pode receber dados diretamente das aplicações instrumentadas, de outros sistemas de observabilidade como o Prometheus ou o Jaeger mas também pode receber dados de outros Collectors ou buscar dados em sistemas Kafka, que podem ter sido alimentados por outros Collectors. Dessa forma pode-se criar um layout de implantação flexível onde os Collectors podem atuar como gateways concentradores ou como agentes de simples transmissão de dados para os BackEnds de Armazenamento. Para enviar dados para o Backend de armazenamento compatível com o Priax (Opensearch) o Collector pode ou não utilizar o Data Prepper (ver abaixo as informações sobre o DataPrepper).

Para compreender mais sobre os layouts de implantação do Data Collector, consulte a [página do OpenTelemetry que trata sobre o assunto.](https://opentelemetry.io/docs/collector/deployment/)

#### Instalação e Configuração dos Collectors

A instalação dos Collectors é relativamente simples e pode ser realizada diretamente sobre os sistemas operacionais Windows ou Linux ou ainda utilizando Docker ou Kubernetes. As instruções para instalação podem ser consultadas na [página de instalação do Collector do OpenTelemetry.](https://opentelemetry.io/docs/collector/installation/)

A Configuração completa do Collector pode ser consultada na [extensa documentação fornecida pelo OpenTelemetry](https://opentelemetry.io/docs/collector/configuration/) porém aqui apresentamos alguns cenários tipicamente utilizados.

##### Configuração do Collector para uso com e sem Data Prepper

```yaml
receivers:
  otlp:
    protocols:
      http:
        #include_metadata: true
        cors:
          allowed_origins: ["http://*"]
          allowed_headers: ["*"]
          #max_age: 7200
        #endpoint: 127.0.0.1:4318
  kafka:
    protocol_version: 3.3.0
    group_id: priaxapm1
    encoding: otlp_proto
    brokers: 
      - priax-teste-01.servicebus.windows.net:9093
    topic: priax
    auth:
      sasl:
        username: $$ConnectionString
        password: Endpoint=sb://kafkaAzure.servicebus.windows.net/;SharedAccessKeyName=teste-priax;SharedAccessKey=z5kREHICeAw0EEMySt7cP2kgh4XGb/zh4+AEhMe7r0g=;EntityPath=priax
        mechanism: PLAIN
      tls:
        insecure: true
processors:
  batch: {}
  tail_sampling/priax:
    decision_wait: 40s
    policies:
      - name: sample-ottl
        type: ottl_condition
        ottl_condition:
          span:
            - "status.code == 2 and attributes[\"lime.envelope.type\"] == nil"
            - "status.code == 2 and attributes[\"lime.envelope.type\"] != nil and attributes[\"lime.envelope.type\"] != \"Notification\""
            - "end_time - start_time > Duration(\"29s\")"
            - "attributes[\"sample.force\"] == true"
      - name: probabilistic-policy
        type: probabilistic
        probabilistic:
          hash_salt: "custom-salt"
          sampling_percentage: 0.1
  k8sattributes:
    extract:
      metadata:
      - k8s.namespace.name
      - k8s.deployment.name
      - k8s.statefulset.name
      - k8s.daemonset.name
      - k8s.cronjob.name
      - k8s.job.name
      - k8s.node.name
      - k8s.pod.name
      - k8s.pod.uid
      - k8s.pod.start_time
    passthrough: false
    pod_association:
    - sources:
      - from: resource_attribute
        name: k8s.pod.ip
    - sources:
      - from: resource_attribute
        name: k8s.pod.uid
    - sources:
      - from: connection
  memory_limiter:
    check_interval: 5s
    limit_percentage: 80
    spike_limit_percentage: 25
  resource:
    attributes:
    - action: insert
      from_attribute: k8s.pod.uid
      key: service.instance.id
exporters:
  debug:
    verbosity: detailed
  otlp/data-prepper:
    endpoint: data-prepper:21890
    tls:
      insecure: true
  opensearch:
    http:
    endpoint: https://opensearchserver:9200
    auth:
      authenticator: basicauth/client
extensions:
  health_check:
  pprof:
  zpages:
    endpoint: ":55679"
  basicauth/client:
    client_auth:
      username: ingester
      password: ingesterpass
service:
  extensions: [health_check, pprof, zpages]
  pipelines:
    traces:
      receivers: [otlp]
      processors: [k8sattributes,memory_limiter,resource,batch,tail_sampling/priax]
      exporters: [debug,opensearch]
    metrics:
      receivers: [otlp]
      processors: [k8sattributes,memory_limiter,resource,batch]
      exporters: [debug,opensearch]
    logs:
      receivers: [otlp]
      processors: [k8sattributes,memory_limiter,resource,batch]
      exporters: [debug,opensearch]
    traceswithKafkaandDataprepper:
      receivers: [kafka]
      processors: [k8sattributes,memory_limiter,resource,batch]
      exporters: [debug,otlp/dataprepper]
    metricswithKafkaandDataprepper:
      receivers: [kafka]
      processors: [k8sattributes,memory_limiter,resource,batch]
      exporters: [debug,otlp/dataprepper]
    logswithKafkaandDataprepper:
      receivers: [kafka]
      processors: [k8sattributes,memory_limiter,resource,batch]
      exporters: [debug,otlp/dataprepper]
```

##### Amostragem de Traces e Spans

É importante perceber que a configuração acima define que serão enviadas ao Backend de Armazenamento o 0,1% das spans coletadas pela instrumentação. Isso se dá nos trechos destacados abaixo:

```
[...]
processors:
[...]
  tail_sampling/priax:
    decision_wait: 40s
    policies:
      - name: sample-ottl
        type: ottl_condition
        ottl_condition:
          span:
            - "end_time - start_time > Duration(\"29s\")"
            - "attributes[\"sample.force\"] == true"
      - name: probabilistic-policy
        type: probabilistic
        probabilistic:
          hash_salt: "custom-salt"
          sampling_percentage: 0.1
[...]
pipelines:
  traces:
      receivers: [otlp]
      processors: [k8sattributes,memory_limiter,resource,batch,tail_sampling/priax] 
      # Para não utilizar o sampling neste pipeline basta rever o processador tail_sampling/priax desta seção.
      exporters: [debug,opensearch]
    traces:
      receivers: 
        - kafka
      processors:
        - batch
        - tail_sampling/priax 
      exporters: 
        - otlp/data-prepper
[...]
```

Para que sejam enviados 100% dos traces para o Backend de Armazenamento, remova a configuração de sampling do pipeline desejado conforme comentado no exemplo acima.

### Data Prepper

**Data Prepper**  
O Data Prepper é um componente da infraestrutura do Opensearch. É um coletor de dados do lado do servidor, capaz de filtrar, enriquecer, transformar, normalizar e agregar dados para análise e visualização posteriores. É a ferramenta de ingestão de dados preferida para o OpenSearch, recomendada para a maioria dos casos de uso de ingestão de dados no OpenSearch, especialmente para o processamento de conjuntos de dados grandes e complexos.

Com o Data Prepper, você pode criar pipelines personalizados para melhorar a visão operacional de suas aplicações. Dois casos de uso comuns do Data Prepper são a análise de rastros (trace analytics) e a análise de logs (log analytics). A análise de rastros ajuda a visualizar fluxos de eventos e identificar problemas de desempenho. Já a análise de logs oferece ferramentas para aprimorar as capacidades de busca, realizar análises detalhadas e obter insights sobre o desempenho e o comportamento das suas aplicações.

**Conceitos-chave e fundamentos**  
O Data Prepper processa dados por meio de pipelines personalizáveis. Esses pipelines são compostos por componentes modulares que podem ser ajustados para atender às suas necessidades, inclusive permitindo a integração de implementações próprias. Um pipeline do Data Prepper consiste nos seguintes componentes:

- **Uma fonte (source)**
- **Um ou mais destinos (sinks)**
- **(Opcional) Um buffer**
- **(Opcional) Um ou mais processadores (processors)**

Cada pipeline contém dois componentes obrigatórios: a **fonte** e o **destino**. Se um buffer, um processador, ou ambos estiverem ausentes do pipeline, o Data Prepper usará o buffer padrão `bounded_blocking` e um processador `no-op`. É importante observar que uma única instância do Data Prepper pode conter um ou mais pipelines.

O uso do Data Prepper com o Priax, facilita a adoção de padrões do Opensearch e é altamente recomendável.

**Instalação do Data Prepper**

A instalação do Data Prepper é relativamente simples e sua documentação pode ser consultada diretamente na [página do OpenSearch](https://opensearch.org/docs/latest/data-prepper/getting-started/).

**Configurações básicas de pipeline**

A configuração básica do Data Prepper para uso com o Priax pode ser vista abaixo:

```yaml
entry-pipeline:
  delay: "100"
  source:
    otel_trace_source:
      ssl: false
    buffer:
      buffer_size: 10240
      batch_size: 160
  sink:
    - pipeline:
        name: "raw-trace-pipeline"
    - pipeline:
        name: "service-map-pipeline"
raw-trace-pipeline:
  source:
    pipeline:
      name: "entry-pipeline"
  buffer:
    bounded_blocking:
      buffer_size: 10240
      batch_size: 160
  processor:
    - otel_trace_raw:
  sink:
    - stdout: null
    - opensearch:
        hosts: ["http://opensearchserver:9200"]
        username: ingester
        password: passwordingester
        max_retries: 20
        bulk_size: 4
        insecure: true
        index_type: trace-analytics-raw
service-map-pipeline:
  delay: "100"
  source:
    pipeline:
      name: "entry-pipeline"
  buffer:
    bounded_blocking:
      buffer_size: 10240
      batch_size: 160
  processor:
    - service_map_stateful:
  sink:
    - stdout: null
    - opensearch:
        hosts: ["http://opensearchserver:9200"]
        username: ingester
        password: passwordingester
        max_retries: 20
        bulk_size: 4
        insecure: true
        index_type: trace-analytics-service-map
```

# Visualização de Dados de Aplicações

### Conceitos Essenciais

O Priax oferece os recursos visuais para analisar o desempenho, a estrutura, as dependências de aplicações. Para que se possa compreender essas telas é importante entender alguns conceitos iniciais.

<table border="1" id="bkmrk-conceito-descri%C3%A7%C3%A3o-s" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 50.0596%;"></col><col style="width: 50.0596%;"></col></colgroup><tbody><tr><td align="left" height="20" style="height: 15.0pt; width: 48pt;" width="64">Conceito</td><td align="left" style="width: 48pt;" width="64">Descrição</td></tr><tr><td align="left" height="20" style="height: 15.0pt;">Serviço</td><td align="left">Os serviços são os blocos de construção das arquiteturas modernas de microserviços. Em termos gerais, um serviço agrupa endpoints, consultas ou tarefas com o objetivo de construir o aplicativo. Em aplicações mais antigas, um serviço representa uma porção lógica da aplicação que desempenha uma porção de trabalho delimitável da aplicação.</td></tr><tr><td align="left" height="20" style="height: 15.0pt;">Transação</td><td align="left">Representam um trecho de código delimitado sendo executado dentro de um serviço. Tal trecho de código pode ser o atendimento de usuários remotos através de um socket de rede (por exemplo um servidor Web atendendo a um usuário), a execução de uma lógica ou função interna para montar a resposta para esse usuário ou a conexão à serviços de rede externos para coletar dados ou informações necessárias.</td></tr><tr><td align="left" height="20" style="height: 15.0pt;">Indicadores/Métricas</td><td align="left">Métricas APM funcionam como métricas regulares, mas com controles específicos para o APM. Use essas métricas para receber alertas no nível do serviço sobre acessos, erros e diversas medidas de latência.</td></tr><tr><td align="left" height="20" style="height: 15.0pt;">Trace</td><td align="left">Um trace é usado para rastrear o tempo gasto por um aplicativo processando uma solicitação e o status dessa solicitação. Cada trace consiste de um ou mais spans.</td></tr><tr><td align="left" height="20" style="height: 15.0pt;">Instrumentação</td><td align="left">Instrumentação é o processo de adicionar código ao seu aplicativo para capturar e relatar dados de observabilidade.</td></tr></tbody></table>

### Explorando Serviços, Traces e Transações

Depois de instrumentar serviços e ativar o discovery de transações no Priax, os serviços serão populados com as transações que estão sendo executadas pelas aplicações e suas interações com usuários e demais sistemas com os quais trocam informações. No Priax, um serviço pode ser representado por um Container (oriundos de sistemas Docker ou similares), um Deplyment, Statefulset, Daemonset (esses três últimos componentes de um cluster Kubernetes) ou ainda por aplicações hospedadas em servidores de aplicação ou interpretadores de linguagens (java, .net, php, ruby, perl, pyton, etc).

Abaixo podemos ver um exemplo de Deployment de um cluster Kubernetes com as transações executadas dentro de seus Pods. Neste caso o Deployment representa o Serviço da aplicação instrumentada.

[![image.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/Fbkimage.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/Fbkimage.png)

Para ver o mapa de um serviço instrumentado, basta selecioná-lo e no canto superior direito do painel da esquerda acessar suas dependências no botão [![image.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/dhTimage.png).](https://docs.app.priax.io/uploads/images/gallery/2025-10/dhTimage.png)

.

[![Screenshot 2024-12-19 003040.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2024-12-19-003040.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/screenshot-2024-12-19-003040.png)

Nesta tela é exibido o mapa de dependências do Serviço. Podemos visualizar tanto os componentes internos das aplicações, representados por transações quanto os componentes da infraestrutura que suportam essas transações, como bases de dados e a estrutura do Kubernetes. Ao selecionar uma Transação, são exibidas à direita os gráficos de Time Series dos indicadores e métricas que são gerados ao longo do tempo como a média de tempo de execução, taxa de erros e taxa de transferência de dados.

[![Screenshot 2024-12-19 184059.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2024-12-19-184059.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/screenshot-2024-12-19-184059.png)

Ao selecionar uma operação na árvore, abaixo são exibidas os detalhes das transações e clicando na aba Transactions você pode filtrar o tempo de exibição que deseja para visualizar as ocorrências quando aquela operação foi executada pela aplicação.

[![image.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/GvGimage.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/GvGimage.png)

Desta fora são exibidas todas execuções da operação ocorridas naquele período de tempo.

[![image.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/B2Oimage.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/B2Oimage.png)

No ícone [![image.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/koQimage.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/koQimage.png), podemos personalizar a janela de tempo que será exibida. Podemos também dar zoom-in e zoom-out ao longo do tempo para poder ter mais detalhes das execuções da transação. As barras que representam cada execução fornecem informações importantes sobre o tempo que levou cada execução. Barras mais longas foram as execuções que mais demoraram, e o tempo de execução pode ser visto passando o mouse em cima de cada execução, o que nos fornece outras informações como ID da Span e do Trace.

Ao clicar em uma das execuções podemos explorar todo o Trace da qual a execução da Transação faz parte e assim podemos compreender exatamente como transcorreu aquela execução, como foi chamada, por qual transação e o que ocorreu com aquela chamada de sistema como um todo.

[![image.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/8bDimage.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/8bDimage.png)

O gráfico de Destacado em vermelho, acima, mostra a linha de tempo e a relação pai-filho entre as spans (execuções da transação) e o gráfico em verde, mostra como o tempo foi percentualmente distribuído entre as spans pai e filho de cada trace.  
Clicando em cada span em qualquer um dos gráficos, é possível ver os detalhes de cada execução, incluindo logs e parâmetros de execução.

[![image.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/wK6image.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/wK6image.png)

As métricas para cada transação tal como: tempo médio Latency (ou Avg Transaction Time), Número de execuções por período (Calls), taxa de erros por período (Error Tax), são exibidas no painel da direita, além de diversos dashboards com será demonstrado nesse documento.

Dentre as diversas tipos de transações que o Priax consegue detectar e analisar, exibir estatísticas, gráfcos e realizar drill down , além de produzir eventos e alertas estão:

- Transações de Servidor HTTP, gRPC, RPC,
- Transações internas (trechos de código que são executados internamente na aplicação, sem interação externa)
- Chamadas de Web Services para outros sistemas, estejam eles instrumentados ou não;
- Consultas à bancos de dados relacionais e não relacionais;
- Produção e consumo em sistemas de mensagens e filas como Kafka e RabbitMQ;
- Dados produzidos pelo navegador, coletado diretamente o comportamento do usuário.

> Os indicadores tradicionalmente coletadas para cada Transação são:
> 
> - Média de Tempo de Execução ao longo do tempo para 5, 10 e 15 minutos.
> - Média de Taxa de erros de execução ao longo do tempo para 5, 10 e 15 minutos.
> - Média de taxa de transferência de dados para 5, 10 e 15 minutos.
> 
> No entanto as métricas podem ser customizadas para cada caso.

### Detectando problemas em Transações

Ao detectar um problema, que pode ser pela detecção de limites auto-calculados o Priax realiza, com a utilização de técnicas de análise de dados e machine learning, uma análise profunda de causa raiz, diferenciando os indicadores que representam um sintoma dos indicadores que de fato estão causando o problema, e unificando isso em um único Evento.

[![Screenshot 2024-12-19 100758.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2024-12-19-100758.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/screenshot-2024-12-19-100758.png)

A partir do momento que um novo evento é detectado e sua causa raiz isolada, ele pode ser direcionado para a equipe e indivíduo correto, podendo ele realizar análise das correlações dos indicadores e itens de configuração envolvidos no Evento.

[![Screenshot 2024-12-19 100022.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2024-12-19-100022.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/screenshot-2024-12-19-100022.png)

Ao receber um evento, você pode realizar a análise de impactos e de dependências da Transação causa-raiz do evento, o que nos permite entender quais outras Transações, Serviços e Aplicações estão sendo afetadas pelo problema. Ao analisar as dependências, também podemos detectar indicadores de infraestrutura que podem estar causando indiretamente o Evento.

Sempre que um Evento é criado são realizadas as análises que evitam a duplicação de eventos, criação de falsos positivos e a criação de eventos isolados quando esses possuem a mesma causa raíz. Para tal o Priax realiza:

- Identificação de Indicadores correlacionados na mesma árvore de Causa-Efeito: Este procedimento garante que apenas um evento seja criado quando múltiplas transações dependentes entre sí, ou ainda recursos que sustentam essas transações estejam reportando comportamento anormal. Neste caso o Item de Configuração ou transação de mais baixo nível na árvore de causa-efeito será a eleito como causa raíz, e todos os demais itens impactados serão reportados como impactos neste mesmo evento.
- Análise flapping: Utilizada para indicadores com alternância constante entre estados, evitando a criação de eventos múltiplos para o mesmo indicador causa-raiz.

As trigger para disparo de Eventos podem ser configuradas manualmente ou ainda podem ser calculadas baseadas nos dados históricos com técnicas de Análise de Dados e Machine Learning.

[![Screenshot 2024-12-18 201953.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2024-12-18-201953.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/screenshot-2024-12-18-201953.png)

Na tela acima, de edição do Indicador é possível habilitar o aprendizado de Triggers, definir se os limites deverão ser abaixo, acima ou abaixo e acima da normalidade, definir se haverá um perfil diferente de trigger por dia da semana e por horário, além de definir qual será o menor nível de alerta que será gerado pelas trigger automaticamente aprendidas.

<p class="callout info">Para saber mais sobre o Gerenciamento de Eventos, consulte o capítulo específico sobre Gerenciamento de Operações e Eventos neste manual.</p>

### APM Dashboards

Após instrumentar uma aplicação ou serviço e coletar métricas, traces e logs é possível no Priax criar painéis e relatórios a respeito de Transações ocorridas dentro de cada Serviço da Aplicação. Ao longo do tempo, com a execução continuada das transações, são produzidos dados Time Series com os indicadores relevantes a respeito de cada transação, como por exemplo:

- Média de Tempo de Execução ao longo do tempo para 5, 10 e 15 minutos.
- Média de Taxa de erros de execução ao longo do tempo para 5, 10 e 15 minutos.
- Média de taxa de transferência (throughput) de dados para 5, 10 e 15 minutos.

Tais dados podem ser visualizados em Dashboards customizados agregados por:

- Aplicações: Conjunto de Serviços que são agrupados logicamente formando a Aplicação.
- Serviços; Componente instrumentado e identificado com o mesmo nome de Serviço.
- EndPoints: Todo o destino de conexão identificado pelo conjunto de transações executadas em determinado período de tempo.
- Transação: Cada operação identificada por um nome na instrumentação realizada.

Abaixo pode ser visualizado um exemplo de Dashboard que apresenta dados sobre as Transações executadas ao londo de determinado período. Os Dashboards podem ser acessados através do ícone destacado na barra de ícones da esquerda na imagem abaixo.

[![Screenshot 2024-12-19 121344.png](https://docs.app.priax.io/uploads/images/gallery/2025-10/scaled-1680-/screenshot-2024-12-19-121344.png)](https://docs.app.priax.io/uploads/images/gallery/2025-10/screenshot-2024-12-19-121344.png)

Na tela acima são exibidos de acordo com o Número destacado:

1. Tela de Filtros: Os filtros podem ser aplicados para definir quais Transações serão considerados no Dashboard. Neste dashboard de exemplo, foram adicionados componentes para que se possa filtrar por Aplicação, Serviço, Transação e Host que executou a transação. É possível, no entanto, filtrar por qualquer Atributo presente nas Spans, como por exemplo, por qualquer campo que represente um endpoint ou pelo tipo de operação realizada.
2. Gráfico que exibe a taxa de execução e de erros ocorrida nas transações filtradas em cada período de tempo.
3. Gráfico que exibe latência média e nos percentis 75 e 99 para cada período de tempo.

Todas os dashboards podem ser filtrados ao nível de Transação específica, podendo exibir dados dos seguintes tipos de transações entre outros:

- Transações de Servidor HTTP, gRPC, RPC: Contendo os endereços, métodos e detalhes da requisição realizada.
- Transações internas (trechos de código que são executados internamente na aplicação, sem interação externa): Contendo informações sobre o código executado, linguagem, versões, etc.
- Chamadas de Web Services para outros sistemas, estejam eles instrumentados ou não: Contendo os detalhes sobre a requisição http realizada.
- Consultas à bancos de dados relacionais e não relacionais: Contendo as consultar realizadas (Statement SQL) anonimizadas, a base de dados consultada, o endereço dos servidores consultados, etc.
- Produção e consumo em sistemas de mensagens e filas como Kafka e RabbitMQ: Contendo o nome dos tópicos os métodos de consumo e demais informações sobre o consumo ou produção nesses sistemas.
- Dados produzidos pelo navegador, coletado diretamente o comportamento do usuário: Contendo o detalhes sobre o User Agent (navegador) utilizado, ip, nome do usuário quando aplicável.

<p class="callout info">Os dashboards são completamente customizáveis, podendo receber novos componentes, filtros, gráficos e layout de exibição. Novos dashboards podem ser criados e publicados, criando novas abas de exibição no topo da tela de dashboards exibida na tela acima.</p>