diff --git a/aperture.go b/aperture.go index 35cec7d..c417112 100644 --- a/aperture.go +++ b/aperture.go @@ -151,7 +151,7 @@ func run() error { errChan := make(chan error) a := NewAperture(cfg) - if err := a.Start(errChan); err != nil { + if err := a.Start(errChan, interceptor.ShutdownChannel()); err != nil { return fmt.Errorf("unable to start aperture: %v", err) } @@ -192,9 +192,9 @@ func NewAperture(cfg *Config) *Aperture { } // Start sets up the proxy server and starts it. -func (a *Aperture) Start(errChan chan error) error { +func (a *Aperture) Start(errChan chan error, shutdown <-chan struct{}) error { // Start the prometheus exporter. - err := StartPrometheusExporter(a.cfg.Prometheus) + err := StartPrometheusExporter(a.cfg.Prometheus, shutdown) if err != nil { return fmt.Errorf("unable to start the prometheus "+ "exporter: %v", err) diff --git a/hashmail_server.go b/hashmail_server.go index 69822d3..0c03276 100644 --- a/hashmail_server.go +++ b/hashmail_server.go @@ -809,9 +809,9 @@ func (sa *streamActivity) Record(baseID string) { // ClassifyAndReset categorizes each tracked stream based on its recent read // rate and returns aggregate counts of active, standby, and in-use sessions. // A stream is classified as: -// - In-use: if read rate ≥ 0.5 reads/sec -// - Standby: if 0 < read rate < 0.5 reads/sec -// - Active: if read rate > 0 (includes standby and in-use) +// - In-use: if read rate ≥ 0.5 reads/sec. +// - Standby: if 0 < read rate < 0.5 reads/sec. +// - Active: if read rate > 0 (includes standby and in-use). func (sa *streamActivity) ClassifyAndReset() (active, standby, inuse int) { sa.Lock() defer sa.Unlock() diff --git a/hashmail_server_test.go b/hashmail_server_test.go index 609dff9..d4a4848 100644 --- a/hashmail_server_test.go +++ b/hashmail_server_test.go @@ -186,7 +186,8 @@ func setupAperture(t *testing.T) { } aperture := NewAperture(apertureCfg) errChan := make(chan error) - require.NoError(t, aperture.Start(errChan)) + shutdown := make(chan struct{}) + require.NoError(t, aperture.Start(errChan, shutdown)) // Any error while starting? select { diff --git a/prometheus.go b/prometheus.go index 353d63e..c921667 100644 --- a/prometheus.go +++ b/prometheus.go @@ -16,21 +16,21 @@ var ( Name: "mailbox_count", }) - // activeSessions tracks the active session count for mailbox + // activeSessions tracks the active session count for mailbox. activeSessions = prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: "hashmail", Name: "mailbox_active_sessions", Help: "Number of active sessions", }) - // standbySessions tracks the standby session count for mailbox + // standbySessions tracks the standby session count for mailbox. standbySessions = prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: "hashmail", Name: "mailbox_standby_sessions", Help: "Number of standby sessions", }) - // inUseSessions tracks the in-use session count for mailbox + // inUseSessions tracks the in-use session count for mailbox. inUseSessions = prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: "hashmail", Name: "mailbox_inuse_sessions", @@ -38,7 +38,7 @@ var ( }) ) -// streamActivityTracker handles the calculation of session statistics +// streamActivityTracker handles the calculation of session statistics. var streamActivityTracker = newStreamActivity() // PrometheusConfig is the set of configuration data that specifies if @@ -56,7 +56,9 @@ type PrometheusConfig struct { // StartPrometheusExporter registers all relevant metrics with the Prometheus // library, then launches the HTTP server that Prometheus will hit to scrape // our metrics. -func StartPrometheusExporter(cfg *PrometheusConfig) error { +func StartPrometheusExporter(cfg *PrometheusConfig, + shutdown <-chan struct{}) error { + // If we're not active, then there's nothing more to do. if !cfg.Enabled { return nil @@ -68,16 +70,23 @@ func StartPrometheusExporter(cfg *PrometheusConfig) error { prometheus.MustRegister(standbySessions) prometheus.MustRegister(inUseSessions) - // Periodically update session classification metrics from internal tracker + // Periodically update session classification metrics from internal tracker. go func() { ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() - for range ticker.C { - active, standby, inuse := streamActivityTracker.ClassifyAndReset() - activeSessions.Set(float64(active)) - standbySessions.Set(float64(standby)) - inUseSessions.Set(float64(inuse)) + for { + select { + case <-ticker.C: + active, standby, inuse := + streamActivityTracker.ClassifyAndReset() + activeSessions.Set(float64(active)) + standbySessions.Set(float64(standby)) + inUseSessions.Set(float64(inuse)) + case <-shutdown: + log.Infof("Shutting down Prometheus session metrics updater") + return + } } }()