routewatch/internal/metrics/metrics.go
sneak 92f7527cc5 Initial commit: RouteWatch BGP stream monitor
- Connects to RIPE RIS Live stream to receive real-time BGP updates
- Stores BGP data in SQLite database:
  - ASNs with first/last seen timestamps
  - Prefixes with IPv4/IPv6 classification
  - BGP announcements and withdrawals
  - AS-to-AS peering relationships from AS paths
  - Live routing table tracking active routes
- HTTP server with statistics endpoints
- Metrics tracking with go-metrics
- Custom JSON unmarshaling to handle nested AS sets in paths
- Dependency injection with uber/fx
- Pure Go implementation (no CGO)
- Includes streamdumper utility for debugging raw messages
2025-07-27 21:18:57 +02:00

101 lines
2.2 KiB
Go

// Package metrics provides centralized metrics tracking for the RouteWatch application
package metrics
import (
"sync"
"sync/atomic"
"time"
"github.com/rcrowley/go-metrics"
)
// Tracker provides centralized metrics tracking
type Tracker struct {
mu sync.RWMutex
registry metrics.Registry
connectedSince time.Time
isConnected atomic.Bool
// Stream metrics
messageCounter metrics.Counter
byteCounter metrics.Counter
messageRate metrics.Meter
byteRate metrics.Meter
}
// New creates a new metrics tracker
func New() *Tracker {
registry := metrics.NewRegistry()
return &Tracker{
registry: registry,
messageCounter: metrics.NewCounter(),
byteCounter: metrics.NewCounter(),
messageRate: metrics.NewMeter(),
byteRate: metrics.NewMeter(),
}
}
// SetConnected updates the connection status
func (t *Tracker) SetConnected(connected bool) {
t.isConnected.Store(connected)
if connected {
t.mu.Lock()
t.connectedSince = time.Now()
t.mu.Unlock()
}
}
// IsConnected returns the current connection status
func (t *Tracker) IsConnected() bool {
return t.isConnected.Load()
}
// RecordMessage records a received message and its size
func (t *Tracker) RecordMessage(bytes int64) {
t.messageCounter.Inc(1)
t.byteCounter.Inc(bytes)
t.messageRate.Mark(1)
t.byteRate.Mark(bytes)
}
// GetStreamMetrics returns current streaming metrics
func (t *Tracker) GetStreamMetrics() StreamMetrics {
t.mu.RLock()
connectedSince := t.connectedSince
t.mu.RUnlock()
const bitsPerByte = 8
// Safely convert counters to uint64
msgCount := t.messageCounter.Count()
byteCount := t.byteCounter.Count()
var totalMessages, totalBytes uint64
if msgCount >= 0 {
totalMessages = uint64(msgCount)
}
if byteCount >= 0 {
totalBytes = uint64(byteCount)
}
return StreamMetrics{
TotalMessages: totalMessages,
TotalBytes: totalBytes,
ConnectedSince: connectedSince,
Connected: t.isConnected.Load(),
MessagesPerSec: t.messageRate.Rate1(),
BitsPerSec: t.byteRate.Rate1() * bitsPerByte,
}
}
// StreamMetrics contains streaming statistics
type StreamMetrics struct {
TotalMessages uint64
TotalBytes uint64
ConnectedSince time.Time
Connected bool
MessagesPerSec float64
BitsPerSec float64
}