feat(tracing): add OpenTelemetry metrics middleware for outbox observability (Vibe Kanban)#39
Merged
jtomaszewski merged 3 commits intomainfrom Dec 22, 2025
Merged
Conversation
## Summary
Added built-in metrics/observability to the NestJS Outbox package. The implementation includes:
### New Files Created
1. **`packages/core/src/metrics/metrics-collector.interface.ts`** - Interface for metrics collection with:
- `MetricsCollector` interface with `recordEmit()`, `recordProcessed()`, `getSnapshot()`, `reset()`
- `OutboxMetricsSnapshot` type with aggregate counters and per-event/per-listener breakdowns
- `EventMetrics` and `ListenerMetrics` types for detailed tracking
2. **`packages/core/src/metrics/default-metrics-collector.ts`** - Default in-memory implementation tracking:
- Total events emitted/processed/succeeded/failed
- Total processing time
- Metrics broken down by event name and listener name
3. **`packages/core/src/metrics/metrics.middleware.ts`** - Middleware that hooks into the event lifecycle to record metrics on emit and after processing
4. **`packages/core/src/metrics/index.ts`** - Barrel export
5. **Test files** - Unit tests for both the collector and middleware
### Module Integration
Updated `OutboxModule` with two new options:
- `enableMetrics: boolean` (default: `false`) - Enable built-in metrics collection
- `metricsCollector?: MetricsCollector` - Optional custom collector implementation
When enabled, the `METRICS_COLLECTOR_TOKEN` is exported and can be injected to access metrics.
### Usage Example
```typescript
OutboxModule.registerAsync({
enableMetrics: true,
// ... other options
});
// Inject and use metrics
@Injectable()
class MetricsReporter {
constructor(
@Inject(METRICS_COLLECTOR_TOKEN)
private metrics: MetricsCollector,
) {}
getStats() {
const snapshot = this.metrics.getSnapshot();
return {
total: snapshot.eventsProcessed,
successRate: snapshot.eventsSucceeded / snapshot.eventsProcessed,
avgDuration: snapshot.totalProcessingTimeMs / snapshot.eventsProcessed,
};
}
}
```
## Summary
Moved metrics to the tracing package with proper OpenTelemetry metrics instead of in-memory counters.
### New File: `packages/tracing/src/metrics.outbox-middleware.ts`
A new `MetricsOutboxMiddleware` that uses OTel metrics API:
**Counters:**
- `outbox.events.emitted` - Total events emitted (with `outbox.event_name` attribute)
- `outbox.events.processed` - Total listener executions
- `outbox.events.succeeded` - Successful executions
- `outbox.events.failed` - Failed executions
**Histogram:**
- `outbox.processing.duration` - Processing duration in milliseconds
All metrics include `outbox.event_name` and `outbox.listener` attributes for filtering/grouping.
### Usage
```typescript
import { MetricsOutboxMiddleware } from '@fullstackhouse/nestjs-outbox-tracing';
OutboxModule.registerAsync({
middlewares: [MetricsOutboxMiddleware],
// ...
});
```
With custom meter name:
```typescript
{
provide: METRICS_OUTBOX_OPTIONS,
useValue: { meterName: 'my-app' },
}
```
The metrics integrate with any OTel-compatible backend (Prometheus, Grafana, Datadog, etc.) via the standard OTel metrics SDK.
…tered` counter that tracks events moved to DLQ with `outbox.event_name` and `outbox.retry_count` attributes.
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds built-in OpenTelemetry metrics support to the tracing package, providing comprehensive observability for outbox event processing.
Changes
New
MetricsOutboxMiddlewareA new middleware in
@fullstackhouse/nestjs-outbox-tracingthat exposes the following OTel metrics:Counters:
outbox.events.emitted- Total events emitted (withoutbox.event_nameattribute)outbox.events.processed- Total listener executionsoutbox.events.succeeded- Successful executionsoutbox.events.failed- Failed executionsoutbox.events.dead_lettered- Events moved to DLQ after exceeding max retriesHistogram:
outbox.processing.duration- Processing duration in millisecondsAll metrics include relevant attributes (
outbox.event_name,outbox.listener,outbox.retry_count) for filtering and grouping in dashboards.Why
Previously, the package relied entirely on custom middleware for observability with no built-in metrics. This made it harder to monitor outbox health out-of-the-box. By adding OTel metrics to the tracing package (which already has OTel as a peer dependency), users get production-ready observability that integrates with any OTel-compatible backend (Prometheus, Grafana, Datadog, etc.).
Usage
With custom meter name:
This PR was written using Vibe Kanban