mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-27 06:03:48 +03:00
caddyhttp: Trace individual middleware handlers (#6313)
* caddyhttp: Trace individual middleware handlers * Fix typo
This commit is contained in:
parent
f98f449f05
commit
9ba999141b
5 changed files with 41 additions and 35 deletions
|
@ -50,6 +50,7 @@ type serverOptions struct {
|
||||||
ClientIPHeaders []string
|
ClientIPHeaders []string
|
||||||
ShouldLogCredentials bool
|
ShouldLogCredentials bool
|
||||||
Metrics *caddyhttp.Metrics
|
Metrics *caddyhttp.Metrics
|
||||||
|
Trace bool // TODO: EXPERIMENTAL
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
|
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
|
||||||
|
@ -246,39 +247,11 @@ func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
|
||||||
}
|
}
|
||||||
serverOpts.Metrics = new(caddyhttp.Metrics)
|
serverOpts.Metrics = new(caddyhttp.Metrics)
|
||||||
|
|
||||||
// TODO: DEPRECATED. (August 2022)
|
case "trace":
|
||||||
case "protocol":
|
|
||||||
caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol sub-option will be removed soon")
|
|
||||||
|
|
||||||
for nesting := d.Nesting(); d.NextBlock(nesting); {
|
|
||||||
switch d.Val() {
|
|
||||||
case "allow_h2c":
|
|
||||||
caddy.Log().Named("caddyfile").Warn("DEPRECATED: allow_h2c will be removed soon; use protocols option instead")
|
|
||||||
|
|
||||||
if d.NextArg() {
|
if d.NextArg() {
|
||||||
return nil, d.ArgErr()
|
return nil, d.ArgErr()
|
||||||
}
|
}
|
||||||
if sliceContains(serverOpts.Protocols, "h2c") {
|
serverOpts.Trace = true
|
||||||
return nil, d.Errf("protocol h2c already specified")
|
|
||||||
}
|
|
||||||
serverOpts.Protocols = append(serverOpts.Protocols, "h2c")
|
|
||||||
|
|
||||||
case "strict_sni_host":
|
|
||||||
caddy.Log().Named("caddyfile").Warn("DEPRECATED: protocol > strict_sni_host in this position will be removed soon; move up to the servers block instead")
|
|
||||||
|
|
||||||
if d.NextArg() && d.Val() != "insecure_off" && d.Val() != "on" {
|
|
||||||
return nil, d.Errf("strict_sni_host only supports 'on' or 'insecure_off', got '%s'", d.Val())
|
|
||||||
}
|
|
||||||
boolVal := true
|
|
||||||
if d.Val() == "insecure_off" {
|
|
||||||
boolVal = false
|
|
||||||
}
|
|
||||||
serverOpts.StrictSNIHost = &boolVal
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, d.Errf("unrecognized protocol option '%s'", d.Val())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, d.Errf("unrecognized servers option '%s'", d.Val())
|
return nil, d.Errf("unrecognized servers option '%s'", d.Val())
|
||||||
|
@ -351,10 +324,17 @@ func applyServerOptions(
|
||||||
server.Metrics = opts.Metrics
|
server.Metrics = opts.Metrics
|
||||||
if opts.ShouldLogCredentials {
|
if opts.ShouldLogCredentials {
|
||||||
if server.Logs == nil {
|
if server.Logs == nil {
|
||||||
server.Logs = &caddyhttp.ServerLogConfig{}
|
server.Logs = new(caddyhttp.ServerLogConfig)
|
||||||
}
|
}
|
||||||
server.Logs.ShouldLogCredentials = opts.ShouldLogCredentials
|
server.Logs.ShouldLogCredentials = opts.ShouldLogCredentials
|
||||||
}
|
}
|
||||||
|
if opts.Trace {
|
||||||
|
// TODO: THIS IS EXPERIMENTAL (MAY 2024)
|
||||||
|
if server.Logs == nil {
|
||||||
|
server.Logs = new(caddyhttp.ServerLogConfig)
|
||||||
|
}
|
||||||
|
server.Logs.Trace = opts.Trace
|
||||||
|
}
|
||||||
|
|
||||||
if opts.Name != "" {
|
if opts.Name != "" {
|
||||||
nameReplacements[key] = opts.Name
|
nameReplacements[key] = opts.Name
|
||||||
|
|
|
@ -198,6 +198,9 @@ func (app *App) Provision(ctx caddy.Context) error {
|
||||||
// only enable access logs if configured
|
// only enable access logs if configured
|
||||||
if srv.Logs != nil {
|
if srv.Logs != nil {
|
||||||
srv.accessLogger = app.logger.Named("log.access")
|
srv.accessLogger = app.logger.Named("log.access")
|
||||||
|
if srv.Logs.Trace {
|
||||||
|
srv.traceLogger = app.logger.Named("log.trace")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the Go standard library does not let us serve only HTTP/2 using
|
// the Go standard library does not let us serve only HTTP/2 using
|
||||||
|
|
|
@ -65,6 +65,17 @@ type ServerLogConfig struct {
|
||||||
// and this includes some request and response headers, i.e `Cookie`,
|
// and this includes some request and response headers, i.e `Cookie`,
|
||||||
// `Set-Cookie`, `Authorization`, and `Proxy-Authorization`.
|
// `Set-Cookie`, `Authorization`, and `Proxy-Authorization`.
|
||||||
ShouldLogCredentials bool `json:"should_log_credentials,omitempty"`
|
ShouldLogCredentials bool `json:"should_log_credentials,omitempty"`
|
||||||
|
|
||||||
|
// Log each individual handler that is invoked.
|
||||||
|
// Requires that the log emit at DEBUG level.
|
||||||
|
//
|
||||||
|
// NOTE: This may log the configuration of your
|
||||||
|
// HTTP handler modules; do not enable this in
|
||||||
|
// insecure contexts when there is sensitive
|
||||||
|
// data in the configuration.
|
||||||
|
//
|
||||||
|
// EXPERIMENTAL: Subject to change or removal.
|
||||||
|
Trace bool `json:"trace,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrapLogger wraps logger in one or more logger named
|
// wrapLogger wraps logger in one or more logger named
|
||||||
|
|
|
@ -326,8 +326,10 @@ func wrapMiddleware(_ caddy.Context, mh MiddlewareHandler, metrics *Metrics) Mid
|
||||||
nextCopy := next
|
nextCopy := next
|
||||||
|
|
||||||
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
|
// EXPERIMENTAL: Trace each module that gets invoked
|
||||||
// TODO: see what the std lib gives us in terms of stack tracing too
|
if server, ok := r.Context().Value(ServerCtxKey).(*Server); ok && server != nil {
|
||||||
|
server.logTrace(handlerToUse)
|
||||||
|
}
|
||||||
return handlerToUse.ServeHTTP(w, r, nextCopy)
|
return handlerToUse.ServeHTTP(w, r, nextCopy)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,6 +234,7 @@ type Server struct {
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
accessLogger *zap.Logger
|
accessLogger *zap.Logger
|
||||||
errorLogger *zap.Logger
|
errorLogger *zap.Logger
|
||||||
|
traceLogger *zap.Logger
|
||||||
ctx caddy.Context
|
ctx caddy.Context
|
||||||
|
|
||||||
server *http.Server
|
server *http.Server
|
||||||
|
@ -738,6 +739,15 @@ func (s *Server) shouldLogRequest(r *http.Request) bool {
|
||||||
return !s.Logs.SkipUnmappedHosts
|
return !s.Logs.SkipUnmappedHosts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// logTrace will log that this middleware handler is being invoked.
|
||||||
|
// It emits at DEBUG level.
|
||||||
|
func (s *Server) logTrace(mh MiddlewareHandler) {
|
||||||
|
if s.Logs == nil || !s.Logs.Trace {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.traceLogger.Debug(caddy.GetModuleName(mh), zap.Any("module", mh))
|
||||||
|
}
|
||||||
|
|
||||||
// logRequest logs the request to access logs, unless skipped.
|
// logRequest logs the request to access logs, unless skipped.
|
||||||
func (s *Server) logRequest(
|
func (s *Server) logRequest(
|
||||||
accLog *zap.Logger, r *http.Request, wrec ResponseRecorder, duration *time.Duration,
|
accLog *zap.Logger, r *http.Request, wrec ResponseRecorder, duration *time.Duration,
|
||||||
|
|
Loading…
Reference in a new issue