From 10db57027df6925c1afc82db1e7ddd0ff2cc53a2 Mon Sep 17 00:00:00 2001 From: Matt Holt Date: Tue, 28 Apr 2020 08:32:04 -0600 Subject: caddyhttp: General improvements to access logging (#3301) * httpcaddyfile: Exclude access logs written to files from default log Even though any logs can just be ignored, most users don't seem to like configuring an access log to go to a file only to have it doubly appear in the default log. Related to: - #3294 - https://caddy.community/t/v2-logging-format/7642/4?u=matt - https://caddy.community/t/caddyfile-questions/7651/3?u=matt * caddyhttp: General improvements to access log controls (fixes #3310) * caddyhttp: Move log config nil check higher * Rename LoggerName -> DefaultLoggerName --- modules/caddyhttp/server.go | 53 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 9 deletions(-) (limited to 'modules/caddyhttp/server.go') diff --git a/modules/caddyhttp/server.go b/modules/caddyhttp/server.go index 29a1d2b..fb30f0d 100644 --- a/modules/caddyhttp/server.go +++ b/modules/caddyhttp/server.go @@ -101,9 +101,9 @@ type Server struct { // client authentication. StrictSNIHost *bool `json:"strict_sni_host,omitempty"` - // Customizes how access logs are handled in this server. To - // minimally enable access logs, simply set this to a non-null, - // empty struct. + // Enables access logging and configures how access logs are handled + // in this server. To minimally enable access logs, simply set this + // to a non-null, empty struct. Logs *ServerLogConfig `json:"logs,omitempty"` // Enable experimental HTTP/3 support. Note that HTTP/3 is not a @@ -157,7 +157,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { loggableReq, ) - if s.accessLogger != nil { + if s.shouldLogRequest(r) { wrec := NewResponseRecorder(w, nil, nil) w = wrec @@ -390,17 +390,52 @@ func (*HTTPErrorConfig) WithError(r *http.Request, err error) *http.Request { return r } -// ServerLogConfig describes a server's logging configuration. +// shouldLogRequest returns true if this request should be logged. +func (s *Server) shouldLogRequest(r *http.Request) bool { + if s.accessLogger == nil || s.Logs == nil { + // logging is disabled + return false + } + for _, dh := range s.Logs.SkipHosts { + // logging for this particular host is disabled + if r.Host == dh { + return false + } + } + if _, ok := s.Logs.LoggerNames[r.Host]; ok { + // this host is mapped to a particular logger name + return true + } + if s.Logs.SkipUnmappedHosts { + // this host is not mapped and thus must not be logged + return false + } + return true +} + +// ServerLogConfig describes a server's logging configuration. If +// enabled without customization, all requests to this server are +// logged to the default logger; logger destinations may be +// customized per-request-host. type ServerLogConfig struct { - // The logger name for all logs emitted by this server unless - // the hostname is found in the LoggerNames (logger_names) map. - LoggerName string `json:"log_name,omitempty"` + // The default logger name for all logs emitted by this server for + // hostnames that are not in the LoggerNames (logger_names) map. + DefaultLoggerName string `json:"default_logger_name,omitempty"` // LoggerNames maps request hostnames to a custom logger name. // For example, a mapping of "example.com" to "example" would // cause access logs from requests with a Host of example.com // to be emitted by a logger named "http.log.access.example". LoggerNames map[string]string `json:"logger_names,omitempty"` + + // By default, all requests to this server will be logged if + // access logging is enabled. This field lists the request + // hosts for which access logging should be disabled. + SkipHosts []string `json:"skip_hosts,omitempty"` + + // If true, requests to any host not appearing in the + // LoggerNames (logger_names) map will not be logged. + SkipUnmappedHosts bool `json:"skip_unmapped_hosts,omitempty"` } // wrapLogger wraps logger in a logger named according to user preferences for the given host. @@ -415,7 +450,7 @@ func (slc ServerLogConfig) getLoggerName(host string) string { if loggerName, ok := slc.LoggerNames[host]; ok { return loggerName } - return slc.LoggerName + return slc.DefaultLoggerName } // errLogValues inspects err and returns the status code -- cgit v1.2.3