Merge pull request #1053 from go-kratos/log-filter

log: logger filter
pull/1054/head
包子 4 years ago committed by GitHub
commit 864a791e04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 81
      log/filter.go
  2. 90
      log/filter_test.go
  3. 2
      log/helper.go
  4. 7
      log/value.go

@ -0,0 +1,81 @@
package log
// FilterOption is filter option.
type FilterOption func(*Filter)
// FilterLevel with filter level.
func FilterLevel(level Level) FilterOption {
return func(opts *Filter) {
opts.level = level
}
}
// FilterKey with filter key.
func FilterKey(key ...string) FilterOption {
return func(o *Filter) {
for _, v := range key {
o.key[v] = struct{}{}
}
}
}
// FilterValue with filter value.
func FilterValue(value ...string) FilterOption {
return func(o *Filter) {
for _, v := range value {
o.value[v] = struct{}{}
}
}
}
// FilterFunc with filter func.
func FilterFunc(f func(level Level, keyvals ...interface{}) bool) FilterOption {
return func(o *Filter) {
o.filter = f
}
}
// Filter is a logger filter.
type Filter struct {
logger Logger
level Level
key map[interface{}]struct{}
value map[interface{}]struct{}
filter func(level Level, keyvals ...interface{}) bool
}
// NewFilter new a logger filter.
func NewFilter(logger Logger, opts ...FilterOption) *Filter {
options := Filter{
logger: logger,
key: make(map[interface{}]struct{}),
value: make(map[interface{}]struct{}),
}
for _, o := range opts {
o(&options)
}
return &options
}
// Log Print log by level and keyvals.
func (f *Filter) Log(level Level, keyvals ...interface{}) error {
if f.level > level {
return nil
}
if f.filter != nil && f.filter(level, keyvals...) {
return nil
}
for i := 0; i < len(keyvals); i += 2 {
if _, ok := f.key[keyvals[i]]; ok {
keyvals[i+1] = "***"
}
vi := i + 1
if vi >= len(keyvals) {
continue
}
if _, ok := f.value[keyvals[vi]]; ok {
keyvals[i+1] = "***"
}
}
return f.logger.Log(level, keyvals...)
}

@ -0,0 +1,90 @@
package log
import (
"io/ioutil"
"testing"
)
func TestFilterAll(t *testing.T) {
logger := With(DefaultLogger, "ts", DefaultTimestamp, "caller", DefaultCaller)
log := NewHelper(NewFilter(logger,
FilterLevel(LevelDebug),
FilterKey("username"),
FilterValue("hello"),
FilterFunc(testFilterFunc),
))
log.Log(LevelDebug, "msg", "test debug")
log.Info("hello")
log.Infow("password", "123456")
log.Infow("username", "kratos")
log.Warn("warn log")
}
func TestFilterLevel(t *testing.T) {
logger := With(DefaultLogger, "ts", DefaultTimestamp, "caller", DefaultCaller)
log := NewHelper(NewFilter(NewFilter(logger, FilterLevel(LevelWarn))))
log.Log(LevelDebug, "msg1", "te1st debug")
log.Debug("test debug")
log.Debugf("test %s", "debug")
log.Debugw("log", "test debug")
log.Warn("warn log")
}
func TestFilterCaller(t *testing.T) {
logger := With(DefaultLogger, "ts", DefaultTimestamp, "caller", DefaultCaller)
log := NewFilter(logger)
log.Log(LevelDebug, "msg1", "te1st debug")
logHelper := NewHelper(NewFilter(logger))
logHelper.Log(LevelDebug, "msg1", "te1st debug")
}
func TestFilterKey(t *testing.T) {
logger := With(DefaultLogger, "ts", DefaultTimestamp, "caller", DefaultCaller)
log := NewHelper(NewFilter(logger, FilterKey("password")))
log.Debugw("password", "123456")
}
func TestFilterValue(t *testing.T) {
logger := With(DefaultLogger, "ts", DefaultTimestamp, "caller", DefaultCaller)
log := NewHelper(NewFilter(logger, FilterValue("debug")))
log.Debugf("test %s", "debug")
}
func TestFilterFunc(t *testing.T) {
logger := With(DefaultLogger, "ts", DefaultTimestamp, "caller", DefaultCaller)
log := NewHelper(NewFilter(logger, FilterFunc(testFilterFunc)))
log.Debug("debug level")
log.Infow("password", "123456")
}
func BenchmarkFilterKey(b *testing.B) {
log := NewHelper(NewFilter(NewStdLogger(ioutil.Discard), FilterKey("password")))
for i := 0; i < b.N; i++ {
log.Infow("password", "123456")
}
}
func BenchmarkFilterValue(b *testing.B) {
log := NewHelper(NewFilter(NewStdLogger(ioutil.Discard), FilterValue("password")))
for i := 0; i < b.N; i++ {
log.Infow("password")
}
}
func BenchmarkFilterFunc(b *testing.B) {
log := NewHelper(NewFilter(NewStdLogger(ioutil.Discard), FilterFunc(testFilterFunc)))
for i := 0; i < b.N; i++ {
log.Info("password", "123456")
}
}
func testFilterFunc(level Level, keyvals ...interface{}) bool {
if level == LevelWarn {
return true
}
for i := 0; i < len(keyvals); i++ {
if keyvals[i] == "password" {
keyvals[i+1] = "***"
}
}
return false
}

@ -25,7 +25,7 @@ func (h *Helper) WithContext(ctx context.Context) *Helper {
}
}
// Log .
// Log Print log by level and keyvals.
func (h *Helper) Log(level Level, keyvals ...interface{}) {
h.logger.Log(level, keyvals...)
}

@ -33,8 +33,13 @@ func Value(ctx context.Context, v interface{}) interface{} {
func Caller(depth int) Valuer {
return func(context.Context) interface{} {
_, file, line, _ := runtime.Caller(depth)
if strings.LastIndex(file, "/log/filter.go") > 0 {
depth++
_, file, line, _ = runtime.Caller(depth)
}
if strings.LastIndex(file, "/log/helper.go") > 0 {
_, file, line, _ = runtime.Caller(depth + 1)
depth++
_, file, line, _ = runtime.Caller(depth)
}
idx := strings.LastIndexByte(file, '/')
return file[idx+1:] + ":" + strconv.Itoa(line)

Loading…
Cancel
Save