Merge pull request 'adding locks for thread safety' (#4) from threadSafe into master

Reviewed-on: #4
This commit is contained in:
Sarah Jamie Lewis 2021-09-09 21:48:00 +00:00
commit 48705b04d3
1 changed files with 23 additions and 0 deletions

23
log.go
View File

@ -6,6 +6,7 @@ import (
"os"
"runtime"
"strings"
"sync"
)
// Level indicates the level a log should be classified at
@ -60,6 +61,7 @@ var levelColor = map[Level]func(...interface{})string {LevelDebug: Debug, LevelI
// privacyFilters by default apply all functions to printf args and add warnings to them for matches
// privacyFilterReplace obscures any matches from the privacy filter functions
type Logger struct {
lock sync.Mutex // ensures atomic writes; protects the following fields
logger *golog.Logger
level Level
useColor bool
@ -85,10 +87,13 @@ func NewFile(level Level, filename string) (*Logger, error) {
return &Logger{logger: golog.New(logfile, "", golog.Ldate|golog.Ltime), level: level, useColor: false, everythingFromPatterns: make([]string, 0), nothingExceptPatterns: make([]string, 0), privacyFilers: make([]func(string)bool, 0), privacyFilterReplace: false}, nil
}
var stdLock sync.Mutex
var std = New(LevelWarn)
// SetStd sets the default logger all other functions use
func SetStd(logger *Logger) {
stdLock.Lock()
defer stdLock.Unlock()
std = logger
}
@ -131,34 +136,48 @@ func (l *Logger) aboveLevel(level Level) bool {
// SetLevel adjusts the output filter by logging level
func (l *Logger) SetLevel(level Level) {
l.lock.Lock()
defer l.lock.Unlock()
l.level = level
}
// SetUseColor toggles weather color output is used
func (l *Logger) SetUseColor(useColor bool) {
l.lock.Lock()
defer l.lock.Unlock()
l.useColor = useColor
}
// AddNothingExceptFilter enables strong filtering showing logs only for things on the approved list, adding this pattern to the list
func (l *Logger) AddNothingExceptFilter(pattern string) {
l.lock.Lock()
defer l.lock.Unlock()
l.nothingExceptPatterns = append(l.nothingExceptPatterns, pattern)
}
// AddEverythingFromPattern adds a pattern to skip log level filtering, guaranteeing all logs matching the pattern are seen
func (l *Logger) AddEverythingFromPattern(pattern string) {
l.lock.Lock()
defer l.lock.Unlock()
l.everythingFromPatterns = append(l.everythingFromPatterns, pattern)
}
// ExcludeFromPattern adds a pattern to exclude logs from
func (l *Logger) ExcludeFromPattern(pattern string) {
l.lock.Lock()
defer l.lock.Unlock()
l.excludeFromPatterns = append(l.excludeFromPatterns, pattern)
}
func (l *Logger) AddPrivacyFilter(fn func(string)bool) {
l.lock.Lock()
defer l.lock.Unlock()
l.privacyFilers = append(l.privacyFilers, fn)
}
func (l *Logger) SetPrivacyFilterReplace(b bool) {
l.lock.Lock()
defer l.lock.Unlock()
l.privacyFilterReplace = b
}
@ -215,6 +234,8 @@ func (l *Logger) privacyFilter(v ...interface{}) []interface{} {
// Printf outputs the format and variables, assuming it passes the filter levels
func (l *Logger) Printf(level Level, format string, v ...interface{}) {
l.lock.Lock()
defer l.lock.Unlock()
if l.filter(level) {
l.logger.Output(3, l.header(level)+fmt.Sprintf(format, l.privacyFilter(v...)...))
}
@ -222,6 +243,8 @@ func (l *Logger) Printf(level Level, format string, v ...interface{}) {
// Println outputs the variables assuming the filter levels are passed
func (l *Logger) Println(level Level, v ...interface{}) {
l.lock.Lock()
defer l.lock.Unlock()
if l.filter(level) {
l.logger.Output(3, l.header(level)+fmt.Sprintln(v...))
}