forked from torbensky/go-logfilter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
logfilter.go
92 lines (75 loc) · 2.3 KB
/
logfilter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package logfilter
import (
"path/filepath"
"strings"
"sync"
"github.com/sirupsen/logrus"
)
type LogFilter struct {
config *sync.Map // thread safe map, from reading sounds like this should be more efficient than manually managing a mutex
fileCache *sync.Map // thread safe map, from reading sounds like this should be more efficient than manually managing a mutex
UseCache bool // whether or not to use a cache of filenames seen and the log levels found
}
func NewLogFilter() *LogFilter {
return &LogFilter{
config: &sync.Map{},
fileCache: &sync.Map{},
UseCache: true,
}
}
/*
Sets a log level for a path
*/
func (lf *LogFilter) SetLevel(level logrus.Level, path string) {
lf.config.Store(path, level)
if !lf.UseCache {
return
}
// Bust the cache
lf.fileCache.Range(func(f, v interface{}) bool {
// A simple and aggressive prune, eliminating any possible match. Should at least be a superset of items affected by the new level setting.
if strings.Contains(f.(string), path) {
lf.fileCache.Delete(f)
}
return true
})
}
/*
Sets a log level for each path provided
*/
func (lf *LogFilter) SetLevels(level logrus.Level, paths ...string) {
for _, p := range paths {
lf.SetLevel(level, p)
}
}
/*
Gets the "best" matching log level matching the given file. "best" in this case means the first file match it finds or any directory match.
Defaults to InfoLevel when no match is found
When multiple matches are possible, this will behave non-deterministically. This is based on the underlying map behavior.
*/
func (lf *LogFilter) GetFileLevel(file string) logrus.Level {
// Check if we already know the level for this file
cached, ok := lf.fileCache.Load(file)
if ok {
return cached.(logrus.Level)
}
level := logrus.InfoLevel // default level if we don't find a match
dir := filepath.Dir(file)
lf.config.Range(func(k, v interface{}) bool {
// If we match a file exactly, immediately return
if strings.HasSuffix(file, k.(string)) {
level = v.(logrus.Level)
return false
}
// If we find a directory match, just remember it in case we don't find a file match
if strings.Contains(dir, k.(string)) {
level = v.(logrus.Level)
}
return true
})
// Cache this result for faster lookup next time
if lf.UseCache {
lf.fileCache.Store(file, level)
}
return level
}