Skip to content

Commit

Permalink
adds secrets, fix #17
Browse files Browse the repository at this point in the history
  • Loading branch information
umputun committed Nov 7, 2019
1 parent b5343dd commit 8162458
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ _Without `lgr.Caller*` it will drop `{caller}` part_
- `lgr.LevelBraces` - wraps levels with "[" and "]"
- `lgr.Msec` - adds milliseconds to timestamp
- `lgr.Format` - sets custom template, overwrite all other formatting modifiers.
- `lgr.Secret(secret ...)` - sets list of the secrets to hide from the logging outputs.

example: `l := lgr.New(lgr.Debug, lgr.Msec)`

Expand Down
11 changes: 11 additions & 0 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const (
FullDebug = `{{.DT.Format "2006/01/02 15:04:05.000"}} {{.Level}} ({{.CallerFile}}:{{.CallerLine}} {{.CallerFunc}}) {{.Message}}`
)

var secretReplacement = []byte("******")

// Logger provided simple logger with basic support of levels. Thread safe
type Logger struct {
// set with Option calls
Expand All @@ -46,6 +48,7 @@ type Logger struct {
levelBraces bool // encloses level with [], i.e. [INFO]
callerDepth int // how many stack frames to skip, relative to the real (reported) frame
format string // layout template
secrets []string // sub-strings to secrets by matching

// internal use
now nowFn
Expand Down Expand Up @@ -163,6 +166,7 @@ func (l *Logger) logf(format string, args ...interface{}) {
data = bytes.Replace(data, []byte("[WARN ]"), []byte("[WARN] "), 1)
data = bytes.Replace(data, []byte("[INFO ]"), []byte("[INFO] "), 1)
}
data = l.hideSecrets(data)

l.lock.Lock()
_, _ = l.stdout.Write(data)
Expand All @@ -189,6 +193,13 @@ func (l *Logger) logf(format string, args ...interface{}) {
l.lock.Unlock()
}

func (l *Logger) hideSecrets(data []byte) []byte {
for _, h := range l.secrets {
data = bytes.Replace(data, []byte(h), secretReplacement, -1)
}
return data
}

type callerInfo struct {
File string
Line int
Expand Down
9 changes: 9 additions & 0 deletions logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,15 @@ func TestLoggerNoSpaceLevel(t *testing.T) {
})
}
}

func TestLoggerHidden(t *testing.T) {
rout, rerr := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{})
l := New(Out(rout), Err(rerr), Format(Short), Secret("password", "secret"))
l.now = func() time.Time { return time.Date(2018, 1, 7, 13, 2, 34, 123000000, time.Local) }
l.Logf("INFO something password 123 secret xyz")
assert.Equal(t, "2018/01/07 13:02:34 INFO something ****** 123 ****** xyz\n", rout.String(), "secrets secrets")
}

func BenchmarkNoDbgNoFormat(b *testing.B) {
rout, rerr := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{})
l := New(Out(rout), Err(rerr))
Expand Down
8 changes: 8 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,11 @@ func CallerFile(l *Logger) {
func Msec(l *Logger) {
l.msec = true
}

// Secret sets list of substring to be hidden, i.e. replaced by "******"
// Useful to prevent passwords or other sensitive tokens to be logged.
func Secret(vals ...string) Option {
return func(l *Logger) {
l.secrets = vals
}
}

0 comments on commit 8162458

Please sign in to comment.