package rushlink import ( "log" "net/http" "time" "gitea.hashru.nl/dsprenkels/rushlink/internal/db" "github.com/gorilla/mux" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" bolt "go.etcd.io/bbolt" ) const metricNamespace = "rushlink" var metricRequestsTotalCounter = prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: metricNamespace, Subsystem: "http", Name: "requests_total", Help: "How many HTTP requests processed, partitioned by status code and HTTP method.", }, []string{"code", "method"}) func metricURLsTotal(database *db.Database) float64 { var metric float64 if err := database.Bolt.View(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte("pastes")) if bucket == nil { return errors.New("bucket 'pastes' could not be found") } metric = float64(bucket.Stats().KeyN) return nil }); err != nil { log.Printf("error: %v", errors.Wrap(err, "fetching pastes_total metric")) return 0 } return metric } // StartMetricsServer starts sering Prometheus metrics exports on addr func StartMetricsServer(addr string, database *db.Database, fs *db.FileStore) { prometheus.MustRegister(metricRequestsTotalCounter) prometheus.MustRegister(prometheus.NewGaugeFunc(prometheus.GaugeOpts{ Namespace: metricNamespace, Subsystem: "pastes", Name: "urls_total", Help: "The current amount of pastes in the database.", }, func() float64 { return metricURLsTotal(database) })) router := mux.NewRouter() router.Handle("/metrics", promhttp.Handler()).Methods("GET") srv := &http.Server{ Handler: router, Addr: addr, WriteTimeout: 15 * time.Second, ReadTimeout: 15 * time.Second, } log.Fatal(srv.ListenAndServe()) }