@marcel91200 / caddy Mirror · read-only / commits / 74547f5b
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 13, 11:45 UTC

caddyhttp: Make metrics opt-in (#5042)

* caddyhttp: Make metrics opt-in Related to #4644 * Make configurable in Caddyfile

Matt Holt committed Sep 16, 2022 at 13:32 UTC 74547f5bedafcb59fc25f14b43301f33a40f9416
5 files changed +30 -8
caddyconfig/httpcaddyfile/serveroptions.go
+11
@@ -43,6 +43,7 @@ type serverOptions struct {
43 Protocols []string
44 StrictSNIHost *bool
45 ShouldLogCredentials bool
46 + Metrics *caddyhttp.Metrics
47 }
48
49 func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
@@ -175,6 +176,15 @@ func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
176 }
177 serverOpts.StrictSNIHost = &boolVal
178
179 + case "metrics":
180 + if d.NextArg() {
181 + return nil, d.ArgErr()
182 + }
183 + if d.NextBlock(0) {
184 + return nil, d.ArgErr()
185 + }
186 + serverOpts.Metrics = new(caddyhttp.Metrics)
187 +
188 // TODO: DEPRECATED. (August 2022)
189 case "protocol":
190 caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol sub-option will be removed soon")
@@ -259,6 +269,7 @@ func applyServerOptions(
269 server.MaxHeaderBytes = opts.MaxHeaderBytes
270 server.Protocols = opts.Protocols
271 server.StrictSNIHost = opts.StrictSNIHost
272 + server.Metrics = opts.Metrics
273 if opts.ShouldLogCredentials {
274 if server.Logs == nil {
275 server.Logs = &caddyhttp.ServerLogConfig{}
modules/caddyhttp/app.go
+1 -1
@@ -263,7 +263,7 @@ func (app *App) Provision(ctx caddy.Context) error {
263 // route handler so that important security checks are done, etc.
264 primaryRoute := emptyHandler
265 if srv.Routes != nil {
266 - err := srv.Routes.ProvisionHandlers(ctx)
266 + err := srv.Routes.ProvisionHandlers(ctx, srv.Metrics)
267 if err != nil {
268 return fmt.Errorf("server %s: setting up route handlers: %v", srvName, err)
269 }
modules/caddyhttp/metrics.go
+4
@@ -11,6 +11,10 @@ import (
11 "github.com/prometheus/client_golang/prometheus/promauto"
12 )
13
14 +// Metrics configures metrics observations.
15 +// EXPERIMENTAL and subject to change or removal.
16 +type Metrics struct{}
17 +
18 var httpMetrics = struct {
19 init sync.Once
20 requestInFlight *prometheus.GaugeVec
modules/caddyhttp/routes.go
+10 -7
@@ -130,7 +130,7 @@ func (routes RouteList) Provision(ctx caddy.Context) error {
130 if err != nil {
131 return err
132 }
133 - return routes.ProvisionHandlers(ctx)
133 + return routes.ProvisionHandlers(ctx, nil)
134 }
135
136 // ProvisionMatchers sets up all the matchers by loading the
@@ -156,7 +156,7 @@ func (routes RouteList) ProvisionMatchers(ctx caddy.Context) error {
156 // handler modules. Only call this method directly if you need
157 // to set up matchers and handlers separately without having
158 // to provision a second time; otherwise use Provision instead.
159 -func (routes RouteList) ProvisionHandlers(ctx caddy.Context) error {
159 +func (routes RouteList) ProvisionHandlers(ctx caddy.Context, metrics *Metrics) error {
160 for i := range routes {
161 handlersIface, err := ctx.LoadModule(&routes[i], "HandlersRaw")
162 if err != nil {
@@ -168,7 +168,7 @@ func (routes RouteList) ProvisionHandlers(ctx caddy.Context) error {
168
169 // pre-compile the middleware handler chain
170 for _, midhandler := range routes[i].Handlers {
171 - routes[i].middleware = append(routes[i].middleware, wrapMiddleware(ctx, midhandler))
171 + routes[i].middleware = append(routes[i].middleware, wrapMiddleware(ctx, midhandler, metrics))
172 }
173 }
174 return nil
@@ -270,9 +270,12 @@ func wrapRoute(route Route) Middleware {
270 // we need to pull this particular MiddlewareHandler
271 // pointer into its own stack frame to preserve it so it
272 // won't be overwritten in future loop iterations.
273 -func wrapMiddleware(ctx caddy.Context, mh MiddlewareHandler) Middleware {
274 - // wrap the middleware with metrics instrumentation
275 - metricsHandler := newMetricsInstrumentedHandler(caddy.GetModuleName(mh), mh)
273 +func wrapMiddleware(ctx caddy.Context, mh MiddlewareHandler, metrics *Metrics) Middleware {
274 + handlerToUse := mh
275 + if metrics != nil {
276 + // wrap the middleware with metrics instrumentation
277 + handlerToUse = newMetricsInstrumentedHandler(caddy.GetModuleName(mh), mh)
278 + }
279
280 return func(next Handler) Handler {
281 // copy the next handler (it's an interface, so it's
@@ -284,7 +287,7 @@ func wrapMiddleware(ctx caddy.Context, mh MiddlewareHandler) Middleware {
287 return HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
288 // TODO: This is where request tracing could be implemented
289 // TODO: see what the std lib gives us in terms of stack tracing too
287 - return metricsHandler.ServeHTTP(w, r, nextCopy)
290 + return handlerToUse.ServeHTTP(w, r, nextCopy)
291 })
292 }
293 }
modules/caddyhttp/server.go
+4
@@ -152,6 +152,10 @@ type Server struct {
152 // Default: `[h1 h2 h3]`
153 Protocols []string `json:"protocols,omitempty"`
154
155 + // If set, metrics observations will be enabled.
156 + // This setting is EXPERIMENTAL and subject to change.
157 + Metrics *Metrics `json:"metrics,omitempty"`
158 +
159 name string
160
161 primaryHandlerChain Handler