@marcel91200 / caddy Mirror · read-only / commits / 9ba99914
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 12, 12:00 UTC

caddyhttp: Trace individual middleware handlers (#6313)

* caddyhttp: Trace individual middleware handlers * Fix typo

Matt Holt committed May 18, 2024 at 14:48 UTC 9ba999141b5ca5adaf45893992f4889629f77a9d
5 files changed +41 -35
caddyconfig/httpcaddyfile/serveroptions.go
+13 -33
@@ -50,6 +50,7 @@ type serverOptions struct {
50 ClientIPHeaders []string
51 ShouldLogCredentials bool
52 Metrics *caddyhttp.Metrics
53 + Trace bool // TODO: EXPERIMENTAL
54 }
55
56 func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
@@ -246,39 +247,11 @@ func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
247 }
248 serverOpts.Metrics = new(caddyhttp.Metrics)
249
249 - // TODO: DEPRECATED. (August 2022)
250 - case "protocol":
251 - caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol sub-option will be removed soon")
252 -
253 - for nesting := d.Nesting(); d.NextBlock(nesting); {
254 - switch d.Val() {
255 - case "allow_h2c":
256 - caddy.Log().Named("caddyfile").Warn("DEPRECATED: allow_h2c will be removed soon; use protocols option instead")
257 -
258 - if d.NextArg() {
259 - return nil, d.ArgErr()
260 - }
261 - if sliceContains(serverOpts.Protocols, "h2c") {
262 - return nil, d.Errf("protocol h2c already specified")
263 - }
264 - serverOpts.Protocols = append(serverOpts.Protocols, "h2c")
265 -
266 - case "strict_sni_host":
267 - caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol > strict_sni_host in this position will be removed soon; move up to the servers block instead")
268 -
269 - if d.NextArg() && d.Val() != "insecure_off" && d.Val() != "on" {
270 - return nil, d.Errf("strict_sni_host only supports 'on' or 'insecure_off', got '%s'", d.Val())
271 - }
272 - boolVal := true
273 - if d.Val() == "insecure_off" {
274 - boolVal = false
275 - }
276 - serverOpts.StrictSNIHost = &boolVal
277 -
278 - default:
279 - return nil, d.Errf("unrecognized protocol option '%s'", d.Val())
280 - }
250 + case "trace":
251 + if d.NextArg() {
252 + return nil, d.ArgErr()
253 }
254 + serverOpts.Trace = true
255
256 default:
257 return nil, d.Errf("unrecognized servers option '%s'", d.Val())
@@ -351,10 +324,17 @@ func applyServerOptions(
324 server.Metrics = opts.Metrics
325 if opts.ShouldLogCredentials {
326 if server.Logs == nil {
354 - server.Logs = &caddyhttp.ServerLogConfig{}
327 + server.Logs = new(caddyhttp.ServerLogConfig)
328 }
329 server.Logs.ShouldLogCredentials = opts.ShouldLogCredentials
330 }
331 + if opts.Trace {
332 + // TODO: THIS IS EXPERIMENTAL (MAY 2024)
333 + if server.Logs == nil {
334 + server.Logs = new(caddyhttp.ServerLogConfig)
335 + }
336 + server.Logs.Trace = opts.Trace
337 + }
338
339 if opts.Name != "" {
340 nameReplacements[key] = opts.Name
modules/caddyhttp/app.go
+3
@@ -198,6 +198,9 @@ func (app *App) Provision(ctx caddy.Context) error {
198 // only enable access logs if configured
199 if srv.Logs != nil {
200 srv.accessLogger = app.logger.Named("log.access")
201 + if srv.Logs.Trace {
202 + srv.traceLogger = app.logger.Named("log.trace")
203 + }
204 }
205
206 // the Go standard library does not let us serve only HTTP/2 using
modules/caddyhttp/logging.go
+11
@@ -65,6 +65,17 @@ type ServerLogConfig struct {
65 // and this includes some request and response headers, i.e `Cookie`,
66 // `Set-Cookie`, `Authorization`, and `Proxy-Authorization`.
67 ShouldLogCredentials bool `json:"should_log_credentials,omitempty"`
68 +
69 + // Log each individual handler that is invoked.
70 + // Requires that the log emit at DEBUG level.
71 + //
72 + // NOTE: This may log the configuration of your
73 + // HTTP handler modules; do not enable this in
74 + // insecure contexts when there is sensitive
75 + // data in the configuration.
76 + //
77 + // EXPERIMENTAL: Subject to change or removal.
78 + Trace bool `json:"trace,omitempty"`
79 }
80
81 // wrapLogger wraps logger in one or more logger named
modules/caddyhttp/routes.go
+4 -2
@@ -326,8 +326,10 @@ func wrapMiddleware(_ caddy.Context, mh MiddlewareHandler, metrics *Metrics) Mid
326 nextCopy := next
327
328 return HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
329 - // TODO: This is where request tracing could be implemented
330 - // TODO: see what the std lib gives us in terms of stack tracing too
329 + // EXPERIMENTAL: Trace each module that gets invoked
330 + if server, ok := r.Context().Value(ServerCtxKey).(*Server); ok && server != nil {
331 + server.logTrace(handlerToUse)
332 + }
333 return handlerToUse.ServeHTTP(w, r, nextCopy)
334 })
335 }
modules/caddyhttp/server.go
+10
@@ -234,6 +234,7 @@ type Server struct {
234 logger *zap.Logger
235 accessLogger *zap.Logger
236 errorLogger *zap.Logger
237 + traceLogger *zap.Logger
238 ctx caddy.Context
239
240 server *http.Server
@@ -738,6 +739,15 @@ func (s *Server) shouldLogRequest(r *http.Request) bool {
739 return !s.Logs.SkipUnmappedHosts
740 }
741
742 +// logTrace will log that this middleware handler is being invoked.
743 +// It emits at DEBUG level.
744 +func (s *Server) logTrace(mh MiddlewareHandler) {
745 + if s.Logs == nil || !s.Logs.Trace {
746 + return
747 + }
748 + s.traceLogger.Debug(caddy.GetModuleName(mh), zap.Any("module", mh))
749 +}
750 +
751 // logRequest logs the request to access logs, unless skipped.
752 func (s *Server) logRequest(
753 accLog *zap.Logger, r *http.Request, wrec ResponseRecorder, duration *time.Duration,