Os rastros nos fornecem uma visão geral do que acontece quando uma solicitação é feita para uma aplicação. Seja sua aplicação um monólito com um único banco de dados ou uma grande variedade de serviços, os rastros são essenciais para compreender o “caminho” completo que uma solicitação percorreu na sua aplicação.
Vamos explorar isso com três unidades de trabalho, representadas como Trechos:
trecho olá
:
{
"name": "olá",
"context": {
"trace_id": "0x5b8aa5a2d2c872e8321cf37308d69df2",
"span_id": "0x051581bf3cb55c13"
},
"parent_id": null,
"start_time": "2022-04-29T18:52:58.114201Z",
"end_time": "2022-04-29T18:52:58.114687Z",
"attributes": {
"http.route": "alguma_rota1"
},
"events": [
{
"name": "Guten Tag!",
"timestamp": "2022-04-29T18:52:58.114561Z",
"attributes": {
"event_attributes": 1
}
}
]
}
Este é o trecho raiz, sinalizando o início e o fim de toda a operação. Note que
ele possui um campo trace_id
indicando o rastro, mas não possui parent_id
. É
assim que você sabe que é o trecho raiz.
O trecho olá-cumprimentos
:
{
"name": "olá-cumprimentos",
"context": {
"trace_id": "0x5b8aa5a2d2c872e8321cf37308d69df2",
"span_id": "0x5fb397be34d26b51"
},
"parent_id": "0x051581bf3cb55c13",
"start_time": "2022-04-29T18:52:58.114304Z",
"end_time": "2022-04-29T22:52:58.114561Z",
"attributes": {
"http.route": "alguma_rota2"
},
"events": [
{
"name": "e aí!",
"timestamp": "2022-04-29T18:52:58.114561Z",
"attributes": {
"event_attributes": 1
}
},
{
"name": "até logo!",
"timestamp": "2022-04-29T18:52:58.114585Z",
"attributes": {
"event_attributes": 1
}
}
]
}
Este trecho encapsula tarefas específicas, como dizer saudações, e seu pai é o
trecho olá
. Note que ele compartilha o mesmo trace_id
que o trecho raiz,
indicando que faz parte do mesmo rastro. Além disso, ele possui um parent_id
que corresponde ao span_id
do trecho olá
.
O trecho olá-saudações
:
{
"name": "olá-saudações",
"context": {
"trace_id": "0x5b8aa5a2d2c872e8321cf37308d69df2",
"span_id": "0x93564f51e1abe1c2"
},
"parent_id": "0x051581bf3cb55c13",
"start_time": "2022-04-29T18:52:58.114492Z",
"end_time": "2022-04-29T18:52:58.114631Z",
"attributes": {
"http.route": "alguma_rota3"
},
"events": [
{
"name": "olá!",
"timestamp": "2022-04-29T18:52:58.114561Z",
"attributes": {
"event_attributes": 1
}
}
]
}
Este trecho representa a terceira operação neste rastro e assim como o anterior,
é um filho do trecho olá
. Isso também o torna um irmão do trecho
olá-cumprimentos
.
Esses três blocos de JSON compartilham o mesmo trace_id
, e o campo parent_id
que representa uma hierarquia. Isso o torna um rastro!
Outra coisa que você notará é que cada trecho se parece com um log estruturado. Isso porque, de certa forma, é mesmo! Uma maneira de pensar em rastros é como uma coleção de logs estruturados com contexto, correlação, hierarquia e outros recursos. No entanto, esses “logs estruturados” podem vir de diferentes processos, serviços, VMs, data centers, e assim por diante. Isso torna possível que o rastreamento represente uma visão de ponta a ponta de qualquer sistema.
Para compreender como o rastreamento no OpenTelemetry funciona, vamos analisar uma lista de componentes que terão um papel fundamental na instrumentação do nosso código.
Um Trace Provider (às vezes chamado de TracerProvider
) é uma fábrica de
rastros
. Na maioria das aplicações, um Trace Provider é inicializado uma vez e
seu ciclo de vida corresponde ao ciclo de vida da aplicação. A inicialização do
Trace Provider também inclui a inicialização de Resource e Exporter. Geralmente
é a primeira etapa do rastreamento com OpenTelemetry. Em alguns SDKs, um Trace
Provider global já é inicializado para você.
Um rastro cria trechos contendo mais informações sobre o que está acontecendo em uma determinada operação, como uma solicitação em um serviço. Rastros são criados a partir de Trace Providers.
Trace Exporters enviam rastros para um consumidor. Esse consumidor pode ser a saída padrão para depuração em tempo de desenvolvimento, o OpenTelemetry Collector ou qualquer backend de código aberto ou fornecedor de sua escolha.
A propagação de contexto é o conceito central que possibilita o rastreamento distribuído. Com a propagação de contexto, trechos podem ser correlacionados entre si e montados em um rastro, independentemente de onde os trechos são gerados. Para saber mais sobre este tópico, consulte a página de conceitos sobre Propagação de Contexto.
Um trecho representa uma unidade de trabalho ou operação. Trechos são os blocos que compõem os rastros. No OpenTelemetry, eles incluem as seguintes informações:
Exemplo de trecho:
{
"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"
}
]
}
Trechos podem ser aninhados, como é indicado pela presença de um ID de trecho pai: trechos filhos representam sub-operações. Isso permite que os trechos capturem de forma mais precisa o trabalho realizado em uma aplicação.
O contexto do trecho é um objeto imutável em cada trecho que contém o seguinte:
O contexto do trecho é a parte de um trecho que é serializada e propagada junto com a propagação de contexto e baggage.
Como o contexto do trecho contém o trace ID, o trace ID é usado ao criar links de trechos.
Atributos são pares chave-valor que contêm metadados que você pode usar para anotar um trecho e carregar informações sobre a operação que ele está acompanhando.
Por exemplo, se um trecho rastreia uma operação que adiciona um item ao carrinho de compras de um usuário em um sistema de eCommerce, é possível obter o ID do usuário o ID do item a ser adicionado ao carrinho e o ID do carrinho.
Você pode adicionar atributos aos trecho durante ou após a criação do trecho. Prefira adicionar atributos na criação do trecho para disponibilizar os atributos para a amostragem do SDK. Se precisar adicionar um valor após a criação do trecho, atualize o trecho com o valor.
Os atributos têm as seguintes regras que é implementada por cada SDK:
Além disso, existem atributos semânticos, que são convenções de nomenclatura conhecidas para metadados que estão tipicamente presentes em operações comuns. É útil usar a nomenclatura de atributos semânticos sempre que possível para que tipos comuns de metadados sejam padronizados entre sistemas.
Um evento de trecho pode ser considerado como uma mensagem de log estruturada (ou anotação) em um trecho, tipicamente usada para apresentar um ponto significativo e único no tempo durante a duração do trecho.
Por exemplo, considere dois cenários em um navegador web:
Um trecho é mais adequado para o primeiro cenário, pois é uma operação que tem início e fim.
Um evento de trecho é mais adequado para rastrear o segundo cenário porque representa um ponto relevante e único na solicitação.
Como eventos de trecho também contêm atributos, a questão de quando usar eventos em vez de atributos nem sempre tem uma resposta óbvia. Para confirmar sua decisão, verifique se uma data e hora específicas são relevantes para você.
Por exemplo, quando você está rastreando uma operação com um trecho e a mesma é finalizada, você pode querer adicionar dados da operação à sua telemetria.
Os links existem para que você possa associar um trecho a um ou mais trechos, resultando em uma relação causal. Por exemplo, imagine que temos um sistema distribuído onde algumas operações são rastreadas por um rastro.
Em resposta a algumas dessas ações, uma operação adicional é enfileirada para ser executada, mas sua execução é assíncrona. Podemos rastrear essa operação seguinte através de um rastro.
Gostaríamos de associar o rastro das operações subsequentes ao primeiro rastro, mas não podemos prever quando as operações subsequentes começarão. Precisamos associar os dois rastros, então utilizaremos um link de trecho.
Você pode vincular o último trecho do primeiro rastro ao primeiro trecho do segundo rastro. Agora, eles estão causalmente associados entre si.
Os links são opcionais, mas servem como uma boa maneira de associar trechos de rastro uns aos outros.
Cada trecho tem um estado. Os três valores possíveis são:
Unset
Error
OK
O valor padrão é Unset
. Um estado de trecho Unset
significa que a operação
rastreada foi concluída com sucesso, sem erro.
Quando o estado de um trecho é Error
, isso significa que algum erro ocorreu na
operação rastreada. Por exemplo, isso pode ser devido a um erro de HTTP 500 em
um servidor que está lidando com uma solicitação.
Quando o estado de um trecho é OK
, isso significa que o trecho foi
expressamente marcado como livre de erros pelo desenvolvedor. Apesar de parecer
contraditório, não é necessário definir o estado de um trecho como OK
quando
se sabe que foi concluído sem erros, pois já está implícito em Unset
. O estado
de OK
representa uma “decisão final” clara sobre o estado de um trecho que foi
explicitamente definido por um usuário. Isso é útil em qualquer situação em que
um desenvolvedor deseje que não haja outra interpretação de um trecho além de
“bem-sucedido”.
Para reiterar: Unset
representa um trecho que foi concluído sem erro. OK
representa quando um desenvolvedor marca explicitamente um trecho como
bem-sucedido. Na maioria dos casos, não é necessário marcar explicitamente um
trecho como OK.
Quando um trecho é criado, ele pode ser do tipo: Client
, Server
, Internal
,
Producer
ou Consumer
. Esse tipo de trecho indica ao backend de rastreamento
como o rastro deve ser montado. De acordo com a especificação do OpenTelemetry,
o trecho pai de um servidor geralmente é um trecho de cliente remoto, e o trecho
filho de um cliente geralmente é um trecho de servidor. Da mesma forma, o trecho
pai de um consumidor é sempre um fornecedor, e o trecho filho de um fornecedor é
sempre um consumidor. Se o tipo de trecho não for especificado, ele será
assumido como interno.
Para mais informações sobre o tipo de Trecho, consulte SpanKind.
Um trecho de client representa uma chamada remota síncrona de saída, como uma
solicitação HTTP ou uma chamada de banco de dados. Observe que, neste contexto,
“síncrono” não se refere a operações async/await
, mas sim ao fato de que a
chamada não é enfileirada para processamento posterior.
Um trecho de servidor representa uma chamada remota síncrona de entrada, como uma solicitação HTTP de entrada ou uma chamada de procedimento remoto.
Trechos internos representam operações que não atravessam uma fronteira de processo. Coisas como instrumentar uma chamada de função ou um Express middleware podem usar trechos internos.
Trechos de fornecedor representam a criação de um trabalho que pode ser processado de forma assíncrona mais tarde. Pode ser uma tarefa remota, como uma adição em uma fila de tarefas, ou uma tarefa local processada por um ouvinte de eventos.
Trechos de consumidor representam o processamento de um trabalho criado por um produtor e podem começar muito tempo depois que o trecho de produtor já terminou.
Para mais informações, consulte especificação de rastros.
Was this page helpful?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!