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ção | Variável | Default |
|---|---|---|
| URL da Management API | RABBITMQ_API_URL | http://localhost:15672/api |
| Virtual host | RABBITMQ_VHOST | /obs |
| Exchange | RABBITMQ_EXCHANGE | obs.events |
| Usuário | RABBITMQ_USER | obs-normalizer |
| Senha | RABBITMQ_PASSWORD | obrigatório |
A publicação usa a Management HTTP API do RabbitMQ no endpoint:
POST {RABBITMQ_API_URL}/exchanges/{vhostEncoded}/{RABBITMQ_EXCHANGE}/publishCada 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.resolvedseverity:info,warning,error,criticalsource.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-adminBindings
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:
- Existe pelo menos uma fila com binding que casa com a routing key gerada.
- 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_URLRABBITMQ_USERRABBITMQ_PASSWORDRABBITMQ_VHOSTRABBITMQ_EXCHANGE
Se você precisa pausar a publicação sem derrubar o serviço, há duas opções operacionais:
- Apontar
RABBITMQ_API_URLpara um endpoint inativo — o circuit breaker doResilientPublisherabre 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: falsee 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.