simpla.fydocs
Obs Normalizer

Topologia de filas

Exchanges, routing keys, bindings e consumers downstream do obs-normalizer no RabbitMQ.

Topologia de filas

O obs-normalizer publica eventos normalizados em um único exchange do RabbitMQ via HTTP API. Esta página descreve a topologia (exchange, routing keys, bindings e consumers) e como ela interage com as configurações de runtime do serviço.

A publicação é feita pelo módulo src/publish/rabbitmq-http.ts, encapsulada por um ResilientPublisher (src/publish/resilient-publish.ts) que adiciona retry com backoff exponencial e circuit breaker.

O obs-normalizer não declara exchanges, filas ou bindings em runtime. Toda a topologia descrita abaixo é gerenciada externamente (provisionamento do broker). O serviço apenas publica em um exchange pré-existente e falha rápido se nenhuma binding casar com a routing key.

Exchanges

O serviço publica em um único exchange, configurado via variável de ambiente.

ConfiguraçãoVariávelDefault
URL da Management APIRABBITMQ_API_URLhttp://localhost:15672/api
Virtual hostRABBITMQ_VHOST/obs
ExchangeRABBITMQ_EXCHANGEobs.events
UsuárioRABBITMQ_USERobs-normalizer
SenhaRABBITMQ_PASSWORDobrigatório

A publicação usa a Management HTTP API do RabbitMQ no endpoint:

POST {RABBITMQ_API_URL}/exchanges/{vhostEncoded}/{RABBITMQ_EXCHANGE}/publish

Cada mensagem é enviada com delivery_mode: 2 (persistente), content_type: application/json, message_id igual ao event_id do evento canônico e timestamp derivado do timestamp do evento.

A resposta da Management API inclui o campo routed. Se vier false, o publisher lança erro indicando que nenhuma binding casou com a routing key. Isso significa que o evento não foi entregue a nenhuma fila — confira os bindings antes de criar novos event_type ou severity.

Routing keys

Cada evento é publicado com uma routing key composta a partir do schema canônico (@simplafy-admin/obs-schema):

{event_type}.{severity}.{source.service}

Os componentes vêm diretamente dos enums do schema:

  • event_type: issue.created, issue.regressed, issue.resolved, alert.fired, alert.resolved
  • severity: info, warning, error, critical
  • source.service: nome do serviço de origem (string livre, ex.: simplafy-hub, simplafy-saude)

O event_type já contém um ponto (por exemplo, issue.created), então a routing key final tem quatro segmentos separados por ponto. Padrões de binding como issue.*.*.simplafy-hub precisam considerar isso.

Exemplos:

issue.created.error.simplafy-hub
issue.regressed.critical.simplafy-saude
alert.fired.warning.simplafy-seguros
alert.resolved.info.simplafy-admin

Bindings

O obs-normalizer não cria bindings. As filas downstream definem suas próprias bindings contra obs.events usando padrões topic compatíveis com o formato acima.

Padrões típicos:

# Tudo de um serviço
*.*.*.simplafy-hub

# Apenas issues críticas/erro
issue.*.error.*
issue.*.critical.*

# Apenas alertas firing
alert.fired.*.*

# Tudo (espelho/auditoria)
#

O exchange obs.events deve ser do tipo topic para que routing keys com pontos funcionem como esperado. Se um operador trocar o tipo para direct ou fanout, a semântica de roteamento descrita aqui deixa de valer.

Consumers downstream

Os consumers ficam em serviços separados e não estão no código-fonte do obs-normalizer. O contrato observado pelo publisher é apenas:

  1. Existe pelo menos uma fila com binding que casa com a routing key gerada.
  2. As filas consomem mensagens JSON aderentes ao schema ObsEvent (@simplafy-admin/obs-schema).

O envelope JSON publicado segue o schema canônico (campos principais):

{
  "schema_version": "1.0",
  "event_id": "string",
  "event_type": "issue.created",
  "severity": "error",
  "timestamp": "2026-05-29T12:00:00Z",
  "source": {
    "system": "glitchtip",
    "project": "string",
    "service": "string",
    "environment": "string"
  },
  "correlation": {
    "trace_id": null,
    "span_id": null,
    "issue_id": null,
    "fingerprint": "string"
  },
  "payload": { "title": "...", "message": "...", "culprit": "...", "url": "", "release": "...", "user_affected_count": 0, "event_count": 0 },
  "trace_summary": null,
  "links": { "logs_query": "...", "traces_url": "...", "repository": "...", "commit": "...", "file_hint": null },
  "metadata": { "tags": {}, "custom": {} }
}

Qualquer consumer downstream (notificador de Slack/Telegram, gravador no banco, agente de incidentes) deve declarar sua própria fila com binding em obs.events e validar o payload contra ObsEvent antes de processar.

Para a versão canônica do schema ObsEvent, consulte o pacote @simplafy-admin/obs-schema no repositório.

Variável RABBITMQ_GLOBAL_ENABLED

A variável RABBITMQ_GLOBAL_ENABLED não faz parte do schema de configuração atual do obs-normalizer (src/config.ts). O serviço não expõe um kill-switch global para publicação via env var nessa revisão do código.

As variáveis de ambiente reconhecidas relacionadas ao RabbitMQ são exclusivamente:

  • RABBITMQ_API_URL
  • RABBITMQ_USER
  • RABBITMQ_PASSWORD
  • RABBITMQ_VHOST
  • RABBITMQ_EXCHANGE

Se você precisa pausar a publicação sem derrubar o serviço, há duas opções operacionais:

  • Apontar RABBITMQ_API_URL para um endpoint inativo — o circuit breaker do ResilientPublisher abre após 5 falhas consecutivas e permanece aberto por 30s, falhando rápido nas requisições subsequentes.
  • Remover ou desativar bindings no broker — o publisher passa a receber routed: false e a lançar erro por evento.

Nenhum dos dois é equivalente a um flag global limpo. Se um kill-switch dedicado for necessário, ele precisa ser adicionado ao schema de config.ts e ao caminho de publicação.

On this page