mirror of
https://github.com/caddyserver/caddy.git
synced 2025-12-08 06:09:53 +00:00
Merge e4ed74ce85 into 67a9e0657e
This commit is contained in:
commit
a1b0bb19ed
5 changed files with 71 additions and 25 deletions
|
|
@ -51,7 +51,7 @@ type Context struct {
|
||||||
ancestry []Module
|
ancestry []Module
|
||||||
cleanupFuncs []func() // invoked at every config unload
|
cleanupFuncs []func() // invoked at every config unload
|
||||||
exitFuncs []func(context.Context) // invoked at config unload ONLY IF the process is exiting (EXPERIMENTAL)
|
exitFuncs []func(context.Context) // invoked at config unload ONLY IF the process is exiting (EXPERIMENTAL)
|
||||||
metricsRegistry *prometheus.Registry
|
metricsRegistry *registryGatherer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContext provides a new context derived from the given
|
// NewContext provides a new context derived from the given
|
||||||
|
|
@ -63,7 +63,8 @@ type Context struct {
|
||||||
// modules which are loaded will be properly unloaded.
|
// modules which are loaded will be properly unloaded.
|
||||||
// See standard library context package's documentation.
|
// See standard library context package's documentation.
|
||||||
func NewContext(ctx Context) (Context, context.CancelFunc) {
|
func NewContext(ctx Context) (Context, context.CancelFunc) {
|
||||||
newCtx := Context{moduleInstances: make(map[string][]Module), cfg: ctx.cfg, metricsRegistry: prometheus.NewPedanticRegistry()}
|
r := prometheus.NewPedanticRegistry()
|
||||||
|
newCtx := Context{moduleInstances: make(map[string][]Module), cfg: ctx.cfg, metricsRegistry: ®istryGatherer{registry: r, gatherer: r}}
|
||||||
c, cancel := context.WithCancel(ctx.Context)
|
c, cancel := context.WithCancel(ctx.Context)
|
||||||
wrappedCancel := func() {
|
wrappedCancel := func() {
|
||||||
cancel()
|
cancel()
|
||||||
|
|
@ -105,7 +106,7 @@ func (ctx *Context) FileSystems() FileSystems {
|
||||||
|
|
||||||
// Returns the active metrics registry for the context
|
// Returns the active metrics registry for the context
|
||||||
// EXPERIMENTAL: This API is subject to change.
|
// EXPERIMENTAL: This API is subject to change.
|
||||||
func (ctx *Context) GetMetricsRegistry() *prometheus.Registry {
|
func (ctx *Context) GetMetricsRegistry() MetricsRegistererGatherer {
|
||||||
return ctx.metricsRegistry
|
return ctx.metricsRegistry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
63
metrics.go
63
metrics.go
|
|
@ -1,9 +1,11 @@
|
||||||
package caddy
|
package caddy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
io_prometheus_client "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2/internal/metrics"
|
"github.com/caddyserver/caddy/v2/internal/metrics"
|
||||||
)
|
)
|
||||||
|
|
@ -82,3 +84,64 @@ func (d *delegator) WriteHeader(code int) {
|
||||||
func (d *delegator) Unwrap() http.ResponseWriter {
|
func (d *delegator) Unwrap() http.ResponseWriter {
|
||||||
return d.ResponseWriter
|
return d.ResponseWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MetricsRegistererGatherer interface {
|
||||||
|
prometheus.Registerer
|
||||||
|
prometheus.Gatherer
|
||||||
|
}
|
||||||
|
type registryGatherer struct {
|
||||||
|
registry prometheus.Registerer
|
||||||
|
gatherer prometheus.Gatherer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gather implements prometheus.Gatherer.
|
||||||
|
func (r *registryGatherer) Gather() ([]*io_prometheus_client.MetricFamily, error) {
|
||||||
|
return r.gatherer.Gather()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustRegister calls `MustRegister` on the backing registry one collector
|
||||||
|
// at a time to capture the module at which the call may have panicked. Panics
|
||||||
|
// of duplicate registration are ignored.
|
||||||
|
func (r *registryGatherer) MustRegister(cs ...prometheus.Collector) {
|
||||||
|
var current prometheus.Collector
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err, ok := r.(error)
|
||||||
|
if !ok {
|
||||||
|
panic(r)
|
||||||
|
}
|
||||||
|
if !errors.Is(err, prometheus.AlreadyRegisteredError{
|
||||||
|
ExistingCollector: current,
|
||||||
|
NewCollector: current,
|
||||||
|
}) {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for _, current = range cs {
|
||||||
|
r.registry.MustRegister(current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register implements prometheus.Registerer. Errors of duplicate registration
|
||||||
|
// are ignored.
|
||||||
|
func (r *registryGatherer) Register(c prometheus.Collector) error {
|
||||||
|
if err := r.registry.Register(c); err != nil &&
|
||||||
|
!errors.Is(err, prometheus.AlreadyRegisteredError{
|
||||||
|
ExistingCollector: c,
|
||||||
|
NewCollector: c,
|
||||||
|
}) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unregister implements prometheus.Registerer.
|
||||||
|
func (r *registryGatherer) Unregister(c prometheus.Collector) bool {
|
||||||
|
return r.registry.Unregister(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ prometheus.Registerer = (*registryGatherer)(nil)
|
||||||
|
_ prometheus.Gatherer = (*registryGatherer)(nil)
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package reverseproxy
|
package reverseproxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -19,7 +18,7 @@ var reverseProxyMetrics = struct {
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
func initReverseProxyMetrics(handler *Handler, registry *prometheus.Registry) {
|
func initReverseProxyMetrics(handler *Handler, registry prometheus.Registerer) {
|
||||||
const ns, sub = "caddy", "reverse_proxy"
|
const ns, sub = "caddy", "reverse_proxy"
|
||||||
|
|
||||||
upstreamsLabels := []string{"upstream"}
|
upstreamsLabels := []string{"upstream"}
|
||||||
|
|
@ -32,17 +31,7 @@ func initReverseProxyMetrics(handler *Handler, registry *prometheus.Registry) {
|
||||||
}, upstreamsLabels)
|
}, upstreamsLabels)
|
||||||
})
|
})
|
||||||
|
|
||||||
// duplicate registration could happen if multiple sites with reverse proxy are configured; so ignore the error because
|
registry.MustRegister(reverseProxyMetrics.upstreamsHealthy)
|
||||||
// there's no good way to capture having multiple sites with reverse proxy. If this happens, the metrics will be
|
|
||||||
// registered twice, but the second registration will be ignored.
|
|
||||||
if err := registry.Register(reverseProxyMetrics.upstreamsHealthy); err != nil &&
|
|
||||||
!errors.Is(err, prometheus.AlreadyRegisteredError{
|
|
||||||
ExistingCollector: reverseProxyMetrics.upstreamsHealthy,
|
|
||||||
NewCollector: reverseProxyMetrics.upstreamsHealthy,
|
|
||||||
}) {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
reverseProxyMetrics.logger = handler.logger.Named("reverse_proxy.metrics")
|
reverseProxyMetrics.logger = handler.logger.Named("reverse_proxy.metrics")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -33,7 +31,7 @@ func init() {
|
||||||
// See the Metrics module for a configurable endpoint that is usable if the
|
// See the Metrics module for a configurable endpoint that is usable if the
|
||||||
// Admin API is disabled.
|
// Admin API is disabled.
|
||||||
type AdminMetrics struct {
|
type AdminMetrics struct {
|
||||||
registry *prometheus.Registry
|
registry caddy.MetricsRegistererGatherer
|
||||||
|
|
||||||
metricsHandler http.Handler
|
metricsHandler http.Handler
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,8 @@
|
||||||
package metrics
|
package metrics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
|
@ -64,9 +62,6 @@ func (l *zapLogger) Println(v ...any) {
|
||||||
func (m *Metrics) Provision(ctx caddy.Context) error {
|
func (m *Metrics) Provision(ctx caddy.Context) error {
|
||||||
log := ctx.Logger()
|
log := ctx.Logger()
|
||||||
registry := ctx.GetMetricsRegistry()
|
registry := ctx.GetMetricsRegistry()
|
||||||
if registry == nil {
|
|
||||||
return errors.New("no metrics registry found")
|
|
||||||
}
|
|
||||||
m.metricsHandler = createMetricsHandler(&zapLogger{log}, !m.DisableOpenMetrics, registry)
|
m.metricsHandler = createMetricsHandler(&zapLogger{log}, !m.DisableOpenMetrics, registry)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -112,7 +107,7 @@ var (
|
||||||
_ caddyfile.Unmarshaler = (*Metrics)(nil)
|
_ caddyfile.Unmarshaler = (*Metrics)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
func createMetricsHandler(logger promhttp.Logger, enableOpenMetrics bool, registry *prometheus.Registry) http.Handler {
|
func createMetricsHandler(logger promhttp.Logger, enableOpenMetrics bool, registry caddy.MetricsRegistererGatherer) http.Handler {
|
||||||
return promhttp.InstrumentMetricHandler(registry,
|
return promhttp.InstrumentMetricHandler(registry,
|
||||||
promhttp.HandlerFor(registry, promhttp.HandlerOpts{
|
promhttp.HandlerFor(registry, promhttp.HandlerOpts{
|
||||||
// will only log errors if logger is non-nil
|
// will only log errors if logger is non-nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue