mirror of
https://github.com/caddyserver/caddy.git
synced 2025-02-24 00:38:53 +01:00
log: 'except' subdirective to skip logging certain requests (#2028)
* proof of concept * Initial implementation with debug code * Tidy up debug code * remove unneeded import * removed extra line * Move ShouldLog function to rule entry Logger type * add tests for ShouldLog * Added tests for log exceptions * Fix logic * fix govet fail for test * Updates requested for code clarity * Update requested for style * log: Minor style tweaks to logic of log exceptions
This commit is contained in:
parent
1580169e2b
commit
1896b420d8
4 changed files with 107 additions and 1 deletions
|
@ -44,6 +44,7 @@ type Logger struct {
|
||||||
V4ipMask net.IPMask
|
V4ipMask net.IPMask
|
||||||
V6ipMask net.IPMask
|
V6ipMask net.IPMask
|
||||||
IPMaskExists bool
|
IPMaskExists bool
|
||||||
|
Exceptions []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTestLogger creates logger suitable for testing purposes
|
// NewTestLogger creates logger suitable for testing purposes
|
||||||
|
@ -84,6 +85,17 @@ func (l Logger) MaskIP(ip string) string {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShouldLog returns true if the path is not exempted from
|
||||||
|
// being logged (i.e. it is not found in l.Exceptions).
|
||||||
|
func (l Logger) ShouldLog(path string) bool {
|
||||||
|
for _, exc := range l.Exceptions {
|
||||||
|
if Path(path).Matches(exc) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Attach binds logger Start and Close functions to
|
// Attach binds logger Start and Close functions to
|
||||||
// controller's OnStartup and OnShutdown hooks.
|
// controller's OnStartup and OnShutdown hooks.
|
||||||
func (l *Logger) Attach(controller *caddy.Controller) {
|
func (l *Logger) Attach(controller *caddy.Controller) {
|
||||||
|
|
|
@ -67,6 +67,10 @@ func (l Logger) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
|
|
||||||
// Write log entries
|
// Write log entries
|
||||||
for _, e := range rule.Entries {
|
for _, e := range rule.Entries {
|
||||||
|
// Check if there is an exception to prevent log being written
|
||||||
|
if !e.Log.ShouldLog(r.URL.Path) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Mask IP Address
|
// Mask IP Address
|
||||||
if e.Log.IPMaskExists {
|
if e.Log.IPMaskExists {
|
||||||
|
@ -78,6 +82,7 @@ func (l Logger) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e.Log.Println(rep.Replace(e.Format))
|
e.Log.Println(rep.Replace(e.Format))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status, err
|
return status, err
|
||||||
|
|
|
@ -177,3 +177,85 @@ func TestMultiEntries(t *testing.T) {
|
||||||
t.Errorf("Expected %q, but got %q", expect, got)
|
t.Errorf("Expected %q, but got %q", expect, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLogExcept(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
LogRules []Rule
|
||||||
|
logPath string
|
||||||
|
shouldLog bool
|
||||||
|
}{
|
||||||
|
{[]Rule{{
|
||||||
|
PathScope: "/",
|
||||||
|
Entries: []*Entry{{
|
||||||
|
Log: &httpserver.Logger{
|
||||||
|
|
||||||
|
Exceptions: []string{"/soup"},
|
||||||
|
},
|
||||||
|
Format: DefaultLogFormat,
|
||||||
|
}},
|
||||||
|
}}, `/soup`, false},
|
||||||
|
{[]Rule{{
|
||||||
|
PathScope: "/",
|
||||||
|
Entries: []*Entry{{
|
||||||
|
Log: &httpserver.Logger{
|
||||||
|
|
||||||
|
Exceptions: []string{"/tart"},
|
||||||
|
},
|
||||||
|
Format: DefaultLogFormat,
|
||||||
|
}},
|
||||||
|
}}, `/soup`, true},
|
||||||
|
{[]Rule{{
|
||||||
|
PathScope: "/",
|
||||||
|
Entries: []*Entry{{
|
||||||
|
Log: &httpserver.Logger{
|
||||||
|
|
||||||
|
Exceptions: []string{"/soup"},
|
||||||
|
},
|
||||||
|
Format: DefaultLogFormat,
|
||||||
|
}},
|
||||||
|
}}, `/tomatosoup`, true},
|
||||||
|
{[]Rule{{
|
||||||
|
PathScope: "/",
|
||||||
|
Entries: []*Entry{{
|
||||||
|
Log: &httpserver.Logger{
|
||||||
|
|
||||||
|
Exceptions: []string{"/pie/"},
|
||||||
|
},
|
||||||
|
Format: DefaultLogFormat,
|
||||||
|
}},
|
||||||
|
// Check exception with a trailing slash does not match without
|
||||||
|
}}, `/pie`, true},
|
||||||
|
{[]Rule{{
|
||||||
|
PathScope: "/",
|
||||||
|
Entries: []*Entry{{
|
||||||
|
Log: &httpserver.Logger{
|
||||||
|
|
||||||
|
Exceptions: []string{"/pie.php"},
|
||||||
|
},
|
||||||
|
Format: DefaultLogFormat,
|
||||||
|
}},
|
||||||
|
}}, `/pie`, true},
|
||||||
|
{[]Rule{{
|
||||||
|
PathScope: "/",
|
||||||
|
Entries: []*Entry{{
|
||||||
|
Log: &httpserver.Logger{
|
||||||
|
|
||||||
|
Exceptions: []string{"/pie"},
|
||||||
|
},
|
||||||
|
Format: DefaultLogFormat,
|
||||||
|
}},
|
||||||
|
// Check that a word without trailing slash will match a filename
|
||||||
|
}}, `/pie.php`, false},
|
||||||
|
}
|
||||||
|
for i, test := range tests {
|
||||||
|
for _, LogRule := range test.LogRules {
|
||||||
|
for _, e := range LogRule.Entries {
|
||||||
|
shouldLog := e.Log.ShouldLog(test.logPath)
|
||||||
|
if shouldLog != test.shouldLog {
|
||||||
|
t.Fatalf("Test %d expected shouldLog=%t but got shouldLog=%t,", i, test.shouldLog, shouldLog)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ func setup(c *caddy.Controller) error {
|
||||||
|
|
||||||
func logParse(c *caddy.Controller) ([]*Rule, error) {
|
func logParse(c *caddy.Controller) ([]*Rule, error) {
|
||||||
var rules []*Rule
|
var rules []*Rule
|
||||||
|
var logExceptions []string
|
||||||
for c.Next() {
|
for c.Next() {
|
||||||
args := c.RemainingArgs()
|
args := c.RemainingArgs()
|
||||||
|
|
||||||
|
@ -91,6 +91,12 @@ func logParse(c *caddy.Controller) ([]*Rule, error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if what == "except" {
|
||||||
|
|
||||||
|
for i := 0; i < len(where); i++ {
|
||||||
|
logExceptions = append(logExceptions, where[i])
|
||||||
|
}
|
||||||
|
|
||||||
} else if httpserver.IsLogRollerSubdirective(what) {
|
} else if httpserver.IsLogRollerSubdirective(what) {
|
||||||
|
|
||||||
if err := httpserver.ParseRoller(logRoller, what, where...); err != nil {
|
if err := httpserver.ParseRoller(logRoller, what, where...); err != nil {
|
||||||
|
@ -133,6 +139,7 @@ func logParse(c *caddy.Controller) ([]*Rule, error) {
|
||||||
V4ipMask: ip4Mask,
|
V4ipMask: ip4Mask,
|
||||||
V6ipMask: ip6Mask,
|
V6ipMask: ip6Mask,
|
||||||
IPMaskExists: ipMaskExists,
|
IPMaskExists: ipMaskExists,
|
||||||
|
Exceptions: logExceptions,
|
||||||
},
|
},
|
||||||
Format: format,
|
Format: format,
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue