Skip to content
Snippets Groups Projects
Commit 839125d9 authored by Alena Petraki's avatar Alena Petraki :nail_care_tone1:
Browse files

Merge branch 'feature/PRXS-951-2037-ChannelCore' into 'feature/PRXS-951-Log'

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

See merge request perxis/perxis-go!166
parents 6f4b0a04 5172bab8
Branches
Tags
No related merge requests found
package zap
import (
"strings"
"go.uber.org/zap/zapcore"
)
const channelKey = "channel"
func HasChannel(channel string) FilterFunc {
return func(entry zapcore.Entry, fields []zapcore.Field) bool {
for _, f := range fields {
if f.Key == channelKey && f.Type == zapcore.StringType {
list := strings.Split(f.String, ",")
for _, v := range list {
if v == channel {
return true
}
}
}
}
return false
}
}
// NewDefaultChannelCore аналогичен NewChannelCore, но также устанавливает переданный канал в качестве канала по умолчанию.
// Это означает, что если поле Channel в записи не указано, запись все равно будет передана в zapcore.Core.
func NewDefaultChannelCore(core zapcore.Core, channel string) zapcore.Core {
return RegisterFilters(
core,
Or(
HasChannel(channel),
Not(HasKey(channelKey)),
),
)
}
// NewChannelCore добавляет к переданному Core фильтрацию записей по каналам.
// Это означает, что если запись содержит поле Channel и значение соответствует переданному каналу, то запись будет передана в zapcore.Core.
func NewChannelCore(core zapcore.Core, channel string) zapcore.Core {
return RegisterFilters(core, HasChannel(channel))
}
package zap
import (
"testing"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"
)
func TestNewChannelCore_WriteSingleChannel(t *testing.T) {
core, logs := observer.New(zapcore.InfoLevel)
core = NewChannelCore(core, "test")
err := core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channel("test")})
require.NoError(t, err)
err = core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channel("empty")}) // запись не попадет в лог
require.NoError(t, err)
require.Equal(t, 1, logs.Len())
}
func TestNewChannelCore_WriteMultiplyChannels(t *testing.T) {
core, logs := observer.New(zapcore.InfoLevel)
core = zapcore.NewTee(
NewChannelCore(core, "test1"),
NewChannelCore(core, "test2"),
)
err := core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channel("test1", "test2")}) // запись попадет сразу в 2 core
require.NoError(t, err)
require.Equal(t, 2, logs.Len())
}
func TestNewDefaultChannelCore(t *testing.T) {
core, logs := observer.New(zapcore.InfoLevel)
core = NewDefaultChannelCore(core, "test1")
err := core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channel("test1")})
require.NoError(t, err)
err = core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channel("test2")}) // эта запись не попадет в лог
require.NoError(t, err)
err = core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{})
require.NoError(t, err)
require.Equal(t, 2, logs.Len())
}
...@@ -2,6 +2,7 @@ package zap ...@@ -2,6 +2,7 @@ package zap
import ( import (
"context" "context"
"strings"
"git.perx.ru/perxis/perxis-go/id" "git.perx.ru/perxis/perxis-go/id"
_ "git.perx.ru/perxis/perxis-go/id/system" // регистрируем обработчики для системных объектов _ "git.perx.ru/perxis/perxis-go/id/system" // регистрируем обработчики для системных объектов
...@@ -9,6 +10,13 @@ import ( ...@@ -9,6 +10,13 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
func Channel(channels ...string) zap.Field {
if len(channels) == 0 {
return zap.Skip()
}
return zap.String(channelKey, strings.Join(channels, ","))
}
func Category(category string) zap.Field { func Category(category string) zap.Field {
if category == "" { if category == "" {
return zap.Skip() return zap.Skip()
......
...@@ -24,6 +24,34 @@ func NotHasField(field zapcore.Field) FilterFunc { ...@@ -24,6 +24,34 @@ func NotHasField(field zapcore.Field) FilterFunc {
} }
} }
func HasKey(key string) FilterFunc {
return func(entry zapcore.Entry, fields []zapcore.Field) bool {
for _, f := range fields {
if f.Key == key {
return true
}
}
return false
}
}
func Or(filters ...FilterFunc) FilterFunc {
return func(entry zapcore.Entry, fields []zapcore.Field) bool {
for _, f := range filters {
if f(entry, fields) {
return true
}
}
return false
}
}
func Not(filter FilterFunc) FilterFunc {
return func(entry zapcore.Entry, fields []zapcore.Field) bool {
return !filter(entry, fields)
}
}
type filterCore struct { type filterCore struct {
zapcore.Core zapcore.Core
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment