obs-normalizer
Background service que normaliza eventos de GlitchTip e Alertmanager para um schema canônico ObsEvent e publica no exchange RabbitMQ obs.events.
obs-normalizer
Background service em Node.js que recebe webhooks de observabilidade (GlitchTip, Alertmanager), converte cada payload para o schema canônico ObsEvent, enriquece com sumário de trace (via Tempo) quando aplicável e publica no exchange RabbitMQ obs.events. Não possui UI — apenas endpoints HTTP de ingestão, probes de saúde e métricas Prometheus.
Subprojeto do monorepo simplafy-admin, localizado em apps/obs-normalizer. Runtime Fastify, schema compartilhado pelo pacote @simplafy-admin/obs-schema.
O que faz
- Recebe webhooks de fontes de observabilidade em endpoints HTTP autenticados.
- Converte cada payload bruto para o schema canônico
ObsEventusando receivers dedicados (parseGlitchTipWebhook,parseAlertmanagerWebhook). - Quando o evento contém
correlation.trace_id, busca umtrace_summaryem Tempo antes de publicar. - Valida o
ObsEventresultante via Zod e publica no exchange RabbitMQ configurado. - Expõe Swagger UI da API em
/docs, spec OpenAPI em/openapi.jsone métricas Prometheus em/metrics.
O serviço só atua como ingestor + publisher: o consumo dos eventos normalizados é responsabilidade de outros workers conectados ao mesmo exchange.
Inputs (webhooks)
Dois endpoints POST, cada um com seu próprio esquema de autenticação.
POST /webhooks/glitchtip
Recebe payloads do GlitchTip. A autenticação aceita o segredo por header x-webhook-secret ou query param ?secret=... (o GlitchTip só permite passar o segredo via URL).
curl -X POST https://obs-normalizer/webhooks/glitchtip?secret=$GLITCHTIP_WEBHOOK_SECRET \
-H "Content-Type: application/json" \
-d @glitchtip-payload.jsonRespostas:
| Código | Significado |
|---|---|
202 | Aceito; retorna { event_id } do ObsEvent publicado. |
400 | invalid_payload — falha ao parsear o webhook. |
401 | invalid_secret. |
500 | internal_validation_failure — ObsEvent produzido violou o schema. |
503 | publish_failed — falha ao publicar no RabbitMQ. |
Quando o evento normalizado contém correlation.trace_id, o serviço chama Tempo (TEMPO_URL) para anexar um trace_summary antes de publicar.
POST /webhooks/alertmanager
Recebe payloads no formato Alertmanager webhook v4. Autenticação via HTTP Basic (ALERTMANAGER_USERNAME / ALERTMANAGER_PASSWORD).
curl -X POST https://obs-normalizer/webhooks/alertmanager \
-u "$ALERTMANAGER_USERNAME:$ALERTMANAGER_PASSWORD" \
-H "Content-Type: application/json" \
-d @alertmanager-payload.jsonUm payload Alertmanager pode gerar múltiplos ObsEvents. O serviço valida todos antes de publicar qualquer um — assim retries não causam publicação parcial.
Respostas:
| Código | Significado |
|---|---|
202 | Aceito; retorna { count } com o número de eventos publicados. |
400 | invalid_payload. |
401 | unauthorized. |
500 | internal_validation_failure. |
503 | publish_failed. |
Erros de publicação retornam 503, sinalizando ao remetente que pode/deve retentar. A validação do schema acontece antes da publicação para evitar mensagens malformadas no exchange.
Outputs (queue)
Os eventos normalizados são publicados no RabbitMQ, no exchange definido por RABBITMQ_EXCHANGE (default obs.events) dentro do vhost RABBITMQ_VHOST (default /obs). A publicação é feita por um ResilientPublisher configurado com a HTTP API do RabbitMQ:
new ResilientPublisher({
publishOpts: {
apiUrl: config.RABBITMQ_API_URL,
user: config.RABBITMQ_USER,
password: config.RABBITMQ_PASSWORD,
vhost: config.RABBITMQ_VHOST,
exchange: config.RABBITMQ_EXCHANGE,
},
})Cada mensagem segue o schema ObsEvent exportado por @simplafy-admin/obs-schema. O fluxo conceitual é:
webhook bruto → receiver dedicado → ObsEvent → (opcional) enrich com trace_summary → Zod validate → publishConsumidores ligam suas filas a este exchange para reagir a eventos canônicos sem precisar conhecer o formato de cada fonte original.
Arquitetura em 1 parágrafo
O serviço é um app Fastify single-process. No bootstrap, instrument.js inicializa OpenTelemetry antes de qualquer outro import, e prom-client coleta métricas default do Node sob o prefixo obs_normalizer_. buildServer registra Swagger/Swagger UI, os health routes (/healthz, /readyz), os webhook routes (/webhooks/glitchtip, /webhooks/alertmanager) e expõe /openapi.json e /metrics. As rotas de webhook recebem um Publisher e um TraceFetcher por injeção de dependência: por padrão usam o ResilientPublisher (RabbitMQ HTTP API) e getTraceSummary (Tempo). Quando executado diretamente, o processo escuta em 0.0.0.0:PORT (default 3002).
Operação (health, metrics)
Health probes
GET /healthz retorna sempre 200 enquanto o processo está vivo, com a versão da app.
{ "status": "ok", "version": "dev" }Apropriado para liveness probe do Kubernetes.
GET /readyz valida em paralelo se Tempo e RabbitMQ estão alcançáveis (timeout de 1s cada):
- Tempo:
GET {TEMPO_URL}/ready - RabbitMQ:
GET {RABBITMQ_API_URL}/aliveness-test/{vhost}com Basic auth
{ "status": "ok", "tempo": true, "rabbitmq": true }Se qualquer dependência falhar, o status passa a degraded (o endpoint ainda responde 200, mas indica a dependência problemática). Use no readiness probe combinado com a inspeção dos campos.
Métricas
GET /metrics expõe as métricas no formato Prometheus, incluindo as default do Node (process_*, nodejs_*) prefixadas com obs_normalizer_.
curl http://obs-normalizer:3002/metricsDocumentação interativa
- Swagger UI:
/docs - OpenAPI JSON:
/openapi.json
Configuração
Variáveis lidas via Zod (src/config.ts); valores sem default são obrigatórios.
| Variável | Default | Observação |
|---|---|---|
PORT | 3002 | Porta HTTP do Fastify. |
NODE_ENV | development | development | staging | production | test. |
LOG_LEVEL | info | debug | info | warn | error. |
TEMPO_URL | http://tempo.monitoring.svc.cluster.local:3200 | Base URL do Tempo para enrichment. |
TEMPO_TIMEOUT_MS | 2000 | Timeout da busca de trace summary. |
RABBITMQ_API_URL | http://localhost:15672/api | HTTP API do RabbitMQ. |
RABBITMQ_USER | obs-normalizer | Usuário do publisher. |
RABBITMQ_PASSWORD | obrigatório | Senha do publisher. |
RABBITMQ_VHOST | /obs | Vhost. |
RABBITMQ_EXCHANGE | obs.events | Exchange de destino. |
GLITCHTIP_WEBHOOK_SECRET | obrigatório | Segredo aceito em x-webhook-secret ou ?secret=. |
ALERTMANAGER_USERNAME | obs-alerts | Basic auth. |
ALERTMANAGER_PASSWORD | obrigatório | Basic auth. |
GLITCHTIP_DSN | — | DSN opcional para auto-instrumentar o próprio serviço. |
OTEL_BASIC_AUTH | — | Auth opcional para o exporter OTel. |
APP_VERSION | dev | Exposto em /healthz. |
Segredos de produção (RABBITMQ_PASSWORD, GLITCHTIP_WEBHOOK_SECRET, ALERTMANAGER_PASSWORD) são gerenciados no Infisical. Consulte a skill infisical para descobrir o path exato.