Pular para o conteúdo

Telemetria

O runner é instrumentado com OpenTelemetry, e a telemetria é no-op por default. Desenvolvimento, teste e CI não precisam de collector nenhum.

Esta é a pegadinha: a telemetria só fica ativa quando três condições valem ao mesmo tempo.

enabled = ROOTPILOT_OTEL_ENABLED && !OTEL_SDK_DISABLED && exporter !== 'none'

E o exporter é none por default. Ou seja:

Terminal window
# NÃO basta: o exporter continua `none` e nada é emitido
ROOTPILOT_OTEL_ENABLED=true
# funciona
ROOTPILOT_OTEL_ENABLED=true
ROOTPILOT_OTEL_EXPORTER=otlp
OTEL_EXPORTER_OTLP_ENDPOINT=https://otel.example.com
Variável Default Notas
ROOTPILOT_OTEL_ENABLED false Master switch. Aceita true ou 1.
ROOTPILOT_OTEL_EXPORTER none otlp, console ou none. Precisa sair de none.
OTEL_SDK_DISABLED false O kill-switch padrão do OTel. true vence o master switch.
OTEL_EXPORTER_OTLP_ENDPOINT nenhum URL do collector.
OTEL_EXPORTER_OTLP_HEADERS nenhum Headers, para collector autenticado.
OTEL_EXPORTER_OTLP_PROTOCOL http/protobuf
OTEL_SERVICE_NAME rootpilot-service
OTEL_SERVICE_VERSION nenhum Ausente ⇒ o atributo service.version simplesmente não é emitido.
OTEL_TRACES_SAMPLER_ARG 1 Razão de amostragem, entre 0 e 1.

O console é útil para verificar rapidamente se a instrumentação está viva sem subir collector.

Por preload, e não por chamada em código:

node --import @rootpilot/otel/register apps/runner/dist/index.js

O preload roda antes de o grafo de módulos da aplicação carregar, o que é o que permite à auto-instrumentação do OTel aplicar patch em http e ws primeiro. O CMD da imagem do runner já é exatamente esse comando, então você não precisa fazer nada além de setar as variáveis.

É também por isso que nome e versão do serviço vêm do ambiente: nesse ponto não existe build que os inline nem chamador em código para passá-los.

Span Quando
rootpilot.handle_invoke_batch Recebimento de um lote de invocações, sob o contexto remoto extraído do metadata da mensagem.
rootpilot.run_op Cada operação, com atributos de MCP e da operação.

O contexto remoto é o detalhe que importa: ele faz o trace ser distribuído, unindo o span do control-plane ao do runner num único trace. Também há métricas por tenant.

O logger correlaciona trace_id e span_id nas linhas de log. Com a telemetria ligada, dá para sair de um span no seu backend direto para as linhas de log daquela operação.

A telemetria é drenada no SIGTERM, junto com o drain do runner. Vale lembrar do terminationGracePeriodSeconds: se o SIGKILL chegar antes, os últimos spans se perdem.

Mesmo com a telemetria desligada, o runner reporta estado ao control-plane pelo handshake:

  • accounts[]: o contexto de nuvem derivado no boot.
  • ConnectorStatus{served, health}: o que cada connector está servindo e como passou no self-check de credencial.
  • ConnectorStatus.ops: quais operações aquele connector serve.

O último existe porque uma lista plana de operações servidas não diz de quem elas são, e sem o dono, o control-plane não consegue descontar as operações de um connector com credencial quebrada.