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étrica | Tipo | Atributos |
|---|---|---|
http.server.request.duration | histograma, segundos | http.request.method, http.route, http.response.status_code |
ronne.db.query.duration | histograma, segundos | db.system.name, db.operation.name |
ronne.sign_ins | contador | outcome (success, failure, rate_limited) |
ronne.tokens.exchanged | contador | outcome (success, failure, rate_limited) |
ronne.releases | contador | |
ronne.feed.builds | contador | tool, cached |
ronne.feed.build.duration | histograma, segundos | tool |
ronne.job.duration | histograma, segundos | job, result (ok, failed) |
ronne.drafts.uploaded | contador | outcome (accepted, refused) |
ronne.rate_limited | contador | limit (sign_in, upload, usage, token_exchange) |
ronne.health | medidor, 1 ou 0 | check (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.