-
Notifications
You must be signed in to change notification settings - Fork 110
/
logger_registry.go
205 lines (176 loc) · 5.37 KB
/
logger_registry.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package logging
import (
"fmt"
"regexp"
"sync"
)
type loggerRegistry struct {
mu sync.RWMutex
loggers map[string]Logger
logConfig []LoggerPatternConfig
}
// TODO(RSDK-8250): convert loggerManager from global variable to variable on local robot.
var globalLoggerRegistry = newLoggerRegistry()
func newLoggerRegistry() *loggerRegistry {
return &loggerRegistry{
loggers: make(map[string]Logger),
}
}
func (lr *loggerRegistry) registerLogger(name string, logger Logger) {
lr.mu.Lock()
defer lr.mu.Unlock()
lr.loggers[name] = logger
}
func (lr *loggerRegistry) deregisterLogger(name string) bool {
lr.mu.Lock()
defer lr.mu.Unlock()
_, ok := lr.loggers[name]
if ok {
delete(lr.loggers, name)
}
return ok
}
func (lr *loggerRegistry) loggerNamed(name string) (logger Logger, ok bool) {
lr.mu.RLock()
defer lr.mu.RUnlock()
logger, ok = lr.loggers[name]
return
}
func (lr *loggerRegistry) updateLoggerLevelWithCfg(name string) error {
lr.mu.RLock()
defer lr.mu.RUnlock()
for _, lpc := range lr.logConfig {
r, err := regexp.Compile(buildRegexFromPattern(lpc.Pattern))
if err != nil {
return err
}
if r.MatchString(name) {
logger, ok := lr.loggers[name]
if !ok {
return fmt.Errorf("logger named %s not recognized", name)
}
level, err := LevelFromString(lpc.Level)
if err != nil {
return err
}
logger.SetLevel(level)
}
}
return nil
}
func (lr *loggerRegistry) updateLoggerLevel(name string, level Level) error {
lr.mu.RLock()
defer lr.mu.RUnlock()
logger, ok := lr.loggers[name]
if !ok {
return fmt.Errorf("logger named %s not recognized", name)
}
logger.SetLevel(level)
return nil
}
func (lr *loggerRegistry) updateLoggerRegistry(logConfig []LoggerPatternConfig) error {
appliedConfigs := make(map[string]Level)
for _, lpc := range logConfig {
if !validatePattern(lpc.Pattern) {
logger := GetOrNewLogger("rdk.logging")
logger.Info("failed to validate a pattern", "pattern", lpc.Pattern)
continue
}
r, err := regexp.Compile(buildRegexFromPattern(lpc.Pattern))
if err != nil {
return err
}
for _, name := range lr.getRegisteredLoggerNames() {
if r.MatchString(name) {
level, err := LevelFromString(lpc.Level)
if err != nil {
return err
}
appliedConfigs[name] = level
}
}
}
for _, name := range lr.getRegisteredLoggerNames() {
level, ok := appliedConfigs[name]
if !ok {
level = INFO
}
err := lr.updateLoggerLevel(name, level)
if err != nil {
return err
}
}
return nil
}
func (lr *loggerRegistry) getRegisteredLoggerNames() []string {
lr.mu.RLock()
defer lr.mu.RUnlock()
registeredNames := make([]string, 0, len(globalLoggerRegistry.loggers))
for name := range lr.loggers {
registeredNames = append(registeredNames, name)
}
return registeredNames
}
func (lr *loggerRegistry) registerConfig(logConfig []LoggerPatternConfig) error {
lr.mu.Lock()
lr.logConfig = logConfig
lr.mu.Unlock()
return lr.updateLoggerRegistry(logConfig)
}
func (lr *loggerRegistry) getCurrentConfig() []LoggerPatternConfig {
lr.mu.RLock()
defer lr.mu.RUnlock()
return lr.logConfig
}
// Exported Functions specifically for use on global logger manager.
// RegisterLogger registers a new logger with a given name.
func RegisterLogger(name string, logger Logger) {
globalLoggerRegistry.registerLogger(name, logger)
}
// DeregisterLogger attempts to remove a logger from the registry and returns a boolean denoting whether it succeeded.
func DeregisterLogger(name string) bool {
return globalLoggerRegistry.deregisterLogger(name)
}
// LoggerNamed returns logger with specified name if exists.
func LoggerNamed(name string) (logger Logger, ok bool) {
return globalLoggerRegistry.loggerNamed(name)
}
// UpdateLoggerLevel assigns level to appropriate logger in the registry.
func UpdateLoggerLevel(name string, level Level) error {
return globalLoggerRegistry.updateLoggerLevel(name, level)
}
// GetRegisteredLoggerNames returns the names of all loggers in the registry.
func GetRegisteredLoggerNames() []string {
return globalLoggerRegistry.getRegisteredLoggerNames()
}
// RegisterConfig atomically stores the current known logger config in the registry, and updates all registered loggers.
func RegisterConfig(logConfig []LoggerPatternConfig) error {
return globalLoggerRegistry.registerConfig(logConfig)
}
// UpdateLoggerLevelWithCfg matches the desired logger to all patterns in the registry and updates its level.
func UpdateLoggerLevelWithCfg(name string) error {
return globalLoggerRegistry.updateLoggerLevelWithCfg(name)
}
// GetCurrentConfig returns the logger config currently being used by the registry.
func GetCurrentConfig() []LoggerPatternConfig {
return globalLoggerRegistry.getCurrentConfig()
}
// GetOrNewLogger returns a logger with the specified name if it exists, otherwise it
// creates and registers one with the same name.
// Consider removing this as a part of or after RSDK-8291 (https://viam.atlassian.net/browse/RSDK-8291)
// which may consolidate various calls to the rdk.networking logger into one.
func GetOrNewLogger(name string) (logger Logger) {
globalLoggerRegistry.mu.Lock()
defer globalLoggerRegistry.mu.Unlock()
logger, ok := globalLoggerRegistry.loggers[name]
if !ok {
logger = &impl{
name: name,
level: NewAtomicLevelAt(INFO),
appenders: []Appender{NewStdoutAppender()},
testHelper: func() {},
}
globalLoggerRegistry.loggers[name] = logger
}
return logger
}