Pular para o conteúdo
Documentação: Monitoramento

Monitoramento

Os traces e as métricas que uma instância pode enviar a um coletor.

Descreve o Ronne AI Marketplace 0.4.0. Traduzida do inglês.

Monitoramento

O endpoint de saúde: GET /api/health responde 200 quando o Ronne pode atender, com cada verificação:

{"status":"ok","checks":{"database":"ok","storage":"ok"}}

e 503 quando não pode, no formato de erro da API: setup_required antes do setup, database_unavailable quando o banco não responde em 3 segundos, storage_unavailable quando a pasta de armazenamento não aceita escrita (o details.checks diz qual). A verificação de saúde do Docker, os serviços e os scripts de instalação esperam por ele, e um balanceador de carga também pode. Ele não diz mais nada (nem versão, nem caminho, nem tempo): é público. O motivo de uma falha fica no log (db.unavailable, storage.unavailable).

Métricas e traces vão para um coletor OpenTelemetry que você roda, por OTLP/HTTP. Ficam desligados até você definir o endereço dele: então, e só então, o Ronne carrega o OpenTelemetry. Defina-o no arquivo de configurações ou no ambiente (com Docker, no arquivo .env ao lado do compose.yaml, depois docker compose up -d), e reinicie o Ronne:

OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
OTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer%20…   # optional, the collector's
OTEL_SERVICE_NAME=ronne-marketplace                  # optional; this is the default
OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production

As variáveis OTEL_* padrão do OpenTelemetry funcionam como ele documenta: o endpoint próprio de um sinal (OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, …_METRICS_ENDPOINT), o amostrador (OTEL_TRACES_SAMPLER), o intervalo de exportação (OTEL_METRIC_EXPORT_INTERVAL, 60 s por padrão), e OTEL_EXPORTER_OTLP_PROTOCOL=http/json para enviar os traces em JSON em vez de protobuf (as métricas vão sempre em JSON). OTEL_SDK_DISABLED=true desliga mesmo com um endereço definido. O NEXT_OTEL_VERBOSE do próprio Next.js é desligado: seus spans a mais levariam os caminhos preenchidos, com nomes privados. Um coletor fora do ar ou lento nunca deixa uma requisição mais lenta: as exportações são tentadas de novo em segundo plano e depois descartadas, com no máximo uma linha telemetry.export_failed por minuto.

Um coletor que os recebe, guarda os traces no próprio log e oferece as métricas ao Prometheus em :8889/metrics (otel-collector.yaml):

receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318
processors:
  batch: {}
exporters:
  # Metrics for Prometheus to scrape, at http://<collector>:8889/metrics.
  prometheus:
    endpoint: 0.0.0.0:8889
  # Traces to the collector's own log: replace with your tracing backend's exporter.
  debug:
    verbosity: basic
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [debug]
    metrics:
      receivers: [otlp]
      processors: [batch]
      exporters: [prometheus]
docker run -p 4318:4318 -p 8889:8889 \
  -v ./otel-collector.yaml:/etc/otelcol-contrib/config.yaml:ro \
  ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.162.0

As métricas, cada uma só com estes atributos:

MétricaTipoAtributos
http.server.request.durationhistograma, segundoshttp.request.method, http.route, http.response.status_code
ronne.db.query.durationhistograma, segundosdb.system.name, db.operation.name
ronne.sign_inscontadoroutcome (success, failure, rate_limited)
ronne.tokens.exchangedcontadoroutcome (success, failure, rate_limited)
ronne.releasescontador
ronne.feed.buildscontadortool, cached
ronne.feed.build.durationhistograma, segundostool
ronne.job.durationhistograma, segundosjob, result (ok, failed)
ronne.drafts.uploadedcontadoroutcome (accepted, refused)
ronne.rate_limitedcontadorlimit (sign_in, upload, usage, token_exchange)
ronne.healthmedidor, 1 ou 0check (database, storage)

Os traces: os spans do próprio Next.js para cada requisição, com o nome do padrão da rota; um span para cada consulta ao banco, com o SQL e seus marcadores, nunca os valores; storage.put e storage.get com a contagem de bytes; e ronne.release, ronne.feed.build e ronne.draft.upload. O span de uma rota da API traz ronne.request_id, o X-Request-Id da resposta.

Nunca enviado: ids de usuários, e-mails, endereços IP de pessoas, user agents, tokens, os valores de uma consulta, nem os nomes de itens, escopos e espaços de trabalho. O caminho e a URL de uma requisição não são enviados (o caminho da página de um item tem o nome dele), nem a mensagem de um erro. Os spans levam só os atributos que o Ronne lista; qualquer outro que uma biblioteca acrescente é descartado. Cada requisição é o seu próprio trace: o traceparent, o tracestate e o baggage de quem chama são ignorados, então um trace nunca se junta ao de um proxy ou de um cliente. O recurso diz service.name, service.version, deployment.* e o que você definir em OTEL_RESOURCE_ATTRIBUTES. Nada vai a lugar nenhum além do seu coletor.

Alertas que valem a pena: a verificação de saúde falhando (ronne.health em 0, ou o 503 do endpoint); um aumento de respostas 5xx (http.server.request.duration por http.response.status_code); um aumento de logins falhos ou limitados (ronne.sign_ins, ronne.rate_limited); consultas lentas (ronne.db.query.duration).

Logs e traces juntos: com o rastreamento ligado, cada linha de log escrita durante uma requisição traz traceId e spanId (Logs), então uma linha leva ao trace dela, e o ronne.request_id de um trace às linhas.