Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 14d55a7

Browse files
authored
log: add FilterCore and filter TiDB log (#862) (#895)
Signed-off-by: ti-srebot <ti-srebot@pingcap.com>
1 parent 8bc293a commit 14d55a7

8 files changed

Lines changed: 168 additions & 18 deletions

File tree

cmd/br/cmd.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ import (
1111
"sync/atomic"
1212
"time"
1313

14-
tidbutils "github.com/pingcap/tidb-tools/pkg/utils"
15-
1614
"github.com/pingcap/errors"
1715
"github.com/pingcap/log"
16+
tidbutils "github.com/pingcap/tidb-tools/pkg/utils"
1817
"github.com/pingcap/tidb/util/logutil"
1918
"github.com/sirupsen/logrus"
2019
"github.com/spf13/cobra"

cmd/tidb-lightning/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func main() {
8383
if err := cfg.LoadFromGlobal(globalCfg); err != nil {
8484
return err
8585
}
86-
return app.RunOnce(context.Background(), cfg, nil, nil)
86+
return app.RunOnce(context.Background(), cfg, nil)
8787
}
8888
}()
8989

pkg/lightning/lightning.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func (l *Lightning) goServe(statusAddr string, realAddrWriter io.Writer) error {
178178
// use a default glue later.
179179
// - for lightning as a library, taskCtx could be a meaningful context that get canceled outside, and glue could be a
180180
// caller implemented glue.
181-
func (l *Lightning) RunOnce(taskCtx context.Context, taskCfg *config.Config, glue glue.Glue, replaceLogger *zap.Logger) error {
181+
func (l *Lightning) RunOnce(taskCtx context.Context, taskCfg *config.Config, glue glue.Glue) error {
182182
if err := taskCfg.Adjust(taskCtx); err != nil {
183183
return err
184184
}
@@ -188,9 +188,6 @@ func (l *Lightning) RunOnce(taskCtx context.Context, taskCfg *config.Config, glu
188188
taskCfg.TaskID = int64(val.(int))
189189
})
190190

191-
if replaceLogger != nil {
192-
log.SetAppLogger(replaceLogger)
193-
}
194191
return l.run(taskCtx, taskCfg, glue)
195192
}
196193

pkg/lightning/lightning_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func (s *lightningSuite) TestRun(c *C) {
6464
cfg := config.NewConfig()
6565
err := cfg.LoadFromGlobal(globalConfig)
6666
c.Assert(err, IsNil)
67-
err = lightning.RunOnce(context.Background(), cfg, nil, nil)
67+
err = lightning.RunOnce(context.Background(), cfg, nil)
6868
c.Assert(err, ErrorMatches, ".*mydumper dir does not exist")
6969

7070
path, _ := filepath.Abs(".")
@@ -357,7 +357,7 @@ func (s *lightningServerSuite) TestHTTPAPIOutsideServerMode(c *C) {
357357
err := cfg.LoadFromGlobal(s.lightning.globalCfg)
358358
c.Assert(err, IsNil)
359359
go func() {
360-
errCh <- s.lightning.RunOnce(s.lightning.ctx, cfg, nil, nil)
360+
errCh <- s.lightning.RunOnce(s.lightning.ctx, cfg, nil)
361361
}()
362362
time.Sleep(100 * time.Millisecond)
363363

pkg/lightning/log/filter.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2021 PingCAP, Inc. Licensed under Apache-2.0.
2+
3+
package log
4+
5+
import (
6+
"strings"
7+
8+
"go.uber.org/zap/zapcore"
9+
)
10+
11+
var _ zapcore.Core = (*FilterCore)(nil)
12+
13+
// FilterCore is a zapcore.Core implementation, it filters log by path-qualified
14+
// package name.
15+
type FilterCore struct {
16+
zapcore.Core
17+
filters []string
18+
}
19+
20+
// NewFilterCore returns a FilterCore.
21+
//
22+
// Example, filter TiDB's log, `NewFilterCore(core, "github.com/pingcap/tidb/")`.
23+
// Note, must set AddCaller() to the logger.
24+
func NewFilterCore(core zapcore.Core, filteredPackages ...string) *FilterCore {
25+
return &FilterCore{
26+
Core: core,
27+
filters: filteredPackages,
28+
}
29+
}
30+
31+
// With adds structured context to the Core.
32+
func (f *FilterCore) With(fields []zapcore.Field) zapcore.Core {
33+
return &FilterCore{
34+
Core: f.Core.With(fields),
35+
filters: f.filters,
36+
}
37+
}
38+
39+
// Check overrides wrapper core.Check and adds itself to zapcore.CheckedEntry.
40+
func (f *FilterCore) Check(entry zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
41+
if f.Enabled(entry.Level) {
42+
return ce.AddCore(entry, f)
43+
}
44+
return ce
45+
}
46+
47+
// Write filters entry by checking if entry's Caller.Function matches filtered
48+
// package path.
49+
func (f *FilterCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
50+
for i := range f.filters {
51+
// Caller.Function is a package path-qualified function name.
52+
if strings.Contains(entry.Caller.Function, f.filters[i]) {
53+
return nil
54+
}
55+
}
56+
return f.Core.Write(entry, fields)
57+
}

pkg/lightning/log/filter_test.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright 2021 PingCAP, Inc. Licensed under Apache-2.0.
2+
3+
package log_test
4+
5+
import (
6+
"regexp"
7+
"strings"
8+
9+
. "github.com/pingcap/check"
10+
"go.uber.org/zap"
11+
"go.uber.org/zap/zapcore"
12+
13+
"github.com/pingcap/br/pkg/lightning/log"
14+
)
15+
16+
var _ = Suite(&testFilterSuite{})
17+
18+
type testFilterSuite struct{}
19+
20+
func (s *testFilterSuite) TestFilter(c *C) {
21+
logger, buffer := log.MakeTestLogger()
22+
logger.Warn("the message", zap.Int("number", 123456), zap.Ints("array", []int{7, 8, 9}))
23+
c.Assert(
24+
buffer.Stripped(), Equals,
25+
`{"$lvl":"WARN","$msg":"the message","number":123456,"array":[7,8,9]}`,
26+
)
27+
28+
logger, buffer = log.MakeTestLogger(zap.WrapCore(func(c zapcore.Core) zapcore.Core {
29+
return log.NewFilterCore(c, "github.com/pingcap/br/")
30+
}), zap.AddCaller())
31+
logger.Warn("the message", zap.Int("number", 123456), zap.Ints("array", []int{7, 8, 9}))
32+
c.Assert(buffer.Stripped(), HasLen, 0)
33+
34+
logger, buffer = log.MakeTestLogger(zap.WrapCore(func(c zapcore.Core) zapcore.Core {
35+
return log.NewFilterCore(c, "github.com/pingcap/tidb/").With([]zap.Field{zap.String("a", "b")})
36+
}), zap.AddCaller())
37+
logger.Warn("the message", zap.Int("number", 123456), zap.Ints("array", []int{7, 8, 9}))
38+
c.Assert(
39+
buffer.Stripped(), Equals,
40+
`{"$lvl":"WARN","$msg":"the message","a":"b","number":123456,"array":[7,8,9]}`,
41+
)
42+
43+
logger, buffer = log.MakeTestLogger(zap.WrapCore(func(c zapcore.Core) zapcore.Core {
44+
return log.NewFilterCore(c, "github.com/pingcap/br/").With([]zap.Field{zap.String("a", "b")})
45+
}), zap.AddCaller())
46+
logger.Warn("the message", zap.Int("number", 123456), zap.Ints("array", []int{7, 8, 9}))
47+
c.Assert(buffer.Stripped(), HasLen, 0)
48+
49+
// Fields won't trigger filter.
50+
logger, buffer = log.MakeTestLogger(zap.WrapCore(func(c zapcore.Core) zapcore.Core {
51+
return log.NewFilterCore(c, "github.com/pingcap/check/").With([]zap.Field{zap.String("a", "b")})
52+
}), zap.AddCaller())
53+
logger.Warn("the message", zap.String("stack", "github.com/pingcap/check/"))
54+
c.Assert(
55+
buffer.Stripped(), Equals,
56+
`{"$lvl":"WARN","$msg":"the message","a":"b","stack":"github.com/pingcap/check/"}`,
57+
)
58+
}
59+
60+
// PASS: filter_test.go:82: testFilterSuite.BenchmarkFilterRegexMatchString 1000000 1163 ns/op
61+
// PASS: filter_test.go:64: testFilterSuite.BenchmarkFilterStringsContains 10000000 159 ns/op
62+
//
63+
// Run `go test github.com/pingcap/br/pkg/lightning/log -check.b -test.v` to get benchmark result.
64+
func (s *testFilterSuite) BenchmarkFilterStringsContains(c *C) {
65+
c.ResetTimer()
66+
67+
inputs := []string{
68+
"github.com/pingcap/tidb/some/package/path",
69+
"github.com/tikv/pd/some/package/path",
70+
"github.com/pingcap/br/some/package/path",
71+
}
72+
filters := []string{"github.com/pingcap/tidb/", "github.com/tikv/pd/"}
73+
for i := 0; i < c.N; i++ {
74+
for i := range inputs {
75+
for j := range filters {
76+
_ = strings.Contains(inputs[i], filters[j])
77+
}
78+
}
79+
}
80+
}
81+
82+
func (s *testFilterSuite) BenchmarkFilterRegexMatchString(c *C) {
83+
c.ResetTimer()
84+
85+
inputs := []string{
86+
"github.com/pingcap/tidb/some/package/path",
87+
"github.com/tikv/pd/some/package/path",
88+
"github.com/pingcap/br/some/package/path",
89+
}
90+
filters := regexp.MustCompile(`github.com/(pingcap/tidb|tikv/pd)/`)
91+
for i := 0; i < c.N; i++ {
92+
for i := range inputs {
93+
_ = filters.MatchString(inputs[i])
94+
}
95+
}
96+
}

pkg/lightning/log/log.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,13 @@ func InitLogger(cfg *Config, tidbLoglevel string) error {
7878
logutil.InitLogger(&logutil.LogConfig{Config: pclog.Config{Level: tidbLoglevel}})
7979

8080
logCfg := &pclog.Config{
81-
Level: cfg.Level,
81+
Level: cfg.Level,
82+
DisableCaller: false, // FilterCore requires zap.AddCaller.
8283
}
84+
filterTiDBLog := zap.WrapCore(func(core zapcore.Core) zapcore.Core {
85+
// Filter logs from TiDB and PD.
86+
return NewFilterCore(core, "github.com/pingcap/tidb/", "github.com/tikv/pd/")
87+
})
8388
if len(cfg.File) > 0 {
8489
logCfg.File = pclog.FileLogConfig{
8590
Filename: cfg.File,
@@ -88,10 +93,11 @@ func InitLogger(cfg *Config, tidbLoglevel string) error {
8893
MaxBackups: cfg.FileMaxBackups,
8994
}
9095
}
91-
logger, props, err := pclog.InitLogger(logCfg)
96+
logger, props, err := pclog.InitLogger(logCfg, filterTiDBLog)
9297
if err != nil {
9398
return err
9499
}
100+
pclog.ReplaceGlobals(logger, props)
95101

96102
// Do not log stack traces at all, as we'll get the stack trace from the
97103
// error itself.
@@ -106,11 +112,6 @@ func L() Logger {
106112
return appLogger
107113
}
108114

109-
// SetAppLogger replaces the default logger in this package to given one
110-
func SetAppLogger(l *zap.Logger) {
111-
appLogger = Logger{l.WithOptions(zap.AddStacktrace(zap.DPanicLevel))}
112-
}
113-
114115
// Level returns the current global log level.
115116
func Level() zapcore.Level {
116117
return appLevel.Level()

pkg/lightning/log/testlogger.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
)
2121

2222
// MakeTestLogger creates a Logger instance which produces JSON logs.
23-
func MakeTestLogger() (Logger, *zaptest.Buffer) {
23+
func MakeTestLogger(opts ...zap.Option) (Logger, *zaptest.Buffer) {
2424
buffer := new(zaptest.Buffer)
2525
logger := zap.New(zapcore.NewCore(
2626
zapcore.NewJSONEncoder(zapcore.EncoderConfig{
@@ -31,6 +31,6 @@ func MakeTestLogger() (Logger, *zaptest.Buffer) {
3131
}),
3232
buffer,
3333
zap.DebugLevel,
34-
))
34+
), opts...)
3535
return Logger{Logger: logger}, buffer
3636
}

0 commit comments

Comments
 (0)