Compare commits
4 Commits
Author | SHA1 | Date |
---|---|---|
Sarah Jamie Lewis | 48705b04d3 | |
Dan Ballard | 385821e4b9 | |
Sarah Jamie Lewis | 1bdcd0226b | |
Dan Ballard | 8f70fe8cda |
|
@ -8,6 +8,10 @@ A simple log primative Open Privacy uses
|
|||
log.SetLevel(log.LevelDebug)
|
||||
log.ExcludeFromPattern("connection/connection")
|
||||
log.ExcludeFromPattern("outbound/3dhauthchannel")
|
||||
log.AddPrivacyFilter(func(s string) bool {
|
||||
return len(s) == 56
|
||||
})
|
||||
log.SetPrivacyFilterReplace(true)
|
||||
|
||||
log.Debugf("Creating the thing with param %v\n", param)
|
||||
log.Infoln("Doing thing X")
|
||||
|
|
79
log.go
79
log.go
|
@ -6,6 +6,7 @@ import (
|
|||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Level indicates the level a log should be classified at
|
||||
|
@ -57,18 +58,23 @@ var levelColor = map[Level]func(...interface{})string {LevelDebug: Debug, LevelI
|
|||
// It allows allows two addition levels of filtering:
|
||||
// everythingFrom which allows inclusion of packages/patterns along with general logging
|
||||
// nothingExcept which allows focusing on just listed areas
|
||||
// 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
|
||||
nothingExceptPatterns []string
|
||||
everythingFromPatterns []string
|
||||
excludeFromPatterns []string
|
||||
privacyFilers []func(string)bool
|
||||
privacyFilterReplace bool
|
||||
}
|
||||
|
||||
// New returns a new Logger with a filter set to the supplied level
|
||||
func New(level Level) *Logger {
|
||||
return &Logger{logger: golog.New(os.Stderr, "", golog.Ldate|golog.Ltime), level: level, useColor: true, everythingFromPatterns: make([]string, 0), nothingExceptPatterns: make([]string, 0)}
|
||||
return &Logger{logger: golog.New(os.Stderr, "", golog.Ldate|golog.Ltime), level: level, useColor: true, everythingFromPatterns: make([]string, 0), nothingExceptPatterns: make([]string, 0), privacyFilers: make([]func(string)bool, 0), privacyFilterReplace: false}
|
||||
}
|
||||
|
||||
// NewFile returns a new Logger that logs to the supplied file with a filter set to the supplied level
|
||||
|
@ -78,13 +84,16 @@ func NewFile(level Level, filename string) (*Logger, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &Logger{logger: golog.New(logfile, "", golog.Ldate|golog.Ltime), level: level, useColor: false, everythingFromPatterns: make([]string, 0), nothingExceptPatterns: make([]string, 0)}, nil
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -127,29 +136,51 @@ 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
|
||||
}
|
||||
|
||||
func (l *Logger) header(level Level) string {
|
||||
_, file, _, ok := runtime.Caller(3)
|
||||
if !ok {
|
||||
|
@ -175,15 +206,45 @@ func (l *Logger) header(level Level) string {
|
|||
}
|
||||
}
|
||||
|
||||
func (l *Logger) privacyFilter(v ...interface{}) []interface{} {
|
||||
if len(l.privacyFilers) > 0 {
|
||||
for i, val := range v {
|
||||
for _, fn := range l.privacyFilers {
|
||||
switch cval := val.(type) {
|
||||
case string:
|
||||
if fn(cval) {
|
||||
if l.privacyFilterReplace {
|
||||
cval = strings.Repeat("*", len(cval))
|
||||
}
|
||||
|
||||
cval = "PRIVACY-FILTER-FLAGGED[" + cval + "]"
|
||||
|
||||
if l.useColor {
|
||||
cval = Magenta(cval)
|
||||
}
|
||||
|
||||
v[i] = cval
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// 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, v...))
|
||||
l.logger.Output(3, l.header(level)+fmt.Sprintf(format, l.privacyFilter(v...)...))
|
||||
}
|
||||
}
|
||||
|
||||
// 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...))
|
||||
}
|
||||
|
@ -214,6 +275,16 @@ func ExcludeFromPattern(pattern string) {
|
|||
std.ExcludeFromPattern(pattern)
|
||||
}
|
||||
|
||||
// AddPrivacyFilter adds a function applied to printf argument strings that can flag them as sensitive data
|
||||
func AddPrivacyFilter(fn func(string)bool) {
|
||||
std.AddPrivacyFilter(fn)
|
||||
}
|
||||
|
||||
// SetPrivacyFilterReplace replaces the string argument to printf that a Privacy Filter identified with ****s
|
||||
func SetPrivacyFilterReplace(b bool) {
|
||||
std.SetPrivacyFilterReplace(b)
|
||||
}
|
||||
|
||||
// Printf outputs the format with variables assuming it passes the filter level
|
||||
func Printf(level Level, format string, v ...interface{}) {
|
||||
std.Printf(level, format, v...)
|
||||
|
@ -262,4 +333,4 @@ func Warnln(v ...interface{}) {
|
|||
// Errorln outputs the variables at the Error level
|
||||
func Errorln(v ...interface{}) {
|
||||
std.Println(LevelError, v...)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue