mirror of
https://github.com/caddyserver/caddy.git
synced 2025-01-14 14:56:27 +03:00
caddyhttp: Make metrics opt-in (#5042)
* caddyhttp: Make metrics opt-in Related to #4644 * Make configurable in Caddyfile
This commit is contained in:
parent
258071d857
commit
74547f5bed
5 changed files with 30 additions and 8 deletions
|
@ -43,6 +43,7 @@ type serverOptions struct {
|
||||||
Protocols []string
|
Protocols []string
|
||||||
StrictSNIHost *bool
|
StrictSNIHost *bool
|
||||||
ShouldLogCredentials bool
|
ShouldLogCredentials bool
|
||||||
|
Metrics *caddyhttp.Metrics
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
|
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
|
||||||
|
@ -175,6 +176,15 @@ func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
|
||||||
}
|
}
|
||||||
serverOpts.StrictSNIHost = &boolVal
|
serverOpts.StrictSNIHost = &boolVal
|
||||||
|
|
||||||
|
case "metrics":
|
||||||
|
if d.NextArg() {
|
||||||
|
return nil, d.ArgErr()
|
||||||
|
}
|
||||||
|
if d.NextBlock(0) {
|
||||||
|
return nil, d.ArgErr()
|
||||||
|
}
|
||||||
|
serverOpts.Metrics = new(caddyhttp.Metrics)
|
||||||
|
|
||||||
// TODO: DEPRECATED. (August 2022)
|
// TODO: DEPRECATED. (August 2022)
|
||||||
case "protocol":
|
case "protocol":
|
||||||
caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol sub-option will be removed soon")
|
caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol sub-option will be removed soon")
|
||||||
|
@ -259,6 +269,7 @@ func applyServerOptions(
|
||||||
server.MaxHeaderBytes = opts.MaxHeaderBytes
|
server.MaxHeaderBytes = opts.MaxHeaderBytes
|
||||||
server.Protocols = opts.Protocols
|
server.Protocols = opts.Protocols
|
||||||
server.StrictSNIHost = opts.StrictSNIHost
|
server.StrictSNIHost = opts.StrictSNIHost
|
||||||
|
server.Metrics = opts.Metrics
|
||||||
if opts.ShouldLogCredentials {
|
if opts.ShouldLogCredentials {
|
||||||
if server.Logs == nil {
|
if server.Logs == nil {
|
||||||
server.Logs = &caddyhttp.ServerLogConfig{}
|
server.Logs = &caddyhttp.ServerLogConfig{}
|
||||||
|
|
|
@ -263,7 +263,7 @@ func (app *App) Provision(ctx caddy.Context) error {
|
||||||
// route handler so that important security checks are done, etc.
|
// route handler so that important security checks are done, etc.
|
||||||
primaryRoute := emptyHandler
|
primaryRoute := emptyHandler
|
||||||
if srv.Routes != nil {
|
if srv.Routes != nil {
|
||||||
err := srv.Routes.ProvisionHandlers(ctx)
|
err := srv.Routes.ProvisionHandlers(ctx, srv.Metrics)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("server %s: setting up route handlers: %v", srvName, err)
|
return fmt.Errorf("server %s: setting up route handlers: %v", srvName, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,10 @@ import (
|
||||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Metrics configures metrics observations.
|
||||||
|
// EXPERIMENTAL and subject to change or removal.
|
||||||
|
type Metrics struct{}
|
||||||
|
|
||||||
var httpMetrics = struct {
|
var httpMetrics = struct {
|
||||||
init sync.Once
|
init sync.Once
|
||||||
requestInFlight *prometheus.GaugeVec
|
requestInFlight *prometheus.GaugeVec
|
||||||
|
|
|
@ -130,7 +130,7 @@ func (routes RouteList) Provision(ctx caddy.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return routes.ProvisionHandlers(ctx)
|
return routes.ProvisionHandlers(ctx, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProvisionMatchers sets up all the matchers by loading the
|
// ProvisionMatchers sets up all the matchers by loading the
|
||||||
|
@ -156,7 +156,7 @@ func (routes RouteList) ProvisionMatchers(ctx caddy.Context) error {
|
||||||
// handler modules. Only call this method directly if you need
|
// handler modules. Only call this method directly if you need
|
||||||
// to set up matchers and handlers separately without having
|
// to set up matchers and handlers separately without having
|
||||||
// to provision a second time; otherwise use Provision instead.
|
// to provision a second time; otherwise use Provision instead.
|
||||||
func (routes RouteList) ProvisionHandlers(ctx caddy.Context) error {
|
func (routes RouteList) ProvisionHandlers(ctx caddy.Context, metrics *Metrics) error {
|
||||||
for i := range routes {
|
for i := range routes {
|
||||||
handlersIface, err := ctx.LoadModule(&routes[i], "HandlersRaw")
|
handlersIface, err := ctx.LoadModule(&routes[i], "HandlersRaw")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -168,7 +168,7 @@ func (routes RouteList) ProvisionHandlers(ctx caddy.Context) error {
|
||||||
|
|
||||||
// pre-compile the middleware handler chain
|
// pre-compile the middleware handler chain
|
||||||
for _, midhandler := range routes[i].Handlers {
|
for _, midhandler := range routes[i].Handlers {
|
||||||
routes[i].middleware = append(routes[i].middleware, wrapMiddleware(ctx, midhandler))
|
routes[i].middleware = append(routes[i].middleware, wrapMiddleware(ctx, midhandler, metrics))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -270,9 +270,12 @@ func wrapRoute(route Route) Middleware {
|
||||||
// we need to pull this particular MiddlewareHandler
|
// we need to pull this particular MiddlewareHandler
|
||||||
// pointer into its own stack frame to preserve it so it
|
// pointer into its own stack frame to preserve it so it
|
||||||
// won't be overwritten in future loop iterations.
|
// won't be overwritten in future loop iterations.
|
||||||
func wrapMiddleware(ctx caddy.Context, mh MiddlewareHandler) Middleware {
|
func wrapMiddleware(ctx caddy.Context, mh MiddlewareHandler, metrics *Metrics) Middleware {
|
||||||
// wrap the middleware with metrics instrumentation
|
handlerToUse := mh
|
||||||
metricsHandler := newMetricsInstrumentedHandler(caddy.GetModuleName(mh), mh)
|
if metrics != nil {
|
||||||
|
// wrap the middleware with metrics instrumentation
|
||||||
|
handlerToUse = newMetricsInstrumentedHandler(caddy.GetModuleName(mh), mh)
|
||||||
|
}
|
||||||
|
|
||||||
return func(next Handler) Handler {
|
return func(next Handler) Handler {
|
||||||
// copy the next handler (it's an interface, so it's
|
// copy the next handler (it's an interface, so it's
|
||||||
|
@ -284,7 +287,7 @@ func wrapMiddleware(ctx caddy.Context, mh MiddlewareHandler) Middleware {
|
||||||
return HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
|
return HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
|
||||||
// TODO: This is where request tracing could be implemented
|
// TODO: This is where request tracing could be implemented
|
||||||
// TODO: see what the std lib gives us in terms of stack tracing too
|
// TODO: see what the std lib gives us in terms of stack tracing too
|
||||||
return metricsHandler.ServeHTTP(w, r, nextCopy)
|
return handlerToUse.ServeHTTP(w, r, nextCopy)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,6 +152,10 @@ type Server struct {
|
||||||
// Default: `[h1 h2 h3]`
|
// Default: `[h1 h2 h3]`
|
||||||
Protocols []string `json:"protocols,omitempty"`
|
Protocols []string `json:"protocols,omitempty"`
|
||||||
|
|
||||||
|
// If set, metrics observations will be enabled.
|
||||||
|
// This setting is EXPERIMENTAL and subject to change.
|
||||||
|
Metrics *Metrics `json:"metrics,omitempty"`
|
||||||
|
|
||||||
name string
|
name string
|
||||||
|
|
||||||
primaryHandlerChain Handler
|
primaryHandlerChain Handler
|
||||||
|
|
Loading…
Reference in a new issue