mirror of
https://github.com/status-im/status-go.git
synced 2025-01-17 18:22:13 +00:00
parent
ae121486ff
commit
1b9e8fdafc
55
logutils/filtering_core.go
Normal file
55
logutils/filtering_core.go
Normal file
@ -0,0 +1,55 @@
|
||||
package logutils
|
||||
|
||||
import "go.uber.org/zap/zapcore"
|
||||
|
||||
type filterFunc func(ent zapcore.Entry) bool
|
||||
|
||||
type filteringCore struct {
|
||||
parent zapcore.Core
|
||||
|
||||
levelEnabler zapcore.LevelEnabler
|
||||
filterFunc filterFunc
|
||||
}
|
||||
|
||||
var (
|
||||
_ zapcore.Core = (*filteringCore)(nil)
|
||||
)
|
||||
|
||||
func newFilteringCore(core zapcore.Core, levelEnabler zapcore.LevelEnabler, filterFunc filterFunc) *filteringCore {
|
||||
return &filteringCore{
|
||||
parent: core,
|
||||
levelEnabler: levelEnabler,
|
||||
filterFunc: filterFunc,
|
||||
}
|
||||
}
|
||||
|
||||
func (core *filteringCore) Enabled(lvl zapcore.Level) bool {
|
||||
return core.levelEnabler.Enabled(lvl)
|
||||
}
|
||||
|
||||
func (core *filteringCore) With(fields []zapcore.Field) zapcore.Core {
|
||||
return &filteringCore{
|
||||
parent: core.parent.With(fields),
|
||||
levelEnabler: core.levelEnabler,
|
||||
filterFunc: core.filterFunc,
|
||||
}
|
||||
}
|
||||
|
||||
func (core *filteringCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
|
||||
if core.filterFunc(ent) {
|
||||
return ce.AddCore(ent, core)
|
||||
}
|
||||
return ce
|
||||
}
|
||||
|
||||
func (core *filteringCore) Write(ent zapcore.Entry, fields []zapcore.Field) error {
|
||||
return core.parent.Write(ent, fields)
|
||||
}
|
||||
|
||||
func (core *filteringCore) Sync() error {
|
||||
return core.parent.Sync()
|
||||
}
|
||||
|
||||
func (core *filteringCore) Parent() zapcore.Core {
|
||||
return core.parent
|
||||
}
|
36
logutils/namespace_filtering_core.go
Normal file
36
logutils/namespace_filtering_core.go
Normal file
@ -0,0 +1,36 @@
|
||||
package logutils
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
type namespaceFilteringCore struct {
|
||||
*filteringCore
|
||||
*namespacesTree
|
||||
}
|
||||
|
||||
func newNamespaceFilteringCore(core zapcore.Core) *namespaceFilteringCore {
|
||||
namespacesTree := newNamespacesTree()
|
||||
|
||||
levelEnablerFunc := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
|
||||
minLvl := namespacesTree.MinLevel()
|
||||
if minLvl != zapcore.InvalidLevel {
|
||||
return minLvl.Enabled(lvl)
|
||||
}
|
||||
return zapcore.LevelOf(core).Enabled(lvl)
|
||||
})
|
||||
|
||||
filterFunc := func(ent zapcore.Entry) bool {
|
||||
namespaceLvl := namespacesTree.LevelFor(ent.LoggerName)
|
||||
if namespaceLvl != zapcore.InvalidLevel {
|
||||
return namespaceLvl.Enabled(ent.Level)
|
||||
}
|
||||
return zapcore.LevelOf(core).Enabled(ent.Level)
|
||||
}
|
||||
|
||||
return &namespaceFilteringCore{
|
||||
filteringCore: newFilteringCore(core, levelEnablerFunc, filterFunc),
|
||||
namespacesTree: namespacesTree,
|
||||
}
|
||||
}
|
113
logutils/namespace_filtering_core_test.go
Normal file
113
logutils/namespace_filtering_core_test.go
Normal file
@ -0,0 +1,113 @@
|
||||
package logutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
func TestNamespaceFilteringCore(t *testing.T) {
|
||||
level := zap.NewAtomicLevelAt(zap.InfoLevel)
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
|
||||
core := zapcore.NewCore(
|
||||
zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()),
|
||||
zapcore.AddSync(buffer),
|
||||
level,
|
||||
)
|
||||
filteringCore := newNamespaceFilteringCore(core)
|
||||
logger := zap.New(filteringCore)
|
||||
|
||||
err := filteringCore.Rebuild("namespaceA:error,namespaceA.namespaceB:debug")
|
||||
require.NoError(t, err)
|
||||
|
||||
logger.Info("one") // OK
|
||||
logger.Debug("two") // not OK
|
||||
logger.Named("unregistered").Info("three") // OK
|
||||
logger.Named("unregistered").Debug("four") // not OK
|
||||
logger.Named("namespaceA").Error("five") // OK
|
||||
logger.Named("namespaceA").Info("six") // not OK
|
||||
logger.Named("namespaceA").Named("unregistered").Error("seven") // OK
|
||||
logger.Named("namespaceA").Named("unregistered").Info("eight") // not OK
|
||||
logger.Named("namespaceA").Named("namespaceB").Debug("nine") // OK
|
||||
logger.Named("namespaceA").Named("namespaceB").Named("unregistered").Debug("ten") // OK
|
||||
|
||||
require.Contains(t, buffer.String(), "one", "three", "five", "seven", "nine", "ten")
|
||||
require.NotContains(t, buffer.String(), "two", "four", "six", "eight")
|
||||
|
||||
err = filteringCore.Rebuild("") // Remove filtering
|
||||
require.NoError(t, err)
|
||||
buffer.Reset()
|
||||
|
||||
logger.Info("one") // OK
|
||||
logger.Named("namespaceA").Named("namespaceB").Debug("two") // not OK
|
||||
|
||||
require.Contains(t, buffer.String(), "one")
|
||||
require.NotContains(t, buffer.String(), "two")
|
||||
}
|
||||
|
||||
func generateNamespaces(n, depth int, level string) (namespaces string, deepestNamespace string) {
|
||||
namespace := ""
|
||||
for i := 0; i < n; i++ {
|
||||
namespace = strconv.Itoa(i)
|
||||
for d := 0; d < depth; d++ {
|
||||
namespace += "." + strconv.Itoa(d)
|
||||
namespaces += namespace + ":" + level + ","
|
||||
}
|
||||
}
|
||||
namespaces = strings.TrimSuffix(namespaces, ",")
|
||||
deepestNamespace = namespace
|
||||
|
||||
return namespaces, deepestNamespace
|
||||
}
|
||||
|
||||
func benchmarkNamespaces(b *testing.B, core zapcore.Core, setupFilter func(namespaces string) error) {
|
||||
// Creates complex namespaces filter:
|
||||
// "0.0:info,0.0.1:info,0.0.1.2:info,0.0.1.2.3:info,1.0:info,1.0.1:info,1.0.1.2:info,1.0.1.2.3:info,2.0:info,2.0.1:info,2.0.1.2:info,2.0.1.2.3:info"
|
||||
const n = 3
|
||||
const depth = 4
|
||||
namespaces, deepestNamespace := generateNamespaces(n, depth, zapcore.LevelOf(core).String())
|
||||
|
||||
err := setupFilter(namespaces)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
rootLogger := zap.New(core)
|
||||
deepestLogger := rootLogger.Named(deepestNamespace)
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
for level := zap.DebugLevel; level <= zap.ErrorLevel; level++ {
|
||||
rootLogger.Check(level, "Benchmark message").Write(zap.Int("i", i))
|
||||
deepestLogger.Check(level, "Benchmark message").Write(zap.Int("i", i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNamespacesFilteringCore(b *testing.B) {
|
||||
core := zapcore.NewCore(
|
||||
zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()),
|
||||
zapcore.Lock(zapcore.AddSync(bytes.NewBuffer(nil))),
|
||||
zap.NewAtomicLevelAt(zap.InfoLevel),
|
||||
)
|
||||
filteringCore := newNamespaceFilteringCore(core)
|
||||
|
||||
benchmarkNamespaces(b, filteringCore, filteringCore.Rebuild)
|
||||
}
|
||||
|
||||
func BenchmarkNamespacesZapCore(b *testing.B) {
|
||||
core := zapcore.NewCore(
|
||||
zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()),
|
||||
zapcore.Lock(zapcore.AddSync(bytes.NewBuffer(nil))),
|
||||
zap.NewAtomicLevelAt(zap.InfoLevel),
|
||||
)
|
||||
|
||||
benchmarkNamespaces(b, core, func(string) error { return nil })
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user