rclone/fs/rc/rcserver/metrics.go

97 lines
2.4 KiB
Go

// Package rcserver implements the HTTP endpoint to serve the remote control
package rcserver
import (
"context"
"fmt"
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/rclone/rclone/fs/accounting"
"github.com/rclone/rclone/fs/fshttp"
"github.com/rclone/rclone/fs/rc"
"github.com/rclone/rclone/fs/rc/jobs"
libhttp "github.com/rclone/rclone/lib/http"
)
const path = "/metrics"
var promHandlerFunc http.HandlerFunc
func init() {
rcloneCollector := accounting.NewRcloneCollector(context.Background())
prometheus.MustRegister(rcloneCollector)
m := fshttp.NewMetrics("rclone")
for _, c := range m.Collectors() {
prometheus.MustRegister(c)
}
fshttp.DefaultMetrics = m
promHandlerFunc = promhttp.Handler().ServeHTTP
}
// MetricsStart the remote control server if configured
//
// If the server wasn't configured the *Server returned may be nil
func MetricsStart(ctx context.Context, opt *rc.Options) (*MetricsServer, error) {
jobs.SetOpt(opt) // set the defaults for jobs
if opt.MetricsHTTP.ListenAddr[0] != "" {
// Serve on the DefaultServeMux so can have global registrations appear
s, err := newMetricsServer(ctx, opt)
if err != nil {
return nil, err
}
return s, s.Serve()
}
return nil, nil
}
// MetricsServer contains everything to run the rc server
type MetricsServer struct {
ctx context.Context // for global config
server *libhttp.Server
promHandlerFunc http.Handler
opt *rc.Options
}
func newMetricsServer(ctx context.Context, opt *rc.Options) (*MetricsServer, error) {
s := &MetricsServer{
ctx: ctx,
opt: opt,
promHandlerFunc: promHandlerFunc,
}
var err error
s.server, err = libhttp.NewServer(ctx,
libhttp.WithConfig(opt.MetricsHTTP),
libhttp.WithAuth(opt.MetricsAuth),
libhttp.WithTemplate(opt.MetricsTemplate),
)
if err != nil {
return nil, fmt.Errorf("failed to init server: %w", err)
}
router := s.server.Router()
router.Get(path, promHandlerFunc)
return s, nil
}
// Serve runs the http server in the background.
//
// Use s.Close() and s.Wait() to shutdown server
func (s *MetricsServer) Serve() error {
s.server.Serve()
return nil
}
// Wait blocks while the server is serving requests
func (s *MetricsServer) Wait() {
s.server.Wait()
}
// Shutdown gracefully shuts down the server
func (s *MetricsServer) Shutdown() error {
return s.server.Shutdown()
}