前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊klog的LogFilter

聊聊klog的LogFilter

作者头像
code4it
发布2021-01-12 14:53:24
4600
发布2021-01-12 14:53:24
举报
文章被收录于专栏:码匠的流水账码匠的流水账

本文主要研究一下klog的LogFilter

LogFilter

k8s.io/klog/v2@v2.4.0/klog.go

代码语言:javascript
复制
// LogFilter is a collection of functions that can filter all logging calls,
// e.g. for sanitization of arguments and prevent accidental leaking of secrets.
type LogFilter interface {
    Filter(args []interface{}) []interface{}
    FilterF(format string, args []interface{}) (string, []interface{})
    FilterS(msg string, keysAndValues []interface{}) (string, []interface{})
}

func SetLogFilter(filter LogFilter) {
    logging.mu.Lock()
    defer logging.mu.Unlock()

    logging.filter = filter
}

LogFilter接口定义了Filter、FilterF、FilterS方法用于过滤log

filter.Filter

k8s.io/klog/v2@v2.4.0/klog.go

代码语言:javascript
复制
func (l *loggingT) println(s severity, logr logr.Logger, filter LogFilter, args ...interface{}) {
    buf, file, line := l.header(s, 0)
    // if logr is set, we clear the generated header as we rely on the backing
    // logr implementation to print headers
    if logr != nil {
        l.putBuffer(buf)
        buf = l.getBuffer()
    }
    if filter != nil {
        args = filter.Filter(args)
    }
    fmt.Fprintln(buf, args...)
    l.output(s, logr, buf, file, line, false)
}

func (l *loggingT) printDepth(s severity, logr logr.Logger, filter LogFilter, depth int, args ...interface{}) {
    buf, file, line := l.header(s, depth)
    // if logr is set, we clear the generated header as we rely on the backing
    // logr implementation to print headers
    if logr != nil {
        l.putBuffer(buf)
        buf = l.getBuffer()
    }
    if filter != nil {
        args = filter.Filter(args)
    }
    fmt.Fprint(buf, args...)
    if buf.Bytes()[buf.Len()-1] != '\n' {
        buf.WriteByte('\n')
    }
    l.output(s, logr, buf, file, line, false)
}

func (l *loggingT) printWithFileLine(s severity, logr logr.Logger, filter LogFilter, file string, line int, alsoToStderr bool, args ...interface{}) {
    buf := l.formatHeader(s, file, line)
    // if logr is set, we clear the generated header as we rely on the backing
    // logr implementation to print headers
    if logr != nil {
        l.putBuffer(buf)
        buf = l.getBuffer()
    }
    if filter != nil {
        args = filter.Filter(args)
    }
    fmt.Fprint(buf, args...)
    if buf.Bytes()[buf.Len()-1] != '\n' {
        buf.WriteByte('\n')
    }
    l.output(s, logr, buf, file, line, alsoToStderr)
}

println、printDepth、printWithFileLine会通过filter.Filter(args)来过滤args

filter.FilterF

k8s.io/klog/v2@v2.4.0/klog.go

代码语言:javascript
复制
func (l *loggingT) printf(s severity, logr logr.Logger, filter LogFilter, format string, args ...interface{}) {
    buf, file, line := l.header(s, 0)
    // if logr is set, we clear the generated header as we rely on the backing
    // logr implementation to print headers
    if logr != nil {
        l.putBuffer(buf)
        buf = l.getBuffer()
    }
    if filter != nil {
        format, args = filter.FilterF(format, args)
    }
    fmt.Fprintf(buf, format, args...)
    if buf.Bytes()[buf.Len()-1] != '\n' {
        buf.WriteByte('\n')
    }
    l.output(s, logr, buf, file, line, false)
}

printf方法使用filter.FilterF(format, args)返回的format及args进行格式化

filter.FilterS

k8s.io/klog/v2@v2.4.0/klog.go

代码语言:javascript
复制
func (l *loggingT) infoS(loggr logr.Logger, filter LogFilter, msg string, keysAndValues ...interface{}) {
    if filter != nil {
        msg, keysAndValues = filter.FilterS(msg, keysAndValues)
    }
    if loggr != nil {
        loggr.Info(msg, keysAndValues...)
        return
    }
    l.printS(nil, msg, keysAndValues...)
}

func (l *loggingT) errorS(err error, loggr logr.Logger, filter LogFilter, msg string, keysAndValues ...interface{}) {
    if filter != nil {
        msg, keysAndValues = filter.FilterS(msg, keysAndValues)
    }
    if loggr != nil {
        loggr.Error(err, msg, keysAndValues...)
        return
    }
    l.printS(err, msg, keysAndValues...)
}

infoS及errorS方法会使用filter.FilterS(msg, keysAndValues)返回的msg及keysAndValues进行打印

实例

代码语言:javascript
复制
type sampleLogFilter struct{}

func (f *sampleLogFilter) Filter(args []interface{}) []interface{} {
    for i, arg := range args {
        v, ok := arg.(string)
        if ok && strings.Contains(v, "filter me") {
            args[i] = "[FILTERED]"
        }
    }
    return args
}

