Skip to content

Commit

Permalink
Logging: add support for additional logger filters other than hostname
Browse files Browse the repository at this point in the history
  • Loading branch information
armadi1809 committed Feb 13, 2024
1 parent 30d6364 commit 6074d06
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 12 deletions.
10 changes: 8 additions & 2 deletions caddyconfig/httpcaddyfile/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,7 @@ func parseLogHelper(h Helper, globalLogNames map[string]struct{}) ([]ConfigValue
// this is useful for setting up loggers per subdomain in a site block
// with a wildcard domain
customHostnames := []string{}

noLoggerNames := false
for h.NextBlock(0) {
switch h.Val() {
case "hostnames":
Expand Down Expand Up @@ -996,14 +996,20 @@ func parseLogHelper(h Helper, globalLogNames map[string]struct{}) ([]ConfigValue
cl.Exclude = append(cl.Exclude, h.Val())
}

case "no_hostname":
if h.NextArg() {
return nil, h.ArgErr()
}
noLoggerNames = true

default:
return nil, h.Errf("unrecognized subdirective: %s", h.Val())
}
}

var val namedCustomLog
val.hostnames = customHostnames

val.noLoggerNames = noLoggerNames
isEmptyConfig := reflect.DeepEqual(cl, new(caddy.CustomLog))

// Skip handling of empty logging configs
Expand Down
10 changes: 7 additions & 3 deletions caddyconfig/httpcaddyfile/httptype.go
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,9 @@ func (st *ServerType) serversFromPairings(
sblockLogHosts := sblock.hostsFromKeys(true)
for _, cval := range sblock.pile["custom_log"] {
ncl := cval.Value.(namedCustomLog)
if ncl.noLoggerNames {
continue
}
if sblock.hasHostCatchAllKey() && len(ncl.hostnames) == 0 {
// all requests for hosts not able to be listed should use
// this log because it's a catch-all-hosts server block
Expand Down Expand Up @@ -1580,9 +1583,10 @@ func (c counter) nextGroup() string {
}

type namedCustomLog struct {
name string
hostnames []string
log *caddy.CustomLog
name string
hostnames []string
log *caddy.CustomLog
noLoggerNames bool
}

// sbAddrAssociation is a mapping from a list of
Expand Down
129 changes: 129 additions & 0 deletions caddytest/integration/caddyfile_adapt/log_filter_with_header.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
localhost {
log {
output file ./caddy.access.log
}
log health_check_log {
output file ./caddy.access.health.log
no_hostname
}
@healthCheck `header_regexp('User-Agent', '^some-regexp$') || path('/healthz*')`
handle @healthCheck {
vars access_logger_name health_check_log
respond "Healthy"
}

handle {
respond "Hello World"
}
}
----------
{
"logging": {
"logs": {
"default": {
"exclude": [
"http.log.access.health_check_log",
"http.log.access.log0"
]
},
"health_check_log": {
"writer": {
"filename": "./caddy.access.health.log",
"output": "file"
},
"include": [
"http.log.access.health_check_log"
]
},
"log0": {
"writer": {
"filename": "./caddy.access.log",
"output": "file"
},
"include": [
"http.log.access.log0"
]
}
}
},
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":443"
],
"routes": [
{
"match": [
{
"host": [
"localhost"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"group": "group2",
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"access_logger_name": "health_check_log",
"handler": "vars"
},
{
"body": "Healthy",
"handler": "static_response"
}
]
}
]
}
],
"match": [
{
"expression": "header_regexp('User-Agent', '^some-regexp$') || path('/healthz*')"
}
]
},
{
"group": "group2",
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "Hello World",
"handler": "static_response"
}
]
}
]
}
]
}
]
}
],
"terminal": true
}
],
"logs": {
"logger_names": {
"localhost": "log0"
}
}
}
}
}
}
}
10 changes: 8 additions & 2 deletions modules/caddyhttp/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@ type ServerLogConfig struct {
}

// wrapLogger wraps logger in a logger named according to user preferences for the given host.
func (slc ServerLogConfig) wrapLogger(logger *zap.Logger, host string) *zap.Logger {
if loggerName := slc.getLoggerName(host); loggerName != "" {
func (slc ServerLogConfig) wrapLogger(logger *zap.Logger, req *http.Request) *zap.Logger {
if access_logger_name := GetVar(req.Context(), AccessLoggerNameVarKey); access_logger_name != nil {
return logger.Named(access_logger_name.(string))
}
if loggerName := slc.getLoggerName(req.Host); loggerName != "" {
return logger.Named(loggerName)
}
return logger
Expand Down Expand Up @@ -170,4 +173,7 @@ const (

// For adding additional fields to the access logs
ExtraLogFieldsCtxKey caddy.CtxKey = "extra_log_fields"

// Variable name used to indicate the logger to be used
AccessLoggerNameVarKey string = "access_logger_name"
)
11 changes: 6 additions & 5 deletions modules/caddyhttp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,6 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {

// prepare the error log
logger := errLog
if s.Logs != nil {
logger = s.Logs.wrapLogger(logger, r.Host)
}
logger = logger.With(zap.Duration("duration", duration))

// get the values that will be used to log the error
errStatus, errMsg, errFields := errLogValues(err)
Expand All @@ -382,6 +378,11 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if s.Errors != nil && len(s.Errors.Routes) > 0 {
// execute user-defined error handling route
err2 := s.errorHandlerChain.ServeHTTP(w, r)
if s.Logs != nil {
logger = s.Logs.wrapLogger(logger, r)
}
logger = logger.With(zap.Duration("duration", duration))

if err2 == nil {
// user's error route handled the error response
// successfully, so now just log the error
Expand Down Expand Up @@ -718,7 +719,7 @@ func (s *Server) logRequest(

logger := accLog
if s.Logs != nil {
logger = s.Logs.wrapLogger(logger, r.Host)
logger = s.Logs.wrapLogger(logger, r)
}

log := logger.Info
Expand Down

0 comments on commit 6074d06

Please sign in to comment.