Files
aether/metrics_prometheus.go
Hugo Nijhuis dae751a6ef
All checks were successful
CI / build (pull_request) Successful in 38s
Add EventBroadcaster metrics for observability and debugging
- Add BroadcasterMetrics interface for reading metrics per namespace
- Add MetricsCollector interface and DefaultMetricsCollector implementation
- Track events_published and events_received counters per namespace
- Track active_subscriptions gauge per namespace
- Track publish_errors, subscribe_errors, and dropped_events counters
- Add MetricsProvider interface for EventBroadcaster implementations
- Integrate metrics tracking into EventBus and NATSEventBus
- Add optional Prometheus integration via PrometheusMetricsAdapter
- Add comprehensive unit tests for metrics functionality

Closes #22

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 19:51:23 +01:00

124 lines
3.4 KiB
Go

package aether
import (
"github.com/prometheus/client_golang/prometheus"
)
// PrometheusMetricsAdapter exposes BroadcasterMetrics as Prometheus metrics.
// It implements prometheus.Collector and can be registered with a Prometheus registry.
type PrometheusMetricsAdapter struct {
metrics BroadcasterMetrics
eventsPublishedDesc *prometheus.Desc
eventsReceivedDesc *prometheus.Desc
activeSubscriptionsDesc *prometheus.Desc
publishErrorsDesc *prometheus.Desc
subscribeErrorsDesc *prometheus.Desc
droppedEventsDesc *prometheus.Desc
}
// NewPrometheusMetricsAdapter creates a new PrometheusMetricsAdapter that wraps
// a BroadcasterMetrics implementation and exposes it as Prometheus metrics.
//
// The adapter implements prometheus.Collector and should be registered with
// a Prometheus registry:
//
// eb := aether.NewEventBus()
// adapter := aether.NewPrometheusMetricsAdapter(eb.Metrics())
// prometheus.MustRegister(adapter)
func NewPrometheusMetricsAdapter(metrics BroadcasterMetrics) *PrometheusMetricsAdapter {
return &PrometheusMetricsAdapter{
metrics: metrics,
eventsPublishedDesc: prometheus.NewDesc(
"aether_events_published_total",
"Total number of events published per namespace",
[]string{"namespace"},
nil,
),
eventsReceivedDesc: prometheus.NewDesc(
"aether_events_received_total",
"Total number of events received per namespace",
[]string{"namespace"},
nil,
),
activeSubscriptionsDesc: prometheus.NewDesc(
"aether_active_subscriptions",
"Number of active subscriptions per namespace",
[]string{"namespace"},
nil,
),
publishErrorsDesc: prometheus.NewDesc(
"aether_publish_errors_total",
"Total number of publish errors per namespace",
[]string{"namespace"},
nil,
),
subscribeErrorsDesc: prometheus.NewDesc(
"aether_subscribe_errors_total",
"Total number of subscribe errors per namespace",
[]string{"namespace"},
nil,
),
droppedEventsDesc: prometheus.NewDesc(
"aether_dropped_events_total",
"Total number of dropped events per namespace",
[]string{"namespace"},
nil,
),
}
}
// Describe implements prometheus.Collector.
func (a *PrometheusMetricsAdapter) Describe(ch chan<- *prometheus.Desc) {
ch <- a.eventsPublishedDesc
ch <- a.eventsReceivedDesc
ch <- a.activeSubscriptionsDesc
ch <- a.publishErrorsDesc
ch <- a.subscribeErrorsDesc
ch <- a.droppedEventsDesc
}
// Collect implements prometheus.Collector.
func (a *PrometheusMetricsAdapter) Collect(ch chan<- prometheus.Metric) {
namespaces := a.metrics.Namespaces()
for _, ns := range namespaces {
ch <- prometheus.MustNewConstMetric(
a.eventsPublishedDesc,
prometheus.CounterValue,
float64(a.metrics.EventsPublished(ns)),
ns,
)
ch <- prometheus.MustNewConstMetric(
a.eventsReceivedDesc,
prometheus.CounterValue,
float64(a.metrics.EventsReceived(ns)),
ns,
)
ch <- prometheus.MustNewConstMetric(
a.activeSubscriptionsDesc,
prometheus.GaugeValue,
float64(a.metrics.ActiveSubscriptions(ns)),
ns,
)
ch <- prometheus.MustNewConstMetric(
a.publishErrorsDesc,
prometheus.CounterValue,
float64(a.metrics.PublishErrors(ns)),
ns,
)
ch <- prometheus.MustNewConstMetric(
a.subscribeErrorsDesc,
prometheus.CounterValue,
float64(a.metrics.SubscribeErrors(ns)),
ns,
)
ch <- prometheus.MustNewConstMetric(
a.droppedEventsDesc,
prometheus.CounterValue,
float64(a.metrics.DroppedEvents(ns)),
ns,
)
}
}