[Issue #22] Add EventBroadcaster metrics (#49)
All checks were successful
CI / build (push) Successful in 19s
All checks were successful
CI / build (push) Successful in 19s
This commit was merged in pull request #49.
This commit is contained in:
36
eventbus.go
36
eventbus.go
@@ -24,6 +24,13 @@ type EventBroadcaster interface {
|
||||
SubscriberCount(namespaceID string) int
|
||||
}
|
||||
|
||||
// MetricsProvider is an optional interface that EventBroadcaster implementations
|
||||
// can implement to expose metrics.
|
||||
type MetricsProvider interface {
|
||||
// Metrics returns the metrics collector for this broadcaster.
|
||||
Metrics() BroadcasterMetrics
|
||||
}
|
||||
|
||||
// subscription represents a single subscriber channel with its pattern
|
||||
type subscription struct {
|
||||
pattern string
|
||||
@@ -45,6 +52,7 @@ type EventBus struct {
|
||||
mutex sync.RWMutex
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
metrics *DefaultMetricsCollector
|
||||
}
|
||||
|
||||
// NewEventBus creates a new event bus
|
||||
@@ -55,9 +63,15 @@ func NewEventBus() *EventBus {
|
||||
wildcardSubscribers: make([]subscription, 0),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
metrics: NewMetricsCollector(),
|
||||
}
|
||||
}
|
||||
|
||||
// Metrics returns the metrics collector for this event bus.
|
||||
func (eb *EventBus) Metrics() BroadcasterMetrics {
|
||||
return eb.metrics
|
||||
}
|
||||
|
||||
// Subscribe creates a new subscription channel for a namespace pattern.
|
||||
// Patterns follow NATS subject matching conventions:
|
||||
// - "*" matches a single token (any sequence without ".")
|
||||
@@ -84,6 +98,9 @@ func (eb *EventBus) Subscribe(namespacePattern string) <-chan *Event {
|
||||
eb.exactSubscribers[namespacePattern] = append(eb.exactSubscribers[namespacePattern], ch)
|
||||
}
|
||||
|
||||
// Record subscription metric
|
||||
eb.metrics.RecordSubscribe(namespacePattern)
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
@@ -98,6 +115,8 @@ func (eb *EventBus) Unsubscribe(namespacePattern string, ch <-chan *Event) {
|
||||
if sub.ch == ch {
|
||||
eb.wildcardSubscribers = append(eb.wildcardSubscribers[:i], eb.wildcardSubscribers[i+1:]...)
|
||||
close(sub.ch)
|
||||
// Record unsubscription metric
|
||||
eb.metrics.RecordUnsubscribe(namespacePattern)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -109,6 +128,8 @@ func (eb *EventBus) Unsubscribe(namespacePattern string, ch <-chan *Event) {
|
||||
// Remove channel from slice
|
||||
eb.exactSubscribers[namespacePattern] = append(subs[:i], subs[i+1:]...)
|
||||
close(subscriber)
|
||||
// Record unsubscription metric
|
||||
eb.metrics.RecordUnsubscribe(namespacePattern)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -128,14 +149,19 @@ func (eb *EventBus) Publish(namespaceID string, event *Event) {
|
||||
eb.mutex.RLock()
|
||||
defer eb.mutex.RUnlock()
|
||||
|
||||
// Record publish metric
|
||||
eb.metrics.RecordPublish(namespaceID)
|
||||
|
||||
// Deliver to exact subscribers
|
||||
subscribers := eb.exactSubscribers[namespaceID]
|
||||
for _, ch := range subscribers {
|
||||
select {
|
||||
case ch <- event:
|
||||
// Event delivered
|
||||
eb.metrics.RecordReceive(namespaceID)
|
||||
default:
|
||||
// Channel full, skip this subscriber (non-blocking)
|
||||
eb.metrics.RecordDroppedEvent(namespaceID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,8 +171,10 @@ func (eb *EventBus) Publish(namespaceID string, event *Event) {
|
||||
select {
|
||||
case sub.ch <- event:
|
||||
// Event delivered
|
||||
eb.metrics.RecordReceive(namespaceID)
|
||||
default:
|
||||
// Channel full, skip this subscriber (non-blocking)
|
||||
eb.metrics.RecordDroppedEvent(namespaceID)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,16 +187,18 @@ func (eb *EventBus) Stop() {
|
||||
|
||||
eb.cancel()
|
||||
|
||||
// Close all exact subscriber channels
|
||||
for _, subs := range eb.exactSubscribers {
|
||||
// Close all exact subscriber channels and update metrics
|
||||
for namespaceID, subs := range eb.exactSubscribers {
|
||||
for _, ch := range subs {
|
||||
close(ch)
|
||||
eb.metrics.RecordUnsubscribe(namespaceID)
|
||||
}
|
||||
}
|
||||
|
||||
// Close all wildcard subscriber channels
|
||||
// Close all wildcard subscriber channels and update metrics
|
||||
for _, sub := range eb.wildcardSubscribers {
|
||||
close(sub.ch)
|
||||
eb.metrics.RecordUnsubscribe(sub.pattern)
|
||||
}
|
||||
|
||||
eb.exactSubscribers = make(map[string][]chan *Event)
|
||||
|
||||
Reference in New Issue
Block a user