diff --git a/modules/caddyhttp/app.go b/modules/caddyhttp/app.go index e48f8286400..3edc5b23a96 100644 --- a/modules/caddyhttp/app.go +++ b/modules/caddyhttp/app.go @@ -263,7 +263,7 @@ func (app *App) Provision(ctx caddy.Context) error { // route handler so that important security checks are done, etc. primaryRoute := emptyHandler if srv.Routes != nil { - err := srv.Routes.ProvisionHandlers(ctx) + err := srv.Routes.ProvisionHandlers(ctx, srv.Metrics) if err != nil { return fmt.Errorf("server %s: setting up route handlers: %v", srvName, err) } diff --git a/modules/caddyhttp/metrics.go b/modules/caddyhttp/metrics.go index 458c22afebc..64fbed750e4 100644 --- a/modules/caddyhttp/metrics.go +++ b/modules/caddyhttp/metrics.go @@ -11,6 +11,10 @@ import ( "github.com/prometheus/client_golang/prometheus/promauto" ) +// Metrics configures metrics observations. +// EXPERIMENTAL and subject to change or removal. +type Metrics struct{} + var httpMetrics = struct { init sync.Once requestInFlight *prometheus.GaugeVec diff --git a/modules/caddyhttp/routes.go b/modules/caddyhttp/routes.go index ce9bece20c2..da25097bfa1 100644 --- a/modules/caddyhttp/routes.go +++ b/modules/caddyhttp/routes.go @@ -130,7 +130,7 @@ func (routes RouteList) Provision(ctx caddy.Context) error { if err != nil { return err } - return routes.ProvisionHandlers(ctx) + return routes.ProvisionHandlers(ctx, nil) } // 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 // to set up matchers and handlers separately without having // 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 { handlersIface, err := ctx.LoadModule(&routes[i], "HandlersRaw") if err != nil { @@ -168,7 +168,7 @@ func (routes RouteList) ProvisionHandlers(ctx caddy.Context) error { // pre-compile the middleware handler chain 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 @@ -270,9 +270,12 @@ func wrapRoute(route Route) Middleware { // we need to pull this particular MiddlewareHandler // pointer into its own stack frame to preserve it so it // won't be overwritten in future loop iterations. -func wrapMiddleware(ctx caddy.Context, mh MiddlewareHandler) Middleware { - // wrap the middleware with metrics instrumentation - metricsHandler := newMetricsInstrumentedHandler(caddy.GetModuleName(mh), mh) +func wrapMiddleware(ctx caddy.Context, mh MiddlewareHandler, metrics *Metrics) Middleware { + handlerToUse := mh + if metrics != nil { + // wrap the middleware with metrics instrumentation + handlerToUse = newMetricsInstrumentedHandler(caddy.GetModuleName(mh), mh) + } return func(next Handler) Handler { // 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 { // TODO: This is where request tracing could be implemented // 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) }) } } diff --git a/modules/caddyhttp/server.go b/modules/caddyhttp/server.go index 83f1a533318..ca5a5949304 100644 --- a/modules/caddyhttp/server.go +++ b/modules/caddyhttp/server.go @@ -152,6 +152,10 @@ type Server struct { // Default: `[h1 h2 h3]` 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 primaryHandlerChain Handler