Skip to content
Snippets Groups Projects
Commit cdcfee8d authored by Pavel Antonov's avatar Pavel Antonov :asterisk:
Browse files

Merge branch 'feature/PRXS-951-2027-ZapFilterCore' into 'feature/PRXS-951-Log'

Добавлен zap Core с фильтрацией

See merge request perxis/perxis-go!162
parents 3c1839ce 8fac5002
No related branches found
No related tags found
No related merge requests found
package zap
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type FilterFunc func(entry zapcore.Entry, fields []zapcore.Field) bool
func HasField(field zapcore.Field) FilterFunc {
return func(_ zapcore.Entry, fields []zapcore.Field) bool {
for _, f := range fields {
if f.Equals(field) {
return true
}
}
return false
}
}
func NotHasField(field zapcore.Field) FilterFunc {
return func(entry zapcore.Entry, fields []zapcore.Field) bool {
return !HasField(field)(entry, fields)
}
}
type filterCore struct {
zapcore.Core
filters []FilterFunc
// fields хранит контекст записей ядра, передаваемых при вызове With.
// В методе Write передаются только поля конкретной записи, но мы также хотим учитывать поля контекста ядра.
fields []zap.Field
}
// RegisterFilters - добавить фильтры, которые будут применяться при записи лога (вызове `core.Write`)
// Метод `core.Write` будет вызван только в случае, когда результат всех фильтров `true`
//
// Обратить внимание, фильтр не применяется к полям, которые были добавлены в `core` через вызов `core.With`
// до вызова RegisterFilters. Пример:
//
// l, _ := zap.NewDevelopment()
// core := l.Core().With([]zapcore.Field{zap.Int("a", 5)})
// core = RegisterFilters(core, HasField(zap.Int("a", 5)))
//
// logger := zap.New(core)
// logger.Info("Test log") // НЕ будет записан
// logger.Info("Test log", zap.Int("a", 5)) // будет записан
func RegisterFilters(core zapcore.Core, filters ...FilterFunc) zapcore.Core {
return &filterCore{
Core: core,
filters: filters,
}
}
func (core *filterCore) With(fields []zapcore.Field) zapcore.Core {
return &filterCore{
Core: core.Core.With(fields),
filters: core.filters,
fields: append(core.fields, fields...),
}
}
func (core *filterCore) Check(entry zapcore.Entry, checkedEntry *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if core.Core.Enabled(entry.Level) {
return checkedEntry.AddCore(entry, core)
}
return checkedEntry
}
func (core *filterCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
if len(core.fields) > 0 {
fields = append(core.fields, fields...)
}
for _, filter := range core.filters {
if !filter(entry, fields) {
return nil
}
}
return core.Core.Write(entry, fields)
}
package zap
import (
"testing"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"
)
func TestFilterCore_Write(t *testing.T) {
core, logs := observer.New(zapcore.InfoLevel)
core = RegisterFilters(core, HasField(zap.Bool("check", true)))
err := core.With([]zapcore.Field{zap.Bool("check", true)}).Write(zapcore.Entry{Message: "msg"}, nil)
require.NoError(t, err)
err = core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{zap.Bool("check", true)})
require.NoError(t, err)
err = core.Write(zapcore.Entry{Message: "msg"}, nil)
require.NoError(t, err)
require.Equal(t, 2, logs.Len())
}
func TestNotHasField(t *testing.T) {
core, logs := observer.New(zapcore.InfoLevel)
core = RegisterFilters(core, NotHasField(zap.Int("b", 2)))
err := core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{
zap.Int("a", 1),
zap.Int("b", 2),
})
require.NoError(t, err)
err = core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{
zap.Int("a", 1),
zap.Int("b", 3),
})
require.NoError(t, err)
err = core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{})
require.NoError(t, err)
require.Equal(t, 2, logs.Len())
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment