Files
aperture/prometheus.go
2025-05-21 11:28:34 -04:00

105 lines
3.1 KiB
Go

package aperture
import (
"fmt"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
// mailboxCount tracks the current number of active mailboxes.
mailboxCount = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "hashmail",
Name: "mailbox_count",
})
// 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 = 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 = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "hashmail",
Name: "mailbox_inuse_sessions",
Help: "Number of in-use sessions",
})
)
// streamActivityTracker handles the calculation of session statistics.
var streamActivityTracker = newStreamActivity()
// PrometheusConfig is the set of configuration data that specifies if
// Prometheus metric exporting is activated, and if so the listening address of
// the Prometheus server.
type PrometheusConfig struct {
// Enabled, if true, then Prometheus metrics will be exported.
Enabled bool `long:"enabled" description:"if true prometheus metrics will be exported"`
// ListenAddr is the listening address that we should use to allow the
// main Prometheus server to scrape our metrics.
ListenAddr string `long:"listenaddr" description:"the interface we should listen on for prometheus"`
}
// 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,
shutdown <-chan struct{}) error {
// If we're not active, then there's nothing more to do.
if !cfg.Enabled {
return nil
}
// Next, we'll register all our metrics.
prometheus.MustRegister(mailboxCount)
prometheus.MustRegister(activeSessions)
prometheus.MustRegister(standbySessions)
prometheus.MustRegister(inUseSessions)
// Periodically update session classification metrics from internal tracker.
go func() {
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
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
}
}
}()
// Finally, we'll launch the HTTP server that Prometheus will use to
// scape our metrics.
go func() {
log.Infof("Prometheus metrics http endpoint being served on "+
"%s", cfg.ListenAddr)
http.Handle("/metrics", promhttp.Handler())
fmt.Println(http.ListenAndServe(cfg.ListenAddr, nil))
}()
return nil
}