Observability API
O Sagaweaw expõe uma API REST completa para monitorar sagas, consultar métricas e gerenciar dead letters. Todos os endpoints exigem autenticação por token.
Segurança
Por padrão, todos os endpoints retornam 403 se o token não estiver configurado.
Configuração
sagaweaw:
observability:
enabled: true
token: ${SAGAWEAW_TOKEN} # obrigatório
Para desabilitar completamente a API:
sagaweaw:
observability:
enabled: false
Autenticação
Passe o token em qualquer um dos dois formatos:
# Bearer token (padrão)
Authorization: Bearer <token>
# Header alternativo
X-Sagaweaw-Token: <token>
Endpoints de Sagas
GET /api/sagas
Lista sagas com paginação e filtros opcionais.
Query params:
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
page | int | 0 | Página (0-indexed) |
size | int | 50 | Itens por página |
status | string | — | Filtrar por status (FAILED, COMPLETED, etc.) |
name | string | — | Busca por nome da saga (contains, case-insensitive) |
id | string | — | Busca por prefixo de ID da saga |
idempotencyKey | string | — | Busca exata por chave de idempotência |
from | ISO 8601 | — | Data inicial (2024-01-01T00:00:00Z) |
to | ISO 8601 | — | Data final |
Exemplos:
# Últimas 50 sagas
curl -H "Authorization: Bearer $TOKEN" /api/sagas
# Sagas que falharam hoje
curl -H "Authorization: Bearer $TOKEN" \
"/api/sagas?status=FAILED&from=2024-01-15T00:00:00Z"
# Buscar por nome (contains)
curl -H "Authorization: Bearer $TOKEN" \
"/api/sagas?name=pix"
# Buscar por prefixo de ID
curl -H "Authorization: Bearer $TOKEN" \
"/api/sagas?id=01934abc"
# Buscar por idempotency key
curl -H "Authorization: Bearer $TOKEN" \
"/api/sagas?idempotencyKey=order-abc-123"
# Paginação
curl -H "Authorization: Bearer $TOKEN" \
"/api/sagas?page=2&size=25"
Resposta — array de SagaInstance:
[
{
"id": "01934...",
"name": "pix-payment",
"status": { "type": "COMPLETED", "completedAt": "2024-01-15T10:05:00Z", "durationMs": 312 },
"contextJson": "{\"transactionId\":\"...\"}",
"steps": [
{
"name": "validate-dict",
"order": 0,
"status": { "type": "COMPLETED" },
"attempt": 1,
"maxAttempts": 3,
"durationMs": 45,
"executedAt": "2024-01-15T10:04:59Z",
"completedAt": "2024-01-15T10:05:00Z"
}
],
"createdAt": "2024-01-15T10:04:58Z",
"updatedAt": "2024-01-15T10:05:00Z",
"version": 4
}
]
GET /api/sagas/{id}
Retorna uma saga específica pelo ID.
curl -H "Authorization: Bearer $TOKEN" /api/sagas/01934abc-...
- 200 — saga encontrada
- 404 — saga não existe
GET /api/sagas/{id}/events
Retorna o log de auditoria imutável da saga — todas as transições de estado em ordem cronológica.
curl -H "Authorization: Bearer $TOKEN" /api/sagas/01934abc-.../events
Resposta:
[
{
"id": "...",
"sagaId": "01934abc-...",
"stepName": null,
"eventType": "SAGA_STARTED",
"payload": null,
"createdAt": "2024-01-15T10:04:58Z"
},
{
"id": "...",
"sagaId": "01934abc-...",
"stepName": "validate-dict",
"eventType": "STEP_COMPLETED",
"payload": "{\"durationMs\":45}",
"createdAt": "2024-01-15T10:05:00Z"
}
]
- 200 — lista de eventos (pode ser vazia)
- 404 — saga não existe
POST /api/sagas/{id}/reprocess
Reexecuta uma saga a partir do step que falhou.
curl -X POST -H "Authorization: Bearer $TOKEN" /api/sagas/01934abc-.../reprocess
- 202 — reprocessamento iniciado
- 404 — saga não existe
Endpoints de Métricas
GET /api/sagas/metrics
Retorna métricas agregadas de todas as sagas.
curl -H "Authorization: Bearer $TOKEN" /api/sagas/metrics
Resposta:
{
"total": 1520,
"started": 3,
"executing": 12,
"completed": 1480,
"compensated": 18,
"failed": 7,
"deadLetters": 2,
"successRate": 98.7,
"byName": [
{
"name": "pix-payment",
"total": 900,
"completed": 885,
"failed": 5
}
]
}
| Campo | Descrição |
|---|---|
successRate | completed / (completed + failed + compensated) * 100, arredondado em 1 decimal |
deadLetters | Dead letters pendentes (não reprocessadas) |
byName | Breakdown por nome de saga, ordenado por volume |
GET /api/sagas/stats/by-name
Retorna estatísticas por tipo de saga, incluindo duração média.
curl -H "Authorization: Bearer $TOKEN" /api/sagas/stats/by-name
Resposta:
[
{
"name": "pix-payment",
"total": 900,
"completed": 885,
"failed": 5,
"avgDurationMs": 312
},
{
"name": "order-processing",
"total": 620,
"completed": 595,
"failed": 2,
"avgDurationMs": 1840
}
]
| Campo | Descrição |
|---|---|
avgDurationMs | Duração média em milissegundos (apenas sagas COMPLETED) |
GET /api/sagas/steps/stats
Retorna estatísticas por step, agrupadas por nome de saga. Usado pelo dashboard para identificar gargalos.
curl -H "Authorization: Bearer $TOKEN" /api/sagas/steps/stats
Resposta:
[
{
"stepName": "transmit-to-bacen",
"sagaName": "pix-payment",
"avgDurationMs": 245,
"total": 900,
"failed": 12
},
{
"stepName": "validate-dict",
"sagaName": "pix-payment",
"avgDurationMs": 18,
"total": 900,
"failed": 0
}
]
Ordenado por avgDurationMs decrescente. avgDurationMs pode ser null se nenhum step ainda terminou.
O dashboard usa este endpoint para calcular a proporção de tempo de cada step relativa ao total da saga. Um step consumindo >40% do tempo total da saga aparece em vermelho — independente do valor absoluto em ms.
Endpoints de Dead Letters
Dead letters são steps que esgotaram todas as tentativas de retry e precisam de intervenção manual. A API expõe apenas as pendentes — itens reprocessados saem da fila e seu histórico fica no log de eventos da saga.
GET /api/dead-letters
Lista dead letters pendentes.
curl -H "Authorization: Bearer $TOKEN" /api/dead-letters
Resposta:
[
{
"id": "...",
"sagaId": "01934abc-...",
"sagaName": "pix-payment",
"stepName": "transmit-to-bacen",
"errorMessage": "Connection timeout after 3 attempts",
"errorTrace": "java.net.SocketTimeoutException: ...",
"contextSnapshot": "{\"transactionId\":\"...\"}",
"createdAt": "2024-01-15T10:10:00Z"
}
]
| Campo | Descrição |
|---|---|
errorMessage | Mensagem resumida da última exceção |
errorTrace | Stack trace completo |
contextSnapshot | JSON do contexto da saga no momento da falha |
GET /api/dead-letters/{id}
Retorna uma dead letter específica pelo ID.
curl -H "Authorization: Bearer $TOKEN" /api/dead-letters/abc-...
- 200 — dead letter encontrada
- 404 — não existe
POST /api/dead-letters/{id}/reprocess
Marca a dead letter como reprocessada e reinicia o step correspondente na saga.
curl -X POST -H "Authorization: Bearer $TOKEN" /api/dead-letters/abc-.../reprocess
- 202 — reprocessamento iniciado
- 404 — dead letter não existe
A dead letter desaparece da fila pendente. O passo é re-executado com a política de retry configurada. O resultado (sucesso ou nova falha) aparece no log de eventos da saga em /api/sagas/{id}/events.