-
Notifications
You must be signed in to change notification settings - Fork 1
/
level_set.go
120 lines (106 loc) · 3.49 KB
/
level_set.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package logger
import (
"fmt"
"regexp"
"strings"
"github.com/gildas/go-core"
)
// LevelSet is a set of levels organized by topic and scope
type LevelSet map[topicscope]Level
// NewLevelSet creates a new LevelSet with a default level
func NewLevelSet(defaultLevel Level) (levels LevelSet) {
levels = LevelSet{}
levels.SetDefault(defaultLevel)
return
}
// ParseLevelsFromEnvironment parses the levels from the environment variable LOG_LEVEL
//
// If LOG_LEVEL is not set, it will return a LevelSet with the default level (INFO)
//
// If the environment variable DEBUG is set to 1 (or yes, on, true), the default level in the LevelSet will be DEBUG
func ParseLevelsFromEnvironment() (levels LevelSet) {
levels = ParseLevels(core.GetEnvAsString("LOG_LEVEL", "INFO"))
if core.GetEnvAsBool("DEBUG", false) {
if levels.Get("any", "any") > DEBUG {
levels.Set(DEBUG, "any", "any")
}
}
return
}
// ParseLevels parses a string and returns a LevelSet
func ParseLevels(settings string) (levels LevelSet) {
levels = LevelSet{}
if len(settings) == 0 {
levels.Set(INFO, "any", "any")
return
}
// Pattern to match a list of topic/scope levels
// See: https://regex101.com/r/GFjOje/1
var (
pattern = regexp.MustCompile(`\s*(?P<LEVEL>[a-zA-Z]+)(?::\{(?P<TOPIC>\w+)?(?::(?P<SCOPES>\w+\s*(?:,\s*\w+)?))?\})?\s*(?:;\s*|$)`)
matches = pattern.FindAllStringSubmatch(settings, -1)
levelGroup = pattern.SubexpIndex("LEVEL")
topicGroup = pattern.SubexpIndex("TOPIC")
scopesGroup = pattern.SubexpIndex("SCOPES")
)
for _, match := range matches {
level := ParseLevel(match[levelGroup])
topic := match[topicGroup]
scopes := strings.Split(match[scopesGroup], ",")
for _, scope := range scopes {
levels.Set(level, topic, strings.TrimSpace(scope))
}
}
return
}
// GetDefault gets the default level
func (levels LevelSet) GetDefault() Level {
return levels.Get("any", "any")
}
// SetDefault sets the level for any topic and any scope
func (set *LevelSet) SetDefault(level Level) {
set.Set(level, "any", "any")
}
// Set sets the level for a given topic,scope pair
func (set *LevelSet) Set(level Level, topic, scope string) {
if *set == nil {
*set = LevelSet{}
}
(*set)[newTopicscope(topic, scope)] = level
}
// Get returns the level for a given topic,scope pair
func (set LevelSet) Get(topic, scope string) (level Level) {
if len(set) == 0 {
return UNSET
}
if level, found := set[newTopicscope(topic, scope)]; found {
return level
}
// We search topic:any first, as topics are higher on the foodchain
if level, found := set[newTopicscope(topic, "any")]; found {
return level
}
if level, found := set[newTopicscope("any", scope)]; found {
return level
}
return set[newTopicscope("any", "any")]
}
// ShouldWrite Tells if the given Level, Topic, and Scope should be written
func (set LevelSet) ShouldWrite(level Level, topic, scope string) bool {
return level.ShouldWrite(set.Get(topic, scope))
}
func (set LevelSet) String() string {
values := []string{}
for topicscope, level := range set {
if topicscope.Topic == "any" && topicscope.Scope == "any" {
values = append(values, level.String())
} else if topicscope.Topic == "any" {
values = append(values, fmt.Sprintf("%s:{:%s}", level.String(), topicscope.Scope))
} else if topicscope.Scope == "any" {
values = append(values, fmt.Sprintf("%s:{%s}", level.String(), topicscope.Topic))
} else {
values = append(values, fmt.Sprintf("%s:{%s:%s}", level.String(), topicscope.Topic, topicscope.Scope))
}
}
return strings.Join(values, ";")
}