mirror of
https://github.com/go-kratos/kratos.git
synced 2025-03-21 21:27:16 +02:00
commit
864a791e04
81
log/filter.go
Normal file
81
log/filter.go
Normal file
@ -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...)
|
||||||
|
}
|
90
log/filter_test.go
Normal file
90
log/filter_test.go
Normal file
@ -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{}) {
|
func (h *Helper) Log(level Level, keyvals ...interface{}) {
|
||||||
h.logger.Log(level, keyvals...)
|
h.logger.Log(level, keyvals...)
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,13 @@ func Value(ctx context.Context, v interface{}) interface{} {
|
|||||||
func Caller(depth int) Valuer {
|
func Caller(depth int) Valuer {
|
||||||
return func(context.Context) interface{} {
|
return func(context.Context) interface{} {
|
||||||
_, file, line, _ := runtime.Caller(depth)
|
_, 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 {
|
if strings.LastIndex(file, "/log/helper.go") > 0 {
|
||||||
_, file, line, _ = runtime.Caller(depth + 1)
|
depth++
|
||||||
|
_, file, line, _ = runtime.Caller(depth)
|
||||||
}
|
}
|
||||||
idx := strings.LastIndexByte(file, '/')
|
idx := strings.LastIndexByte(file, '/')
|
||||||
return file[idx+1:] + ":" + strconv.Itoa(line)
|
return file[idx+1:] + ":" + strconv.Itoa(line)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user