Arquitetura
O conteúdo desta página pode estar desatualizado e alguns links podem ser
inválidos.
Uma versão mais recente desta página existe em
Inglês. Para visualizar as alterações na página em inglês desde a última atualização: visite
GitHub compare 2871fe3c..714d6cc9
e procure por Mais informações ...
content/en/docs/collector/architecture.md.
O OpenTelemetry Collector é um arquivo executável que pode receber telemetria, processá-la e exportá-la para múltiplos destinos, como backends de observabilidade.
O Collector suporta vários protocolos populares de código aberto para receber e enviar dados de telemetria, e oferece uma arquitetura extensível para adicionar mais protocolos.
O recebimento, processamento e exportação de dados são feitos usando pipelines. Você pode configurar o Collector para ter um ou mais pipelines.
Cada pipeline inclui:
- Um conjunto de receivers que coletam os dados.
- Uma série de processors opcionais que recebem os dados dos receivers e os processam.
- Um conjunto de exporters que recebem os dados dos processors e os enviam para fora do Collector.
O mesmo receiver pode ser incluído em múltiplos pipelines, e múltiplos pipelines podem incluir o mesmo exporter.
Pipelines
Um pipeline define um caminho que os dados seguem no Collector: desde a recepção, passando pelo processamento (ou modificação), até a exportação.
Os pipelines podem operar em três tipos de dados de telemetria: rastros,
métricas e logs. O tipo de dado é uma propriedade do pipeline definida por sua
configuração. Os receivers, processors e exporters utilizados em um
pipeline devem suportar o tipo de dado específico, caso contrário a exceção
pipeline.ErrSignalNotSupported é reportada quando a configuração é carregada.
O diagrama a seguir representa um pipeline típico:
--- title: Pipeline --- flowchart LR R1(Receiver 1) --> P1[Processor 1] R2(Receiver 2) --> P1 RM(...) ~~~ P1 RN(Receiver N) --> P1 P1 --> P2[Processor 2] P2 --> PM[...] PM --> PN[Processor N] PN --> FO((distribuidor)) FO --> E1[[Exporter 1]] FO --> E2[[Exporter 2]] FO ~~~ EM[[...]] FO --> EN[[Exporter N]]
Os pipelines podem ter um ou mais receivers. Os dados de todos os
receivers são enviados para o primeiro processor, que processa os dados e os
repassa para o próximo processor. Um processor também pode descartar os
dados caso esteja realizando amostragem ou filtragem. Esse processo continua até
que o último processor do pipeline envie os dados para os exporters. Cada
exporter recebe uma cópia de cada elemento de dado. O último processor usa
um fanoutconsumer para enviar os dados para múltiplos exporters.
O pipeline é construído durante a inicialização do Collector com base na definição do pipeline na configuração.
Uma configuração típica de pipeline se parece com isso:
service:
pipelines: # seção que pode conter várias subseções, uma por tubulação
traces: # tipo do _pipeline_
receivers: [otlp, zipkin]
processors: [memory_limiter]
exporters: [otlp, zipkin]
O exemplo anterior define um pipeline para o tipo rastro de dado de telemetria, que inclui dois receivers, um processor e dois exporters. O receiver com dois receivers, um processor e dois exporters.
Receivers
Os receivers normalmente escutam em uma porta de rede e recebem dados de
telemetria. Eles também podem obter dados ativamente, como scrapers.
Normalmente um receiver é configurado para enviar os dados recebidos para um
pipeline. No entanto, também é possível configurar o mesmo receiver para
enviar os mesmos dados recebidos para múltiplos pipelines. Isso pode ser feito
listando o mesmo receiver na chave receivers de vários pipelines:
receivers:
otlp:
protocols:
grpc:
endpoint: localhost:4317
service:
pipelines:
traces: # o _pipeline_ do tipo "rastro (_traces_)"
receivers: [otlp]
processors: [memory_limiter]
exporters: [otlp]
traces/2: # outro _pipeline_ do tipo "rastro (_traces_)"
receivers: [otlp]
processors: [transform]
exporters: [otlp]
No exemplo acima, o receiver otlp enviará os mesmos dados para o pipeline
traces e para o pipeline traces/2.
A configuração usa nomes de chaves compostas na forma
tipo[/nome].
Quando o Collector carrega essa configuração, o resultado se parece com este diagrama (parte dos processors e exporters foram omitidos por brevidade):
flowchart LR
R1("`#quot;opentelemetry-collector#quot; Receiver`") --> FO((distribuidor))
FO -->|Pipeline 'traces'| P1["`#quot;memory_limiter#quot; Processor`"]
FO -->|Pipeline 'traces/2'| P2["`#quot;transform#quot; Processor`"]
P1 ~~~ M1[...]
P2 ~~~ M2[...]Quando o mesmo receiver é referenciado em mais de um pipeline, o Collector cria apenas uma instância do receiver em tempo de execução, que envia os dados para um distribuidor. O distribuidor, por sua vez, envia os dados para o primeiro processor de cada pipeline. A propagação dos dados do receiver para o distribuidor e depois para os processors é realizada por meio de uma chamada de função síncrona. Isso significa que, se um processor bloquear a chamada, os outros pipelines associados a esse receiver serão bloqueados de receber os mesmos dados, e o próprio receiver para de processar e encaminhar os dados recebidos.
Exporters
Os exporters normalmente encaminham os dados que recebem para um destino na
rede, mas também podem enviar os dados para outros lugares. Por exemplo, o
exporter debug escreve os dados de telemetria no destino de log.
A configuração permite múltiplos exporters do mesmo tipo, no mesmo pipeline.
Por exemplo, você pode ter dois exporters otlp definidos, cada um enviando
para um endpoint OTLP diferente:
exporters:
otlp/1:
endpoint: example.com:4317
otlp/2:
endpoint: localhost:14317
Um exporter normalmente recebe dados de um pipeline. No entanto, você pode configurar múltiplos pipelines para enviar dados para o mesmo exporter:
exporters:
otlp:
protocols:
grpc:
endpoint: localhost:14250
service:
pipelines:
traces: # o _pipeline_ do tipo "rastro (_traces_)"
receivers: [zipkin]
processors: [memory_limiter]
exporters: [otlp]
traces/2: # outro _pipeline_ do tipo "rastro (_traces_)"
receivers: [otlp]
processors: [transform]
exporters: [otlp]
No exemplo acima, o exporter otlp recebe dados do pipeline traces e do
pipeline traces/2. Quando o Collector carrega essa configuração, o resultado
se parece com este diagrama (parte dos processors e receivers foram omitidos
por brevidade):
flowchart LR M1[...] ~~~ P1["`#quot;memory_limiter#quot; Processor`"] M2[...] ~~~ P2["`#quot;transform#quot; Processor`"] P1 -->|Pipeline 'traces'|E1[["`#quot;otlp#quot; Exporter`"]] P2 -->|Pipeline 'traces/2'|E1
Processors
Um pipeline pode conter processors conectados em sequência. O primeiro processor recebe os dados de um ou mais receivers configurados para o pipeline, e o último processor envia os dados para um ou mais exporters configurados para o pipeline. Todos os processors entre o primeiro e o último recebem os dados de apenas um processor anterior e enviam dados para apenas um processor sucessor.
Os processors podem transformar os dados antes de encaminhá-los, como
adicionar ou remover atributos de trecho. Podem também descartar os dados ao
decidir não encaminhá-los (por exemplo, o processor probabilisticsampler).
Ou podem gerar novos dados.
O mesmo nome do processor pode ser referenciado na chave processors de
múltiplos pipelines. Nesse caso, a mesma configuração é usada para cada um
desses processors, mas cada pipeline sempre obtém sua própria instância do
processor. Cada um desses processors tem seu próprio estado, e os
processors nunca são compartilhados entre pipelines. Por exemplo, se o
processor transform for usado em vários pipelines, cada pipeline terá
seu próprio processor transform, mas cada processor transform é configurado
exatamente da mesma forma se referenciarem a mesma chave na configuração. Veja a
seguinte configuração:
processors:
transform:
error_mode: ignore
trace_statements:
- set(resource.attributes["namespace"],
resource.attributes["k8s.namespace.name"])
- delete_key(resource.attributes, "k8s.namespace.name")
service:
pipelines:
traces: # o _pipeline_ do tipo "rastro (_traces_)"
receivers: [zipkin]
processors: [transform]
exporters: [otlp]
traces/2: # outro _pipeline_ do tipo "rastro (_traces_)"
receivers: [otlp]
processors: [transform]
exporters: [otlp]
Quando o Collector carrega essa configuração, o resultado se parece com este diagrama:
---
title: Pipeline "traces"
---
flowchart LR
R1("`zipkin Receiver`") --> P1["`#quot;transform#quot; Processor`"]
P1 --> E1[["`#quot;otlp#quot; Exporter`"]]---
title: Pipeline "traces/2"
---
flowchart LR
R1("`otlp Receiver`") --> P1["`#quot;transform#quot; Processor`"]
P1 --> E1[["`#quot;otlp#quot; Exporter`"]]Observe que cada processor transform é uma instância independente, embora
sejam configurados da mesma forma com um send_batch_size de 10000.
O mesmo nome do processor não deve ser referenciado mais de uma vez na chave
processorsde um único pipeline.
Executando como agente
Em uma VM/container típica, as aplicações do usuário estão sendo executadas em alguns processos/pods com uma biblioteca OpenTelemetry. Anteriormente, a biblioteca fazia todo o registro, coleta, amostragem e agregação de rastros, métricas e logs e, em seguida, exportava os dados para outros backends de armazenamento persistente através dos exporters da biblioteca, ou os exibia em zpages locais. Esse padrão tem várias desvantagens, por exemplo:
- Para cada biblioteca OpenTelemetry, os exporters e zpages precisam ser reimplementados em linguagens nativas.
- Em algumas linguagens de programação (por exemplo, Ruby ou PHP), é difícil fazer a agregação de estatísticas em processo.
- Para habilitar a exportação de trechos, estatísticas ou métricas do OpenTelemetry, os usuários da aplicação precisam adicionar manualmente os exporters da biblioteca e reimplantar seus binários. Isso é especialmente difícil quando um incidente ocorreu e os usuários querem usar o OpenTelemetry para investigar o problema imediatamente.
- Os usuários da aplicação precisam assumir a responsabilidade de configurar e inicializar os exporters. Essas tarefas são suscetíveis a erros (por exemplo, configurar credenciais incorretas ou recursos monitorados), e os usuários podem relutar em “poluir” seu código com OpenTelemetry.
Para resolver os problemas acima, você pode executar o OpenTelemetry Collector como um agente. O agente é executado como um daemon na VM/container e pode ser implantado independentemente da biblioteca. Uma vez implantado e em execução, o agente deve ser capaz de recuperar rastros, métricas e logs da biblioteca e exportá-los para outros backends. Também podemos dar ao agente a capacidade de enviar configurações (como a probabilidade de amostragem) para a biblioteca. Para as linguagens que não conseguem fazer a agregação de estatísticas em processo, elas podem enviar medições brutas e deixar o agente fazer a agregação.
flowchart LR
subgraph S1 ["#nbsp;"]
subgraph S2 ["#nbsp;"]
subgraph VM [VM]
PR["Processo [Biblioteca]"] -->|Amostra trechos, métricas| AB[Agente Binário]
AB -->|Enviar configurações| PR
end
subgraph K8s-pod [K8s Pod]
AC["`Contêiner de aplicativo [Biblioteca]`"] --> AS[Agente Binário]
AS --> AC
end
subgraph K8s-node [K8s Node]
subgraph Pod1 [Pod]
APP1[App] ~~~ APP2[App]
end
subgraph Pod2 [Pod]
APP3[App] ~~~ APP4[App]
end
subgraph Pod3 [Pod]
APP5[App] ~~~ APP6[App]
end
subgraph AD [Agente Daemonset]
end
APP1 --> AD
APP2 --> AD
APP4 --> AD
APP6 --> AD
end
end
subgraph Backends ["#nbsp;"]
AB --> BE[Backend]
AS --> PRM[Prometheus Backend]
AS --> JA[Jaeger Backend]
AD --> JA
end
end
class S2 noLines;
class VM,K8s-pod,K8s-node,Pod1,Pod2,Pod3,Backends withLines;
class PR,AB,AC,AS,APP1,APP2,APP3,APP4,APP5,APP6,AD,BE,PRM,JA nodeStyle
classDef noLines stroke:#fff,stroke-width:4px,color:#000000;
classDef withLines fill:#fff,stroke:#4f62ad,color:#000000;
classDef nodeStyle fill:#e3e8fc,stroke:#4f62ad,color:#000000;Para desenvolvedores e mantenedores de outras bibliotecas: adicionando receivers específicos, você pode configurar um agente para aceitar rastros, métricas e logs de outras bibliotecas de rastreamento/monitoramento, como Zipkin, Prometheus, etc. Consulte Receivers para mais detalhes.
Executando como gateway
O OpenTelemetry Collector pode ser executado como uma instância de gateway e receber trechos e métricas exportados por um ou mais agentes ou bibliotecas, ou por tarefas/agentes que emitem em um dos protocolos suportados. O Collector é configurado para enviar dados para os exporter(s) configurados. A figura a seguir resume a arquitetura de implantação:
flowchart LR
subgraph S1 ["#nbsp;"]
subgraph S2 ["#nbsp;"]
subgraph S3 ["#nbsp;"]
subgraph VM [VM]
PR["Processo [Biblioteca]"]
end
subgraph K8s-pod [K8s Pod]
AC["`Contêiner de aplicativo [Biblioteca]`"]
end
subgraph K8s-node [K8s Node]
subgraph Pod1 [Pod]
APP1[App] ~~~ APP2[App]
end
subgraph Pod2 [Pod]
APP3[App] ~~~ APP4[App]
end
subgraph Pod3 [Pod]
APP5[App] ~~~ APP6[App]
end
subgraph AD [Agente Daemonset]
end
APP1 --> AD
APP2 --> AD
APP4 --> AD
APP6 --> AD
end
end
subgraph S4 ["#nbsp;"]
PR --> OTEL["`Serviço OpenTelemetry Collector`"]
AC --> OTEL
AD --> OTEL
OTEL ---> BE[Backend X]
end
end
subgraph S5 ["#nbsp;"]
subgraph S6 ["#nbsp;"]
JA[Jaeger Backend]
end
subgraph S7 ["#nbsp;"]
PRM[Prometheus Backend]
end
end
JA ~~~ PRM
OTEL --> JA
OTEL --> PRM
end
class S1,S3,S4,S5,S6,S7,S8 noLines;
class VM,K8s-pod,K8s-node,Pod1,Pod2,Pod3 withLines;
class S2 lightLines
class PR,AC,APP1,APP2,APP3,APP4,APP5,APP6,AD,OTEL,BE,JA,PRM nodeStyle
classDef noLines stroke-width:0px,color:#000000;
classDef withLines fill:#fff,stroke:#4f62ad,color:#000000;
classDef lightLines stroke:#acaeb0,color:#000000;
classDef nodeStyle fill:#e3e8fc,stroke:#4f62ad,color:#000000;O OpenTelemetry Collector também pode ser implantado em outras configurações, como receber dados de outros agentes ou clientes em um dos formatos suportados pelos seus receivers.
Feedback
Esta página foi útil?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!