func (f *sampleLogFilter) FilterF(format string, args []interface{}) (string, []interface{}) {
    return strings.Replace(format, "filter me", "[FILTERED]", 1), f.Filter(args)
}

func (f *sampleLogFilter) FilterS(msg string, keysAndValues []interface{}) (string, []interface{}) {
    return strings.Replace(msg, "filter me", "[FILTERED]", 1), f.Filter(keysAndValues)
}

func TestLogFilter(t *testing.T) {
    setFlags()
    defer logging.swap(logging.newBuffers())
    SetLogFilter(&sampleLogFilter{})
    defer SetLogFilter(nil)
    funcs := []struct {
        name     string
        logFunc  func(args ...interface{})
        severity severity
    }{{
        name:     "Info",
        logFunc:  Info,
        severity: infoLog,
    }, {
        name: "InfoDepth",
        logFunc: func(args ...interface{}) {
            InfoDepth(1, args...)
        },
        severity: infoLog,
    }, {
        name:     "Infoln",
        logFunc:  Infoln,
        severity: infoLog,
    }, {
        name: "Infof",
        logFunc: func(args ...interface{}) {

            Infof(args[0].(string), args[1:]...)
        },
        severity: infoLog,
    }, {
        name: "InfoS",
        logFunc: func(args ...interface{}) {
            InfoS(args[0].(string), args[1:]...)
        },
        severity: infoLog,
    }, {
        name:     "Warning",
        logFunc:  Warning,
        severity: warningLog,
    }, {
        name: "WarningDepth",
        logFunc: func(args ...interface{}) {
            WarningDepth(1, args...)
        },
        severity: warningLog,
    }, {
        name:     "Warningln",
        logFunc:  Warningln,
        severity: warningLog,
    }, {
        name: "Warningf",
        logFunc: func(args ...interface{}) {
            Warningf(args[0].(string), args[1:]...)
        },
        severity: warningLog,
    }, {
        name:     "Error",
        logFunc:  Error,
        severity: errorLog,
    }, {
        name: "ErrorDepth",
        logFunc: func(args ...interface{}) {
            ErrorDepth(1, args...)
        },
        severity: errorLog,
    }, {
        name:     "Errorln",
        logFunc:  Errorln,
        severity: errorLog,
    }, {
        name: "Errorf",
        logFunc: func(args ...interface{}) {
            Errorf(args[0].(string), args[1:]...)
        },
        severity: errorLog,
    }, {
        name: "ErrorS",
        logFunc: func(args ...interface{}) {
            ErrorS(errors.New("testerror"), args[0].(string), args[1:]...)
        },
        severity: errorLog,
    }, {
        name: "V().Info",
        logFunc: func(args ...interface{}) {
            V(0).Info(args...)
        },
        severity: infoLog,
    }, {
        name: "V().Infoln",
        logFunc: func(args ...interface{}) {
            V(0).Infoln(args...)
        },
        severity: infoLog,
    }, {
        name: "V().Infof",
        logFunc: func(args ...interface{}) {
            V(0).Infof(args[0].(string), args[1:]...)
        },
        severity: infoLog,
    }, {
        name: "V().InfoS",
        logFunc: func(args ...interface{}) {
            V(0).InfoS(args[0].(string), args[1:]...)
        },
        severity: infoLog,
    }, {
        name: "V().Error",
        logFunc: func(args ...interface{}) {
            V(0).Error(errors.New("test error"), args[0].(string), args[1:]...)
        },
        severity: errorLog,
    }, {
        name: "V().ErrorS",
        logFunc: func(args ...interface{}) {
            V(0).ErrorS(errors.New("test error"), args[0].(string), args[1:]...)
        },
        severity: errorLog,
    }}

    testcases := []struct {
        name           string
        args           []interface{}
        expectFiltered bool
    }{{
        args:           []interface{}{"%s:%s", "foo", "bar"},
        expectFiltered: false,
    }, {
        args:           []interface{}{"%s:%s", "foo", "filter me"},
        expectFiltered: true,
    }, {
        args:           []interface{}{"filter me %s:%s", "foo", "bar"},
        expectFiltered: true,
    }}

    for _, f := range funcs {
        for _, tc := range testcases {
            logging.newBuffers()
            f.logFunc(tc.args...)
            got := contains(f.severity, "[FILTERED]", t)
            if got != tc.expectFiltered {
                t.Errorf("%s filter application failed, got %v, want %v", f.name, got, tc.expectFiltered)
            }
        }
    }
}

小结

klog的LogFilter接口定义了Filter、FilterF、FilterS方法用于过滤log;println、printDepth、printWithFileLine会通过filter.Filter(args)来过滤args;printf方法使用filter.FilterF(format, args)返回的format及args进行格式化;infoS及errorS方法会使用filter.FilterS(msg, keysAndValues)返回的msg及keysAndValues进行打印。

doc

  • klog
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码匠的流水账 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • LogFilter
  • filter.Filter
  • filter.FilterF
  • filter.FilterS
  • 实例
  • 小结
  • doc
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档