diff --git a/assets/templates/middleware/access_log b/assets/templates/middleware/access_log deleted file mode 100755 index 86b4fe25ef6247f78dd491578f5b6bf05fa8e992..0000000000000000000000000000000000000000 --- a/assets/templates/middleware/access_log +++ /dev/null @@ -1,65 +0,0 @@ -import ( - "fmt" - "time" - "context" - - "go.uber.org/zap" -) - -{{ $funcName := (or .Vars.FuncName ("LoggingMiddleware")) }} -{{ $decorator := (or .Vars.DecoratorName ("loggingMiddleware")) }} - -// {{$decorator}} implements {{.Interface.Type}} that is instrumented with logging -type {{$decorator}} struct { - logger *zap.Logger - next {{.Interface.Type}} -} - -// {{$funcName}} instruments an implementation of the {{.Interface.Type}} with simple logging -func {{$funcName}}(logger *zap.Logger) Middleware { - return func(next {{.Interface.Type}}) {{.Interface.Type}} { - return &{{$decorator}}{ - next: next, - logger: logger, - } - } -} - -{{range $method := .Interface.Methods}} - func (m *{{$decorator}}) {{$method.Declaration}} { - begin := time.Now() - var fields []zapcore.Field - {{- if $method.HasParams}} - for k, v := range {{$method.ParamsMap}} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k,v)) - } - {{end}} - - m.logger.Debug("{{$method.Name}}.Request",fields...) - - {{ $method.ResultsNames }} = m.next.{{ $method.Call }} - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - {{ if $method.HasResults}} - for k, v := range {{$method.ResultsMap}} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k,v)) - } - {{end}} - - m.logger.Debug("{{$method.Name}}.Response", fields...) - - return {{ $method.ResultsNames }} - } -{{end}} diff --git a/assets/templates/middleware/access_log.tmpl b/assets/templates/middleware/access_log.tmpl new file mode 100755 index 0000000000000000000000000000000000000000..9f9899b835a1ec46652da008035f3a8931dc472d --- /dev/null +++ b/assets/templates/middleware/access_log.tmpl @@ -0,0 +1,58 @@ +import ( + "fmt" + "time" + "context" + + "go.uber.org/zap" +) + +{{ $funcName := (or .Vars.FuncName ("AccessLoggingMiddleware")) }} +{{ $decorator := (or .Vars.DecoratorName ("accessLoggingMiddleware")) }} +{{ $objectName := (trimSuffix "s" (split "." .Interface.Type)._1) }} + +// {{$decorator}} implements {{.Interface.Type}} that is instrumented with logging +type {{$decorator}} struct { + logger *zap.Logger + next {{.Interface.Type}} +} + +// {{$funcName}} instruments an implementation of the {{.Interface.Type}} with simple logging +func {{$funcName}}(logger *zap.Logger) Middleware { + return func(next {{.Interface.Type}}) {{.Interface.Type}} { + return &{{$decorator}}{ + next: next, + logger: logger, + } + } +} + +{{range $method := .Interface.Methods}} + func (m *{{$decorator}}) {{$method.Declaration}} { + begin := time.Now() + + m.logger.Debug("{{$method.Name}}.Request", + {{- range $param := $method.Params -}} + {{- if (eq $param.Name "ctx") }} + zap.Reflect("principal", auth.GetPrincipal(ctx)), + {{- else }} + zap.Reflect("{{$param.Name}}", {{$param.Name}}), + {{- end -}} + {{ end }} + ) + + {{ $method.ResultsNames }} = m.next.{{ $method.Call }} + + m.logger.Debug("{{$method.Name}}.Response", + zap.Duration("time", time.Since(begin)), + {{- range $param := $method.Results -}} + {{- if (eq $param.Name "err") }} + zap.Error(err), + {{- else }} + zap.Reflect("{{$param.Name}}", {{$param.Name}}), + {{- end -}} + {{ end }} + ) + + return {{ $method.ResultsNames }} + } +{{end}} diff --git a/assets/templates/middleware/log.tmpl b/assets/templates/middleware/log.tmpl new file mode 100644 index 0000000000000000000000000000000000000000..ab91909fb61f1044fe74810390a64d469a6cb614 --- /dev/null +++ b/assets/templates/middleware/log.tmpl @@ -0,0 +1,73 @@ +{{/* +Этот шаблон предназначен только для первичной генерации LoggingMiddleware, +поскольку он не может учесть все сигнатуры логгируемых методов. После генерации +необходимо внести правки в код в местах, помеченных 'TODO' + +Сгенерировать middleware: +```shell +gowrap gen -p git.perx.ru/perxis/perxis-go/<package_name> -i <interface> -t ../../../assets/templates/middleware/logging.tmpl -o info_logging_middleware.go -g +``` + */}} + +import ( + "fmt" + "time" + "context" + + logzap "git.perx.ru/perxis/perxis-go/zap" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +{{ $funcName := (or .Vars.FuncName ("LoggingMiddleware")) }} +{{ $decorator := (or .Vars.DecoratorName ("loggingMiddleware")) }} +{{ $packageName := (split "." .Interface.Type)._0 }} +{{ $serviceName := (split "." .Interface.Type)._1 }} +{{ $objectName := (trimSuffix "s" (split "." .Interface.Type)._1) }} +{{ $writeMethods := list "Archive" "Create" "Delete" "Publish" "Unarchive" "Undelete" "Unpublish" "Update" "SetSchema" "Migrate" }} + +type {{ $decorator }} struct { + logger *zap.Logger + next {{ .Interface.Type }} +} + +func {{ $funcName }} (logger *zap.Logger) Middleware { + return func(next {{ .Interface.Type }}) {{ .Interface.Type }} { + return &{{ $decorator }}{ + next: next, + logger: logger.With(logzap.Component("{{ (lower $serviceName ) }}")), + } + } +} + +{{ range $method := .Interface.Methods }} +func (m *{{ $decorator }}) {{ $method.Declaration }} { + logger := m.logger.With( + {{- if $method.AcceptsContext }} + logzap.CallerFromContext(ctx), + {{ end -}} + {{- if has $method.Name $writeMethods -}} + logzap.Event({{ $packageName }}.Event{{ $objectName }}{{ $method.Name }}), + logzap.Object(TODO), + {{ end -}} + ) + + {{ $method.ResultsNames }} = m.next.{{ $method.Call }} + + {{- if $method.ReturnsError }} + if err != nil { + logger.Error("Failed to {{ (lower $method.Name) }}", zap.Error(err) + {{- if has $method.Name $writeMethods -}} + , logzap.Channels(logzap.Userlog, logzap.Syslog) + {{- end -}}) + return + } + {{ end }} + + {{ if has $method.Name $writeMethods }} + logger.Info("Successfully {{ (lower (trimSuffix "e" $method.Name)) }}ed", logzap.Channels(logzap.Userlog)) + {{ end -}} + + return {{ $method.ResultsNames }} +} +{{ end }} diff --git a/assets/templates/middleware/middleware b/assets/templates/middleware/middleware.tmpl similarity index 57% rename from assets/templates/middleware/middleware rename to assets/templates/middleware/middleware.tmpl index 89877774c933840c2bdd569f2beed8105588aae2..c717d577e89331ed386cf21a1b8ba5486cd54714 100755 --- a/assets/templates/middleware/middleware +++ b/assets/templates/middleware/middleware.tmpl @@ -2,20 +2,26 @@ import ( "go.uber.org/zap" ) -type Middleware func({{.Interface.Type}}) {{.Interface.Type}} +{{ $serviceName := (split "." .Interface.Type)._1 }} +type Middleware func({{.Interface.Type}}) {{.Interface.Type}} func WithLog(s {{.Interface.Type}}, logger *zap.Logger, log_access bool) {{.Interface.Type}} { if logger == nil { logger = zap.NewNop() } - - logger = logger.Named("{{ .Interface.Name }}") + logger = logger.Named("{{ .Interface.Name }}") + {{- if (has $serviceName (list "Items" "Collections") ) }} + if log_access { + s = AccessLoggingMiddleware(logger)(s) + } + s = LoggingMiddleware(logger)(s) + {{ else }} s = ErrorLoggingMiddleware(logger)(s) if log_access { s = LoggingMiddleware(logger)(s) } + {{ end -}} s = RecoveringMiddleware(logger)(s) return s } - diff --git a/log/service.go b/log/service.go index 8a39ca53e0573ac4ed0bed8bba619837d1fdf030..46e306077d8ee3476dc1e83aa30a7501494325d5 100644 --- a/log/service.go +++ b/log/service.go @@ -8,6 +8,8 @@ import ( pb "git.perx.ru/perxis/perxis-go/proto/log" ) +const ServiceName = "logs" + type Service interface { // Log метод записи логов diff --git a/log/zap/buffered_write_syncer_test.go b/log/zap/buffered_write_syncer_test.go index 58e40098bb2370b7899d31fc42c2ea569ca81cf7..58d64fa9f6a612f58701e5284262b505ec190cc5 100644 --- a/log/zap/buffered_write_syncer_test.go +++ b/log/zap/buffered_write_syncer_test.go @@ -53,16 +53,12 @@ func TestBufferedWriteSyncer_Write_Concurrent(t *testing.T) { wg.Add(1) go func(wg *sync.WaitGroup) { defer wg.Done() - - err := ws.Write(&log.Entry{Message: "log message"}) - require.NoError(t, err) + require.NoError(t, ws.Write(&log.Entry{Message: "log message"})) }(&wg) } wg.Wait() - - err := ws.Stop() - require.NoError(t, err) + require.NoError(t, ws.Stop()) service.AssertExpectations(t) } @@ -81,15 +77,12 @@ func TestBufferedWriteSyncer_Flush(t *testing.T) { for i := 0; i < 10; i++ { for j := 0; j < 10; j++ { - err := ws.Write(&log.Entry{Message: "log message"}) - require.NoError(t, err) + require.NoError(t, ws.Write(&log.Entry{Message: "log message"})) } - err := ws.Sync() - require.NoError(t, err) + require.NoError(t, ws.Sync()) } - err := ws.Stop() - require.NoError(t, err) + require.NoError(t, ws.Stop()) service.AssertExpectations(t) } @@ -107,12 +100,10 @@ func TestBufferedWriteSyncer_MaxBufferSize(t *testing.T) { ws := &BufferedWriteSyncer{Service: service, MaxBufferSize: 10} for i := 0; i < 100; i++ { - err := ws.Write(&log.Entry{Message: "log message"}) - require.NoError(t, err) + require.NoError(t, ws.Write(&log.Entry{Message: "log message"})) } - err := ws.Stop() - require.NoError(t, err) + require.NoError(t, ws.Stop()) service.AssertExpectations(t) } @@ -130,14 +121,11 @@ func TestBufferedWriteSyncer_FlushInterval(t *testing.T) { ws := &BufferedWriteSyncer{Service: service, FlushInterval: time.Second} for j := 0; j < 10; j++ { - err := ws.Write(&log.Entry{Message: "log message"}) - require.NoError(t, err) + require.NoError(t, ws.Write(&log.Entry{Message: "log message"})) } time.Sleep(3 * time.Second) // ждем, пока сработает интервал - - err := ws.Stop() - require.NoError(t, err) + require.NoError(t, ws.Stop()) service.AssertExpectations(t) } diff --git a/log/zap/core.go b/log/zap/core.go index f2b220eab78a6cd2416408385b521c743bcefb94..070e6fb84eb3ca74cd59262eb5244054967e9307 100644 --- a/log/zap/core.go +++ b/log/zap/core.go @@ -1,6 +1,8 @@ package zap import ( + "fmt" + oid "git.perx.ru/perxis/perxis-go/id" "git.perx.ru/perxis/perxis-go/log" "git.perx.ru/perxis/perxis-go/pkg/id" @@ -76,6 +78,10 @@ func (core *Core) getEntry(entry zapcore.Entry, fields []zapcore.Field) *log.Ent ent.CallerID, _ = enc.Fields["caller"].(*oid.ObjectId) ent.Attr = enc.Fields["attr"] + if err, _ := enc.Fields["error"].(error); err != nil { + ent.Message = fmt.Sprintf("%s. Error: %s", ent.Message, err.Error()) + } + if tags, ok := enc.Fields["tags"].([]any); ok { for _, item := range tags { if tag, ok := item.(string); ok { diff --git a/log/zap/core_test.go b/log/zap/core_test.go index 51b222bdc002c6ed74bb2e81fc8c84be59f95cba..8b2d64d75c737164f38b911fcbd4a9a0e0c56101 100644 --- a/log/zap/core_test.go +++ b/log/zap/core_test.go @@ -5,7 +5,7 @@ import ( "git.perx.ru/perxis/perxis-go/id" "git.perx.ru/perxis/perxis-go/log" - zap2 "git.perx.ru/perxis/perxis-go/zap" + logzap "git.perx.ru/perxis/perxis-go/zap" "github.com/stretchr/testify/require" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -31,13 +31,13 @@ func TestCore_getEntry(t *testing.T) { entry: zapcore.Entry{Level: zapcore.InfoLevel, Message: "создан элемент коллекции"}, fields: []zapcore.Field{ zap.String("key", "val"), // будет проигнорировано - zap2.Category("create"), - zap2.Component("Items.Service"), - zap2.Event("Items.Create"), - zap2.Object("/spaces/WPNN/envs/9VGP/cols/GxNv/items/W0fl"), - zap2.Caller("/users/PHVz"), - zap2.Attr("any"), - zap2.Tags("tag1", "tag2", "tag3"), + logzap.Category("create"), + logzap.Component("Items.Service"), + logzap.Event("Items.Create"), + logzap.Object("/spaces/WPNN/envs/9VGP/cols/GxNv/items/W0fl"), + logzap.Caller("/users/PHVz"), + logzap.Attr("any"), + logzap.Tags("tag1", "tag2", "tag3"), }, }, want: &log.Entry{ diff --git a/log/zap/example_test.go b/log/zap/example_test.go index ee51ef0345b01a88993e30c24a38f7e89bbe5929..0ffb282a6c2c91cff4c203e8500773c3630fdfa8 100644 --- a/log/zap/example_test.go +++ b/log/zap/example_test.go @@ -13,7 +13,7 @@ import ( "git.perx.ru/perxis/perxis-go/pkg/items" "git.perx.ru/perxis/perxis-go/pkg/users" usersmocks "git.perx.ru/perxis/perxis-go/pkg/users/mocks" - zap2 "git.perx.ru/perxis/perxis-go/zap" + logzap "git.perx.ru/perxis/perxis-go/zap" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "go.uber.org/zap" @@ -29,7 +29,7 @@ func TestExample(t *testing.T) { LogLevel: log.Level(zapcore.InfoLevel), Message: "Successfully created", Component: "Items", - Event: items.EventCreateItem, + Event: items.EventItemCreate, ObjectID: id.MustObjectId(item), CallerID: id.MustObjectId(user), Tags: []string{"tag1", "tag2", "tag3"}, @@ -38,7 +38,7 @@ func TestExample(t *testing.T) { LogLevel: log.Level(zapcore.WarnLevel), Message: "Successfully updated", Component: "Items", - Event: items.EventUpdateItem, + Event: items.EventItemUpdate, ObjectID: id.MustObjectId(item), CallerID: id.MustObjectId(user), Attr: map[string]map[string]any{"title": {"old": "old title", "new": "new title"}}, @@ -70,23 +70,23 @@ func TestExample(t *testing.T) { // Пример отправки логов для сервиса Items { - logger := logger.With(zap2.Component("Items")) + logger := logger.With(logzap.Component("Items")) ctx := auth.WithPrincipal(context.Background(), factory.User("74d90aaf")) // Отправка лога при создании item logger.Info("Successfully created", - zap2.Event(items.EventCreateItem), - zap2.Object(item), - zap2.CallerFromContext(ctx), - zap2.Tags("tag1", "tag2", "tag3"), + logzap.Event(items.EventItemCreate), + logzap.Object(item), + logzap.CallerFromContext(ctx), + logzap.Tags("tag1", "tag2", "tag3"), ) // Отправка лога при обновлении item logger.Warn("Successfully updated", - zap2.Event(items.EventUpdateItem), - zap2.Object(item), - zap2.CallerFromContext(ctx), - zap2.Attr(map[string]map[string]any{"title": {"old": "old title", "new": "new title"}}), + logzap.Event(items.EventItemUpdate), + logzap.Object(item), + logzap.CallerFromContext(ctx), + logzap.Attr(map[string]map[string]any{"title": {"old": "old title", "new": "new title"}}), ) } diff --git a/pkg/collections/events.go b/pkg/collections/events.go new file mode 100644 index 0000000000000000000000000000000000000000..bdc92e7769a7cd7ffc880825caaf3098fb5495fb --- /dev/null +++ b/pkg/collections/events.go @@ -0,0 +1,8 @@ +package collections + +const ( + EventCollectionCreate = "collection_create" + EventCollectionUpdate = "collection_update" + EventCollectionDelete = "collection_delete" + EventCollectionSetSchema = "collection_set_schema" +) diff --git a/pkg/collections/middleware/access_logging_middleware.go b/pkg/collections/middleware/access_logging_middleware.go new file mode 100644 index 0000000000000000000000000000000000000000..3624955b5d3ef6201704932e623b4e8e00cc6192 --- /dev/null +++ b/pkg/collections/middleware/access_logging_middleware.go @@ -0,0 +1,175 @@ +// Code generated by gowrap. DO NOT EDIT. +// template: ../../../assets/templates/middleware/access_log.tmpl +// gowrap: http://github.com/hexdigest/gowrap + +package middleware + +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/collections -i Collections -t ../../../assets/templates/middleware/access_log.tmpl -o access_logging_middleware.go -l "" + +import ( + "context" + "time" + + "git.perx.ru/perxis/perxis-go/pkg/auth" + "git.perx.ru/perxis/perxis-go/pkg/collections" + "git.perx.ru/perxis/perxis-go/pkg/schema" + "go.uber.org/zap" +) + +// accessLoggingMiddleware implements collections.Collections that is instrumented with logging +type accessLoggingMiddleware struct { + logger *zap.Logger + next collections.Collections +} + +// AccessLoggingMiddleware instruments an implementation of the collections.Collections with simple logging +func AccessLoggingMiddleware(logger *zap.Logger) Middleware { + return func(next collections.Collections) collections.Collections { + return &accessLoggingMiddleware{ + next: next, + logger: logger, + } + } +} + +func (m *accessLoggingMiddleware) Create(ctx context.Context, collection *collections.Collection) (created *collections.Collection, err error) { + begin := time.Now() + + m.logger.Debug("Create.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("collection", collection), + ) + + created, err = m.next.Create(ctx, collection) + + m.logger.Debug("Create.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("created", created), + zap.Error(err), + ) + + return created, err +} + +func (m *accessLoggingMiddleware) Delete(ctx context.Context, spaceId string, envId string, collectionId string) (err error) { + begin := time.Now() + + m.logger.Debug("Delete.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + ) + + err = m.next.Delete(ctx, spaceId, envId, collectionId) + + m.logger.Debug("Delete.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} + +func (m *accessLoggingMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, options ...*collections.GetOptions) (collection *collections.Collection, err error) { + begin := time.Now() + + m.logger.Debug("Get.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("options", options), + ) + + collection, err = m.next.Get(ctx, spaceId, envId, collectionId, options...) + + m.logger.Debug("Get.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("collection", collection), + zap.Error(err), + ) + + return collection, err +} + +func (m *accessLoggingMiddleware) List(ctx context.Context, spaceId string, envId string, filter *collections.Filter) (collections []*collections.Collection, err error) { + begin := time.Now() + + m.logger.Debug("List.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("filter", filter), + ) + + collections, err = m.next.List(ctx, spaceId, envId, filter) + + m.logger.Debug("List.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("collections", collections), + zap.Error(err), + ) + + return collections, err +} + +func (m *accessLoggingMiddleware) SetSchema(ctx context.Context, spaceId string, envId string, collectionId string, schema *schema.Schema) (err error) { + begin := time.Now() + + m.logger.Debug("SetSchema.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("schema", schema), + ) + + err = m.next.SetSchema(ctx, spaceId, envId, collectionId, schema) + + m.logger.Debug("SetSchema.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} + +func (m *accessLoggingMiddleware) SetState(ctx context.Context, spaceId string, envId string, collectionId string, state *collections.StateInfo) (err error) { + begin := time.Now() + + m.logger.Debug("SetState.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("state", state), + ) + + err = m.next.SetState(ctx, spaceId, envId, collectionId, state) + + m.logger.Debug("SetState.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} + +func (m *accessLoggingMiddleware) Update(ctx context.Context, coll *collections.Collection) (err error) { + begin := time.Now() + + m.logger.Debug("Update.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("coll", coll), + ) + + err = m.next.Update(ctx, coll) + + m.logger.Debug("Update.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} diff --git a/pkg/collections/middleware/error_logging_middleware.go b/pkg/collections/middleware/error_logging_middleware.go deleted file mode 100644 index 0491250639063a0e4d229c711c19b36223b9b2e4..0000000000000000000000000000000000000000 --- a/pkg/collections/middleware/error_logging_middleware.go +++ /dev/null @@ -1,101 +0,0 @@ -package middleware - -// Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/error_log -// gowrap: http://github.com/hexdigest/gowrap - -//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/collections -i Collections -t ../../../assets/templates/middleware/error_log -o error_logging_middleware.go -l "" - -import ( - "context" - - "git.perx.ru/perxis/perxis-go/pkg/collections" - "git.perx.ru/perxis/perxis-go/pkg/schema" - "go.uber.org/zap" -) - -// errorLoggingMiddleware implements collections.Collections that is instrumented with logging -type errorLoggingMiddleware struct { - logger *zap.Logger - next collections.Collections -} - -// ErrorLoggingMiddleware instruments an implementation of the collections.Collections with simple logging -func ErrorLoggingMiddleware(logger *zap.Logger) Middleware { - return func(next collections.Collections) collections.Collections { - return &errorLoggingMiddleware{ - next: next, - logger: logger, - } - } -} - -func (m *errorLoggingMiddleware) Create(ctx context.Context, collection *collections.Collection) (created *collections.Collection, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Create(ctx, collection) -} - -func (m *errorLoggingMiddleware) Delete(ctx context.Context, spaceId string, envId string, collectionId string) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Delete(ctx, spaceId, envId, collectionId) -} - -func (m *errorLoggingMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, options ...*collections.GetOptions) (collection *collections.Collection, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Get(ctx, spaceId, envId, collectionId, options...) -} - -func (m *errorLoggingMiddleware) List(ctx context.Context, spaceId string, envId string, filter *collections.Filter) (collections []*collections.Collection, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.List(ctx, spaceId, envId, filter) -} - -func (m *errorLoggingMiddleware) SetSchema(ctx context.Context, spaceId string, envId string, collectionId string, schema *schema.Schema) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.SetSchema(ctx, spaceId, envId, collectionId, schema) -} - -func (m *errorLoggingMiddleware) SetState(ctx context.Context, spaceId string, envId string, collectionId string, state *collections.StateInfo) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.SetState(ctx, spaceId, envId, collectionId, state) -} - -func (m *errorLoggingMiddleware) Update(ctx context.Context, coll *collections.Collection) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Update(ctx, coll) -} diff --git a/pkg/collections/middleware/logging_middleware.go b/pkg/collections/middleware/logging_middleware.go index bc3e41070fc56e0a4ec2a75f073f9696a88560fb..c5e2e2fb3e5bf604fdb57c8484f4a20289029da6 100644 --- a/pkg/collections/middleware/logging_middleware.go +++ b/pkg/collections/middleware/logging_middleware.go @@ -1,303 +1,140 @@ -package middleware - // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/access_log +// template: ../../../assets/templates/middleware/log.tmpl // gowrap: http://github.com/hexdigest/gowrap -//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/collections -i Collections -t ../../../assets/templates/middleware/access_log -o logging_middleware.go -l "" +package middleware + +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/collections -i Collections -t ../../../assets/templates/middleware/log.tmpl -o logging_middleware.go -l "" import ( "context" - "fmt" - "time" - "git.perx.ru/perxis/perxis-go/pkg/auth" + "git.perx.ru/perxis/perxis-go/id" "git.perx.ru/perxis/perxis-go/pkg/collections" "git.perx.ru/perxis/perxis-go/pkg/schema" + logzap "git.perx.ru/perxis/perxis-go/zap" "go.uber.org/zap" - "go.uber.org/zap/zapcore" ) -// loggingMiddleware implements collections.Collections that is instrumented with logging type loggingMiddleware struct { logger *zap.Logger next collections.Collections } -// LoggingMiddleware instruments an implementation of the collections.Collections with simple logging func LoggingMiddleware(logger *zap.Logger) Middleware { return func(next collections.Collections) collections.Collections { return &loggingMiddleware{ next: next, - logger: logger, + logger: logger.With(logzap.Component("collections")), } } } func (m *loggingMiddleware) Create(ctx context.Context, collection *collections.Collection) (created *collections.Collection, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "collection": collection} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Create.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(collections.EventCollectionCreate), + ) created, err = m.next.Create(ctx, collection) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to create", zap.Error(err), logzap.Object(collection), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - for k, v := range map[string]interface{}{ - "created": created, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Create.Response", fields...) - + logger.Info("Successfully created", logzap.Object(created), logzap.Channels(logzap.Userlog)) return created, err } func (m *loggingMiddleware) Delete(ctx context.Context, spaceId string, envId string, collectionId string) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Delete.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(collections.EventCollectionDelete), + logzap.Object(id.NewCollectionId(spaceId, envId, collectionId)), + ) err = m.next.Delete(ctx, spaceId, envId, collectionId) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to delete", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - m.logger.Debug("Delete.Response", fields...) - + logger.Info("Successfully deleted", logzap.Channels(logzap.Userlog)) return err } func (m *loggingMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, options ...*collections.GetOptions) (collection *collections.Collection, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Get.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + ) collection, err = m.next.Get(ctx, spaceId, envId, collectionId, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "collection": collection, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to get", zap.Error(err)) + return } - m.logger.Debug("Get.Response", fields...) - return collection, err } func (m *loggingMiddleware) List(ctx context.Context, spaceId string, envId string, filter *collections.Filter) (collections []*collections.Collection, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "filter": filter} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("List.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + ) collections, err = m.next.List(ctx, spaceId, envId, filter) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "collections": collections, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to list", zap.Error(err)) + return } - m.logger.Debug("List.Response", fields...) - return collections, err } func (m *loggingMiddleware) SetSchema(ctx context.Context, spaceId string, envId string, collectionId string, schema *schema.Schema) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "schema": schema} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("SetSchema.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(collections.EventCollectionSetSchema), + logzap.Object(id.NewCollectionId(spaceId, envId, collectionId)), + ) err = m.next.SetSchema(ctx, spaceId, envId, collectionId, schema) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to setschema", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("SetSchema.Response", fields...) - + logger.Info("Successfully setschemaed", logzap.Channels(logzap.Userlog)) return err } func (m *loggingMiddleware) SetState(ctx context.Context, spaceId string, envId string, collectionId string, state *collections.StateInfo) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "state": state} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("SetState.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + ) err = m.next.SetState(ctx, spaceId, envId, collectionId, state) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to setstate", zap.Error(err)) + return } - m.logger.Debug("SetState.Response", fields...) - return err } func (m *loggingMiddleware) Update(ctx context.Context, coll *collections.Collection) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "coll": coll} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Update.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(collections.EventCollectionUpdate), + logzap.Object(coll), + ) err = m.next.Update(ctx, coll) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to update", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Update.Response", fields...) - + logger.Info("Successfully updated", logzap.Channels(logzap.Userlog)) return err } diff --git a/pkg/collections/middleware/middleware.go b/pkg/collections/middleware/middleware.go index b581ce74b6071c707cc96fe9f11656bece37eb99..22514e7c93ec032847590821bfb2ba7467462f63 100644 --- a/pkg/collections/middleware/middleware.go +++ b/pkg/collections/middleware/middleware.go @@ -1,10 +1,10 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/middleware +// template: ../../../assets/templates/middleware/middleware.tmpl // gowrap: http://github.com/hexdigest/gowrap package middleware -//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/collections -i Collections -t ../../../assets/templates/middleware/middleware -o middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/collections -i Collections -t ../../../assets/templates/middleware/middleware.tmpl -o middleware.go -l "" import ( "git.perx.ru/perxis/perxis-go/pkg/collections" @@ -17,12 +17,11 @@ func WithLog(s collections.Collections, logger *zap.Logger, log_access bool) col if logger == nil { logger = zap.NewNop() } - logger = logger.Named("Collections") - s = ErrorLoggingMiddleware(logger)(s) if log_access { - s = LoggingMiddleware(logger)(s) + s = AccessLoggingMiddleware(logger)(s) } + s = LoggingMiddleware(logger)(s) s = RecoveringMiddleware(logger)(s) return s } diff --git a/pkg/delivery/transport/grpc/protobuf_type_converters.microgen.go b/pkg/delivery/transport/grpc/protobuf_type_converters.microgen.go index aedb4ff8a7612702413760f2a1276153c1571c9e..6961c709da405a34710e76ff6c1ad6f34c218f1b 100644 --- a/pkg/delivery/transport/grpc/protobuf_type_converters.microgen.go +++ b/pkg/delivery/transport/grpc/protobuf_type_converters.microgen.go @@ -302,39 +302,11 @@ func ProtoToPtrItemsFilter(protoFilter *itemspb.Filter) (*items.Filter, error) { } func PtrServicesFindOptionsToProto(options *services.FindOptions) (*common.FindOptions, error) { - if options == nil { - return nil, nil - } - return &common.FindOptions{ - Sort: options.Sort, - PageNum: int32(options.PageNum), - PageSize: int32(options.PageSize), - Offset: int32(options.Offset), - Limit: int32(options.Limit), - Fields: options.Fields, - ExcludeFields: options.ExcludeFields, - }, nil + return services.FindOptionsToPB(options), nil } func ProtoToPtrServicesFindOptions(protoOptions *common.FindOptions) (*services.FindOptions, error) { - if protoOptions == nil { - return nil, nil - } - return &services.FindOptions{ - SortOptions: services.SortOptions{ - Sort: protoOptions.Sort, - }, - PaginationOptions: services.PaginationOptions{ - PageNum: int(protoOptions.PageNum), - PageSize: int(protoOptions.PageSize), - Offset: int(protoOptions.Offset), - Limit: int(protoOptions.Limit), - }, - FieldOptions: services.FieldOptions{ - Fields: protoOptions.Fields, - ExcludeFields: protoOptions.ExcludeFields, - }, - }, nil + return services.FindOptionsFromPB(protoOptions), nil } func ListPtrItemsItemToProto(itms []*items.Item) ([]*itemspb.Item, error) { diff --git a/pkg/invitations/transport/grpc/protobuf_type_converters.microgen.go b/pkg/invitations/transport/grpc/protobuf_type_converters.microgen.go index ee7b788e2bf670b9f885c0fa3d9a52cbff30502e..1b222519b0aacc35feb180e0273ac9758394aefe 100644 --- a/pkg/invitations/transport/grpc/protobuf_type_converters.microgen.go +++ b/pkg/invitations/transport/grpc/protobuf_type_converters.microgen.go @@ -104,11 +104,18 @@ func PtrServicesFindOptionsToProto(opts *options.FindOptions) (*pb.FindOptions, if opts == nil { return nil, nil } - return &pb.FindOptions{ + + fo := &pb.FindOptions{ Sort: opts.Sort, - PageNum: int32(opts.PageNum), - PageSize: int32(opts.PageSize), - }, nil + PageSize: int32(opts.Limit), + } + + if opts.Limit != 0 { + // Потенциальная ошибка если offset не кратен limit + fo.PageNum = int32(opts.Offset / opts.Limit) + } + + return fo, nil } func ProtoToPtrServicesFindOptions(protoOpts *pb.FindOptions) (*options.FindOptions, error) { @@ -120,8 +127,8 @@ func ProtoToPtrServicesFindOptions(protoOpts *pb.FindOptions) (*options.FindOpti Sort: protoOpts.Sort, }, PaginationOptions: options.PaginationOptions{ - PageNum: int(protoOpts.PageNum), - PageSize: int(protoOpts.PageSize), + Limit: int(protoOpts.PageSize), + Offset: int(protoOpts.PageNum * protoOpts.PageSize), }, }, nil } diff --git a/pkg/items/dummy.go b/pkg/items/dummy.go deleted file mode 100644 index fc1f725abc3e5f9c16164daca30f3334c16f9f86..0000000000000000000000000000000000000000 --- a/pkg/items/dummy.go +++ /dev/null @@ -1,17 +0,0 @@ -package items - -import "context" - -type FindResultDummy struct { - Items []*Item - Total int - Error error -} -type Dummy struct { - Items - FindResult *FindResultDummy -} - -func (d *Dummy) Find(_ context.Context, _, _, _ string, _ *Filter, _ ...*FindOptions) ([]*Item, int, error) { - return d.FindResult.Items, d.FindResult.Total, d.FindResult.Error -} diff --git a/pkg/items/events.go b/pkg/items/events.go index b697d60733031bc259ce0d5b2efc24f2bb63bc94..9a1eb9249ff9224eaa217fdfd8bf1cb12c9d68fc 100644 --- a/pkg/items/events.go +++ b/pkg/items/events.go @@ -7,11 +7,14 @@ import ( ) const ( - EventCreateItem = "create_item" - EventUpdateItem = "update_item" - EventPublishItem = "publish_item" - EventUnpublishItem = "unpublish_item" - EventDeleteItem = "delete_item" + EventItemCreate = "create_item" + EventItemUpdate = "update_item" + EventItemPublish = "publish_item" + EventItemUnpublish = "unpublish_item" + EventItemDelete = "delete_item" + EventItemUndelete = "item_undelete" + EventItemArchive = "item_archive" + EventItemUnarchive = "item_unarchive" DefaultEventSubject = "content.{{.EventType}}.{{.SpaceID}}.{{.EnvID}}.{{.CollectionID}}.{{.ItemID}}" ) diff --git a/pkg/items/middleware/access_logging_middleware.go b/pkg/items/middleware/access_logging_middleware.go new file mode 100644 index 0000000000000000000000000000000000000000..2342a6d99249f427aa0f4ad6b4220a43ba872a4f --- /dev/null +++ b/pkg/items/middleware/access_logging_middleware.go @@ -0,0 +1,418 @@ +// Code generated by gowrap. DO NOT EDIT. +// template: ../../../assets/templates/middleware/access_log.tmpl +// gowrap: http://github.com/hexdigest/gowrap + +package middleware + +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/items -i Items -t ../../../assets/templates/middleware/access_log.tmpl -o access_logging_middleware.go -l "" + +import ( + "context" + "time" + + "git.perx.ru/perxis/perxis-go/pkg/auth" + "git.perx.ru/perxis/perxis-go/pkg/items" + "git.perx.ru/perxis/perxis-go/pkg/schema" + "go.uber.org/zap" +) + +// accessLoggingMiddleware implements items.Items that is instrumented with logging +type accessLoggingMiddleware struct { + logger *zap.Logger + next items.Items +} + +// AccessLoggingMiddleware instruments an implementation of the items.Items with simple logging +func AccessLoggingMiddleware(logger *zap.Logger) Middleware { + return func(next items.Items) items.Items { + return &accessLoggingMiddleware{ + next: next, + logger: logger, + } + } +} + +func (m *accessLoggingMiddleware) Aggregate(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregateOptions) (result map[string]interface{}, err error) { + begin := time.Now() + + m.logger.Debug("Aggregate.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("filter", filter), + zap.Reflect("options", options), + ) + + result, err = m.next.Aggregate(ctx, spaceId, envId, collectionId, filter, options...) + + m.logger.Debug("Aggregate.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("result", result), + zap.Error(err), + ) + + return result, err +} + +func (m *accessLoggingMiddleware) AggregatePublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregatePublishedOptions) (result map[string]interface{}, err error) { + begin := time.Now() + + m.logger.Debug("AggregatePublished.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("filter", filter), + zap.Reflect("options", options), + ) + + result, err = m.next.AggregatePublished(ctx, spaceId, envId, collectionId, filter, options...) + + m.logger.Debug("AggregatePublished.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("result", result), + zap.Error(err), + ) + + return result, err +} + +func (m *accessLoggingMiddleware) Archive(ctx context.Context, item *items.Item, options ...*items.ArchiveOptions) (err error) { + begin := time.Now() + + m.logger.Debug("Archive.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("item", item), + zap.Reflect("options", options), + ) + + err = m.next.Archive(ctx, item, options...) + + m.logger.Debug("Archive.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} + +func (m *accessLoggingMiddleware) Create(ctx context.Context, item *items.Item, opts ...*items.CreateOptions) (created *items.Item, err error) { + begin := time.Now() + + m.logger.Debug("Create.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("item", item), + zap.Reflect("opts", opts), + ) + + created, err = m.next.Create(ctx, item, opts...) + + m.logger.Debug("Create.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("created", created), + zap.Error(err), + ) + + return created, err +} + +func (m *accessLoggingMiddleware) Delete(ctx context.Context, item *items.Item, options ...*items.DeleteOptions) (err error) { + begin := time.Now() + + m.logger.Debug("Delete.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("item", item), + zap.Reflect("options", options), + ) + + err = m.next.Delete(ctx, item, options...) + + m.logger.Debug("Delete.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} + +func (m *accessLoggingMiddleware) Find(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindOptions) (items []*items.Item, total int, err error) { + begin := time.Now() + + m.logger.Debug("Find.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("filter", filter), + zap.Reflect("options", options), + ) + + items, total, err = m.next.Find(ctx, spaceId, envId, collectionId, filter, options...) + + m.logger.Debug("Find.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("items", items), + zap.Reflect("total", total), + zap.Error(err), + ) + + return items, total, err +} + +func (m *accessLoggingMiddleware) FindArchived(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindArchivedOptions) (items []*items.Item, total int, err error) { + begin := time.Now() + + m.logger.Debug("FindArchived.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("filter", filter), + zap.Reflect("options", options), + ) + + items, total, err = m.next.FindArchived(ctx, spaceId, envId, collectionId, filter, options...) + + m.logger.Debug("FindArchived.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("items", items), + zap.Reflect("total", total), + zap.Error(err), + ) + + return items, total, err +} + +func (m *accessLoggingMiddleware) FindPublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindPublishedOptions) (items []*items.Item, total int, err error) { + begin := time.Now() + + m.logger.Debug("FindPublished.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("filter", filter), + zap.Reflect("options", options), + ) + + items, total, err = m.next.FindPublished(ctx, spaceId, envId, collectionId, filter, options...) + + m.logger.Debug("FindPublished.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("items", items), + zap.Reflect("total", total), + zap.Error(err), + ) + + return items, total, err +} + +func (m *accessLoggingMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetOptions) (item *items.Item, err error) { + begin := time.Now() + + m.logger.Debug("Get.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("itemId", itemId), + zap.Reflect("options", options), + ) + + item, err = m.next.Get(ctx, spaceId, envId, collectionId, itemId, options...) + + m.logger.Debug("Get.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("item", item), + zap.Error(err), + ) + + return item, err +} + +func (m *accessLoggingMiddleware) GetPublished(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetPublishedOptions) (item *items.Item, err error) { + begin := time.Now() + + m.logger.Debug("GetPublished.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("itemId", itemId), + zap.Reflect("options", options), + ) + + item, err = m.next.GetPublished(ctx, spaceId, envId, collectionId, itemId, options...) + + m.logger.Debug("GetPublished.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("item", item), + zap.Error(err), + ) + + return item, err +} + +func (m *accessLoggingMiddleware) GetRevision(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, revisionId string, options ...*items.GetRevisionOptions) (item *items.Item, err error) { + begin := time.Now() + + m.logger.Debug("GetRevision.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("itemId", itemId), + zap.Reflect("revisionId", revisionId), + zap.Reflect("options", options), + ) + + item, err = m.next.GetRevision(ctx, spaceId, envId, collectionId, itemId, revisionId, options...) + + m.logger.Debug("GetRevision.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("item", item), + zap.Error(err), + ) + + return item, err +} + +func (m *accessLoggingMiddleware) Introspect(ctx context.Context, item *items.Item, opts ...*items.IntrospectOptions) (itm *items.Item, sch *schema.Schema, err error) { + begin := time.Now() + + m.logger.Debug("Introspect.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("item", item), + zap.Reflect("opts", opts), + ) + + itm, sch, err = m.next.Introspect(ctx, item, opts...) + + m.logger.Debug("Introspect.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("itm", itm), + zap.Reflect("sch", sch), + zap.Error(err), + ) + + return itm, sch, err +} + +func (m *accessLoggingMiddleware) ListRevisions(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.ListRevisionsOptions) (items []*items.Item, err error) { + begin := time.Now() + + m.logger.Debug("ListRevisions.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("spaceId", spaceId), + zap.Reflect("envId", envId), + zap.Reflect("collectionId", collectionId), + zap.Reflect("itemId", itemId), + zap.Reflect("options", options), + ) + + items, err = m.next.ListRevisions(ctx, spaceId, envId, collectionId, itemId, options...) + + m.logger.Debug("ListRevisions.Response", + zap.Duration("time", time.Since(begin)), + zap.Reflect("items", items), + zap.Error(err), + ) + + return items, err +} + +func (m *accessLoggingMiddleware) Publish(ctx context.Context, item *items.Item, options ...*items.PublishOptions) (err error) { + begin := time.Now() + + m.logger.Debug("Publish.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("item", item), + zap.Reflect("options", options), + ) + + err = m.next.Publish(ctx, item, options...) + + m.logger.Debug("Publish.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} + +func (m *accessLoggingMiddleware) Unarchive(ctx context.Context, item *items.Item, options ...*items.UnarchiveOptions) (err error) { + begin := time.Now() + + m.logger.Debug("Unarchive.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("item", item), + zap.Reflect("options", options), + ) + + err = m.next.Unarchive(ctx, item, options...) + + m.logger.Debug("Unarchive.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} + +func (m *accessLoggingMiddleware) Undelete(ctx context.Context, item *items.Item, options ...*items.UndeleteOptions) (err error) { + begin := time.Now() + + m.logger.Debug("Undelete.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("item", item), + zap.Reflect("options", options), + ) + + err = m.next.Undelete(ctx, item, options...) + + m.logger.Debug("Undelete.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} + +func (m *accessLoggingMiddleware) Unpublish(ctx context.Context, item *items.Item, options ...*items.UnpublishOptions) (err error) { + begin := time.Now() + + m.logger.Debug("Unpublish.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("item", item), + zap.Reflect("options", options), + ) + + err = m.next.Unpublish(ctx, item, options...) + + m.logger.Debug("Unpublish.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} + +func (m *accessLoggingMiddleware) Update(ctx context.Context, item *items.Item, options ...*items.UpdateOptions) (err error) { + begin := time.Now() + + m.logger.Debug("Update.Request", + zap.Reflect("principal", auth.GetPrincipal(ctx)), + zap.Reflect("item", item), + zap.Reflect("options", options), + ) + + err = m.next.Update(ctx, item, options...) + + m.logger.Debug("Update.Response", + zap.Duration("time", time.Since(begin)), + zap.Error(err), + ) + + return err +} diff --git a/pkg/items/middleware/error_logging_middleware.go b/pkg/items/middleware/error_logging_middleware.go deleted file mode 100644 index 345d22ca2727d1516e4a7176e885195ab38f1d20..0000000000000000000000000000000000000000 --- a/pkg/items/middleware/error_logging_middleware.go +++ /dev/null @@ -1,211 +0,0 @@ -// Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/error_log -// gowrap: http://github.com/hexdigest/gowrap - -package middleware - -//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/items -i Items -t ../../../assets/templates/middleware/error_log -o error_logging_middleware.go -l "" - -import ( - "context" - - "git.perx.ru/perxis/perxis-go/pkg/items" - "git.perx.ru/perxis/perxis-go/pkg/schema" - "go.uber.org/zap" -) - -// errorLoggingMiddleware implements items.Items that is instrumented with logging -type errorLoggingMiddleware struct { - logger *zap.Logger - next items.Items -} - -// ErrorLoggingMiddleware instruments an implementation of the items.Items with simple logging -func ErrorLoggingMiddleware(logger *zap.Logger) Middleware { - return func(next items.Items) items.Items { - return &errorLoggingMiddleware{ - next: next, - logger: logger, - } - } -} - -func (m *errorLoggingMiddleware) Aggregate(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregateOptions) (result map[string]interface{}, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Aggregate(ctx, spaceId, envId, collectionId, filter, options...) -} - -func (m *errorLoggingMiddleware) AggregatePublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregatePublishedOptions) (result map[string]interface{}, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.AggregatePublished(ctx, spaceId, envId, collectionId, filter, options...) -} - -func (m *errorLoggingMiddleware) Archive(ctx context.Context, item *items.Item, options ...*items.ArchiveOptions) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Archive(ctx, item, options...) -} - -func (m *errorLoggingMiddleware) Create(ctx context.Context, item *items.Item, opts ...*items.CreateOptions) (created *items.Item, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Create(ctx, item, opts...) -} - -func (m *errorLoggingMiddleware) Delete(ctx context.Context, item *items.Item, options ...*items.DeleteOptions) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Delete(ctx, item, options...) -} - -func (m *errorLoggingMiddleware) Find(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindOptions) (items []*items.Item, total int, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Find(ctx, spaceId, envId, collectionId, filter, options...) -} - -func (m *errorLoggingMiddleware) FindArchived(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindArchivedOptions) (items []*items.Item, total int, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.FindArchived(ctx, spaceId, envId, collectionId, filter, options...) -} - -func (m *errorLoggingMiddleware) FindPublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindPublishedOptions) (items []*items.Item, total int, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.FindPublished(ctx, spaceId, envId, collectionId, filter, options...) -} - -func (m *errorLoggingMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetOptions) (item *items.Item, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Get(ctx, spaceId, envId, collectionId, itemId, options...) -} - -func (m *errorLoggingMiddleware) GetPublished(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetPublishedOptions) (item *items.Item, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.GetPublished(ctx, spaceId, envId, collectionId, itemId, options...) -} - -func (m *errorLoggingMiddleware) GetRevision(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, revisionId string, options ...*items.GetRevisionOptions) (item *items.Item, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.GetRevision(ctx, spaceId, envId, collectionId, itemId, revisionId, options...) -} - -func (m *errorLoggingMiddleware) Introspect(ctx context.Context, item *items.Item, opts ...*items.IntrospectOptions) (itm *items.Item, sch *schema.Schema, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Introspect(ctx, item, opts...) -} - -func (m *errorLoggingMiddleware) ListRevisions(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.ListRevisionsOptions) (items []*items.Item, err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.ListRevisions(ctx, spaceId, envId, collectionId, itemId, options...) -} - -func (m *errorLoggingMiddleware) Publish(ctx context.Context, item *items.Item, options ...*items.PublishOptions) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Publish(ctx, item, options...) -} - -func (m *errorLoggingMiddleware) Unarchive(ctx context.Context, item *items.Item, options ...*items.UnarchiveOptions) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Unarchive(ctx, item, options...) -} - -func (m *errorLoggingMiddleware) Undelete(ctx context.Context, item *items.Item, options ...*items.UndeleteOptions) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Undelete(ctx, item, options...) -} - -func (m *errorLoggingMiddleware) Unpublish(ctx context.Context, item *items.Item, options ...*items.UnpublishOptions) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Unpublish(ctx, item, options...) -} - -func (m *errorLoggingMiddleware) Update(ctx context.Context, item *items.Item, options ...*items.UpdateOptions) (err error) { - logger := m.logger - defer func() { - if err != nil { - logger.Warn("response error", zap.Error(err)) - } - }() - return m.next.Update(ctx, item, options...) -} diff --git a/pkg/items/middleware/logging_middleware.go b/pkg/items/middleware/logging_middleware.go index 6ed28f90053eab68a44b1e5ac79d5228d7bfe9be..8870912f5ee01671c026431c80fe1e091b36bbdd 100644 --- a/pkg/items/middleware/logging_middleware.go +++ b/pkg/items/middleware/logging_middleware.go @@ -1,744 +1,306 @@ -// Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/access_log -// gowrap: http://github.com/hexdigest/gowrap - package middleware -//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/items -i Items -t ../../../assets/templates/middleware/access_log -o logging_middleware.go -l "" - import ( "context" - "fmt" - "time" - "git.perx.ru/perxis/perxis-go/pkg/auth" + "git.perx.ru/perxis/perxis-go/id" "git.perx.ru/perxis/perxis-go/pkg/items" "git.perx.ru/perxis/perxis-go/pkg/schema" + logzap "git.perx.ru/perxis/perxis-go/zap" "go.uber.org/zap" - "go.uber.org/zap/zapcore" ) -// loggingMiddleware implements items.Items that is instrumented with logging type loggingMiddleware struct { logger *zap.Logger next items.Items } -// LoggingMiddleware instruments an implementation of the items.Items with simple logging func LoggingMiddleware(logger *zap.Logger) Middleware { return func(next items.Items) items.Items { return &loggingMiddleware{ next: next, - logger: logger, + logger: logger.With(logzap.Component("items")), } } } func (m *loggingMiddleware) Aggregate(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregateOptions) (result map[string]interface{}, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "filter": filter, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Aggregate.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + ) result, err = m.next.Aggregate(ctx, spaceId, envId, collectionId, filter, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to aggregate", zap.Error(err)) + return } - for k, v := range map[string]interface{}{ - "result": result, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Aggregate.Response", fields...) - return result, err } func (m *loggingMiddleware) AggregatePublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregatePublishedOptions) (result map[string]interface{}, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "filter": filter, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("AggregatePublished.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + ) result, err = m.next.AggregatePublished(ctx, spaceId, envId, collectionId, filter, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to aggregate_published", zap.Error(err)) + return } - for k, v := range map[string]interface{}{ - "result": result, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("AggregatePublished.Response", fields...) - return result, err } func (m *loggingMiddleware) Archive(ctx context.Context, item *items.Item, options ...*items.ArchiveOptions) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "item": item, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Archive.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(items.EventItemArchive), + logzap.Object(item), + ) err = m.next.Archive(ctx, item, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to archive", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Archive.Response", fields...) - + logger.Info("Successfully archived", logzap.Channels(logzap.Userlog)) return err } func (m *loggingMiddleware) Create(ctx context.Context, item *items.Item, opts ...*items.CreateOptions) (created *items.Item, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "item": item, - "opts": opts} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Create.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(items.EventItemCreate), + ) created, err = m.next.Create(ctx, item, opts...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "created": created, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to create", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog), logzap.Object(item)) + return } - m.logger.Debug("Create.Response", fields...) - + logger.Info("Successfully created", logzap.Channels(logzap.Userlog), logzap.Object(created)) return created, err } func (m *loggingMiddleware) Delete(ctx context.Context, item *items.Item, options ...*items.DeleteOptions) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "item": item, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Delete.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(items.EventItemDelete), + logzap.Object(item), + ) err = m.next.Delete(ctx, item, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to delete", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Delete.Response", fields...) - + logger.Info("Successfully deleted", logzap.Channels(logzap.Userlog)) return err } func (m *loggingMiddleware) Find(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindOptions) (items []*items.Item, total int, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "filter": filter, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Find.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + ) items, total, err = m.next.Find(ctx, spaceId, envId, collectionId, filter, options...) - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "items": items, - "total": total, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to find", zap.Error(err)) + return } - m.logger.Debug("Find.Response", fields...) - return items, total, err } func (m *loggingMiddleware) FindArchived(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindArchivedOptions) (items []*items.Item, total int, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "filter": filter, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("FindArchived.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + ) items, total, err = m.next.FindArchived(ctx, spaceId, envId, collectionId, filter, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "items": items, - "total": total, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to find_archived", zap.Error(err)) + return } - m.logger.Debug("FindArchived.Response", fields...) - return items, total, err } func (m *loggingMiddleware) FindPublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindPublishedOptions) (items []*items.Item, total int, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "filter": filter, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("FindPublished.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + ) items, total, err = m.next.FindPublished(ctx, spaceId, envId, collectionId, filter, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "items": items, - "total": total, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to findpublished", zap.Error(err)) + return } - m.logger.Debug("FindPublished.Response", fields...) - return items, total, err } func (m *loggingMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetOptions) (item *items.Item, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "itemId": itemId, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Get.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)), + ) item, err = m.next.Get(ctx, spaceId, envId, collectionId, itemId, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to get", zap.Error(err)) + return } - for k, v := range map[string]interface{}{ - "item": item, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Get.Response", fields...) - return item, err } func (m *loggingMiddleware) GetPublished(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetPublishedOptions) (item *items.Item, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "itemId": itemId, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("GetPublished.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)), + ) item, err = m.next.GetPublished(ctx, spaceId, envId, collectionId, itemId, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to get published", zap.Error(err)) + return } - for k, v := range map[string]interface{}{ - "item": item, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("GetPublished.Response", fields...) - return item, err } func (m *loggingMiddleware) GetRevision(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, revisionId string, options ...*items.GetRevisionOptions) (item *items.Item, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "itemId": itemId, - "revisionId": revisionId, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("GetRevision.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)), + ) item, err = m.next.GetRevision(ctx, spaceId, envId, collectionId, itemId, revisionId, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to get revision", zap.Error(err)) + return } - for k, v := range map[string]interface{}{ - "item": item, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("GetRevision.Response", fields...) - return item, err } func (m *loggingMiddleware) Introspect(ctx context.Context, item *items.Item, opts ...*items.IntrospectOptions) (itm *items.Item, sch *schema.Schema, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "item": item, - "opts": opts} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Introspect.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Object(item), + ) itm, sch, err = m.next.Introspect(ctx, item, opts...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "itm": itm, - "sch": sch, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to introspect", zap.Error(err)) + return } - m.logger.Debug("Introspect.Response", fields...) - return itm, sch, err } func (m *loggingMiddleware) ListRevisions(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.ListRevisionsOptions) (items []*items.Item, err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "spaceId": spaceId, - "envId": envId, - "collectionId": collectionId, - "itemId": itemId, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("ListRevisions.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)), + ) items, err = m.next.ListRevisions(ctx, spaceId, envId, collectionId, itemId, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to list revisions", zap.Error(err)) + return } - for k, v := range map[string]interface{}{ - "items": items, - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("ListRevisions.Response", fields...) - return items, err } func (m *loggingMiddleware) Publish(ctx context.Context, item *items.Item, options ...*items.PublishOptions) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "item": item, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Publish.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(items.EventItemPublish), + logzap.Object(item), + ) err = m.next.Publish(ctx, item, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to publish", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Publish.Response", fields...) - + logger.Info("Successfully published", logzap.Channels(logzap.Userlog)) return err } func (m *loggingMiddleware) Unarchive(ctx context.Context, item *items.Item, options ...*items.UnarchiveOptions) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "item": item, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Unarchive.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(items.EventItemUnarchive), + logzap.Object(item), + ) err = m.next.Unarchive(ctx, item, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to unarchive", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - m.logger.Debug("Unarchive.Response", fields...) - + logger.Info("Successfully unarchived", logzap.Channels(logzap.Userlog)) return err } func (m *loggingMiddleware) Undelete(ctx context.Context, item *items.Item, options ...*items.UndeleteOptions) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "item": item, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Undelete.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(items.EventItemUndelete), + logzap.Object(item), + ) err = m.next.Undelete(ctx, item, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to undelete", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - m.logger.Debug("Undelete.Response", fields...) - + logger.Info("Successfully undeleted", logzap.Channels(logzap.Userlog)) return err } func (m *loggingMiddleware) Unpublish(ctx context.Context, item *items.Item, options ...*items.UnpublishOptions) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "item": item, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Unpublish.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(items.EventItemUnpublish), + logzap.Object(item), + ) err = m.next.Unpublish(ctx, item, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), - } - - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) + if err != nil { + logger.Error("Failed to unpublish", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - m.logger.Debug("Unpublish.Response", fields...) - + logger.Info("Successfully unpublished", logzap.Channels(logzap.Userlog)) return err } func (m *loggingMiddleware) Update(ctx context.Context, item *items.Item, options ...*items.UpdateOptions) (err error) { - begin := time.Now() - var fields []zapcore.Field - for k, v := range map[string]interface{}{ - "ctx": ctx, - "item": item, - "options": options} { - if k == "ctx" { - fields = append(fields, zap.String("principal", fmt.Sprint(auth.GetPrincipal(ctx)))) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Update.Request", fields...) + logger := m.logger.With( + logzap.CallerFromContext(ctx), + logzap.Event(items.EventItemUpdate), + logzap.Object(item), + ) err = m.next.Update(ctx, item, options...) - - fields = []zapcore.Field{ - zap.Duration("time", time.Since(begin)), + if err != nil { + logger.Error("Failed to update", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog)) + return } - for k, v := range map[string]interface{}{ - "err": err} { - if k == "err" { - err, _ := v.(error) - fields = append(fields, zap.Error(err)) - continue - } - fields = append(fields, zap.Reflect(k, v)) - } - - m.logger.Debug("Update.Response", fields...) - + logger.Info("Successfully updated", logzap.Channels(logzap.Userlog)) return err } diff --git a/pkg/items/middleware/middleware.go b/pkg/items/middleware/middleware.go index 52a1c1218d1605dc52ae80342684bb0339e63103..2ce07ef94ff532af1ed3353ef5bdba6e5f6871aa 100644 --- a/pkg/items/middleware/middleware.go +++ b/pkg/items/middleware/middleware.go @@ -1,10 +1,10 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/middleware +// template: ../../../assets/templates/middleware/middleware.tmpl // gowrap: http://github.com/hexdigest/gowrap package middleware -//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/items -i Items -t ../../../assets/templates/middleware/middleware -o middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/items -i Items -t ../../../assets/templates/middleware/middleware.tmpl -o middleware.go -l "" import ( "git.perx.ru/perxis/perxis-go/pkg/items" @@ -17,12 +17,11 @@ func WithLog(s items.Items, logger *zap.Logger, log_access bool) items.Items { if logger == nil { logger = zap.NewNop() } - logger = logger.Named("Items") - s = ErrorLoggingMiddleware(logger)(s) if log_access { - s = LoggingMiddleware(logger)(s) + s = AccessLoggingMiddleware(logger)(s) } + s = LoggingMiddleware(logger)(s) s = RecoveringMiddleware(logger)(s) return s } diff --git a/pkg/items/pagination.go b/pkg/items/pagination.go index 1910a34ba67c21cb1ebf54923ebe750af0fd10d2..c8c4bb16d2da0d2d10e3d98422aaf345ffbf7c21 100644 --- a/pkg/items/pagination.go +++ b/pkg/items/pagination.go @@ -16,9 +16,7 @@ type BatchProcessor struct { FindPublishedOptions *FindPublishedOptions Filter *Filter - // Deprecated использовать offset, limit - pageSize, pageNum int - + limit int sort []string processed int } @@ -39,7 +37,7 @@ func (b *BatchProcessor) getBatch(ctx context.Context) ([]*Item, bool, error) { Regular: b.FindPublishedOptions.Regular, Hidden: b.FindPublishedOptions.Hidden, Templates: b.FindPublishedOptions.Templates, - FindOptions: *options.NewFindOptions(b.pageNum, b.pageSize, b.sort...), + FindOptions: *options.New(b.processed, b.limit, b.sort...), }, ) } else { @@ -54,14 +52,13 @@ func (b *BatchProcessor) getBatch(ctx context.Context) ([]*Item, bool, error) { Regular: b.FindOptions.Regular, Hidden: b.FindOptions.Hidden, Templates: b.FindOptions.Templates, - FindOptions: *options.NewFindOptions(b.pageNum, b.pageSize, b.sort...), + FindOptions: *options.New(b.processed, b.limit, b.sort...), }, ) } if err == nil { b.processed += len(res) - b.pageNum++ } return res, b.processed != total, err @@ -86,32 +83,29 @@ func (b *BatchProcessor) next(ctx context.Context) (res []*Item, next bool, err } func (b *BatchProcessor) reducePageSize() bool { - if b.pageSize == 1 { + if b.limit == 1 { return false } - b.pageNum = 2 * b.pageNum - b.pageSize = b.pageSize / 2 - + b.limit /= 2 return true } func (b *BatchProcessor) Do(ctx context.Context, f func(batch []*Item) error) (int, error) { - if b.FindOptions == nil && b.FindPublishedOptions == nil { b.FindOptions = new(FindOptions) } if b.FindOptions != nil { - b.pageSize = b.FindOptions.PageSize + b.limit = b.FindOptions.Limit b.sort = b.FindOptions.Sort } if b.FindPublishedOptions != nil { - b.pageSize = b.FindPublishedOptions.PageSize + b.limit = b.FindPublishedOptions.Limit b.sort = b.FindPublishedOptions.Sort } - if b.pageSize == 0 { - b.pageSize = 128 + if b.limit == 0 { + b.limit = 128 } if b.Filter != nil && (len(b.Filter.ID) > 0 || len(b.Filter.Q) > 0) && !data.Contains("_id", b.sort) { diff --git a/pkg/items/pagination_test.go b/pkg/items/pagination_test.go index bf13af39e00bd19550ddd49bae3e165b5cfa9fff..008b17795cc1c57d4e2dcf6bb3507bee8b3f1646 100644 --- a/pkg/items/pagination_test.go +++ b/pkg/items/pagination_test.go @@ -11,25 +11,51 @@ import ( ) func TestBatchProcessor(t *testing.T) { + t.Run("EmptyResults", func(t *testing.T) { + itemssvc := &Stub{ + FindResult: func(req StubFindRequest) StubFindResult { + return StubFindResult{Items: nil, Total: 0, Error: nil} + }, + } - itemssvc := &Dummy{FindResult: &FindResultDummy{Items: nil, Total: 0, Error: nil}} + b := &BatchProcessor{ + Items: itemssvc, + SpaceID: "sp", + EnvID: environments.DefaultEnvironment, + CollectionID: "col", + FindOptions: &FindOptions{ + Regular: true, + Hidden: true, + Templates: true, + FindOptions: *options.NewFindOptions(0, 10), + }, + Filter: NewFilter("a > 5"), + } - b := &BatchProcessor{ - Items: itemssvc, - SpaceID: "sp", - EnvID: environments.DefaultEnvironment, - CollectionID: "col", - FindOptions: &FindOptions{ - Regular: true, - Hidden: true, - Templates: true, - FindOptions: *options.NewFindOptions(0, 10), - }, - Filter: NewFilter("a > 5"), - } + var counter int + _, err := b.Do(context.Background(), func(batch []*Item) error { counter++; return nil }) + require.NoError(t, err) + assert.Equal(t, 0, counter) + }) - var counter int - _, err := b.Do(context.Background(), func(batch []*Item) error { counter++; return nil }) - require.NoError(t, err) - assert.Equal(t, 0, counter) + t.Run("With FindOptions", func(t *testing.T) { + itemssvc := &Stub{ + FindResult: func(req StubFindRequest) StubFindResult { + fo := MergeFindOptions(req.Options...) + return StubFindResult{Items: make([]*Item, fo.Limit), Total: 1000, Error: nil} + }, + } + b := &BatchProcessor{ + Items: itemssvc, + SpaceID: "sp", + EnvID: environments.DefaultEnvironment, + CollectionID: "col", + FindOptions: &FindOptions{FindOptions: *options.New(0, 25)}, + } + + var counter int + _, err := b.Do(context.Background(), func(batch []*Item) error { counter++; return nil }) + require.NoError(t, err) + assert.Equal(t, 1000/25, counter) + }) } diff --git a/pkg/items/stub.go b/pkg/items/stub.go new file mode 100644 index 0000000000000000000000000000000000000000..33573514b655a6084f636403a581bad46b130172 --- /dev/null +++ b/pkg/items/stub.go @@ -0,0 +1,35 @@ +package items + +import ( + "context" +) + +type StubFindRequest struct { + Context context.Context + SpaceID, EnvID, CollID string + Filter *Filter + Options []*FindOptions +} + +type StubFindResult struct { + Items []*Item + Total int + Error error +} + +type Stub struct { + Items + FindResult func(req StubFindRequest) StubFindResult +} + +func (d *Stub) Find(ctx context.Context, spaceID, envID, collID string, filter *Filter, opts ...*FindOptions) ([]*Item, int, error) { + res := d.FindResult(StubFindRequest{ + Context: ctx, + SpaceID: spaceID, + EnvID: envID, + CollID: collID, + Filter: filter, + Options: opts, + }) + return res.Items, res.Total, res.Error +} diff --git a/pkg/items/transport/grpc/protobuf_type_converters.microgen.go b/pkg/items/transport/grpc/protobuf_type_converters.microgen.go index 0b214cc93c44392ad1490ced7665dd1b595b76b3..ade05bfffeb4a1c745f80338e7faac2287b067a2 100644 --- a/pkg/items/transport/grpc/protobuf_type_converters.microgen.go +++ b/pkg/items/transport/grpc/protobuf_type_converters.microgen.go @@ -144,39 +144,11 @@ func ProtoToPtrFilter(protoFilter *pb.Filter) (*service.Filter, error) { } func PtrServicesFindOptionsToProto(opts *options.FindOptions) (*pbcommon.FindOptions, error) { - if opts == nil { - return nil, nil - } - return &pbcommon.FindOptions{ - Sort: opts.Sort, - PageNum: int32(opts.PageNum), - PageSize: int32(opts.PageSize), - Offset: int32(opts.Offset), - Limit: int32(opts.Limit), - Fields: opts.Fields, - ExcludeFields: opts.ExcludeFields, - }, nil + return options.FindOptionsToPB(opts), nil } func ProtoToPtrServicesFindOptions(protoOpts *pbcommon.FindOptions) (*options.FindOptions, error) { - if protoOpts == nil { - return nil, nil - } - return &options.FindOptions{ - SortOptions: options.SortOptions{ - Sort: protoOpts.Sort, - }, - PaginationOptions: options.PaginationOptions{ - PageNum: int(protoOpts.PageNum), - PageSize: int(protoOpts.PageSize), - Offset: int(protoOpts.Offset), - Limit: int(protoOpts.Limit), - }, - FieldOptions: options.FieldOptions{ - Fields: protoOpts.Fields, - ExcludeFields: protoOpts.ExcludeFields, - }, - }, nil + return options.FindOptionsFromPB(protoOpts), nil } func ListPtrItemToProto(items []*service.Item) ([]*pb.Item, error) { diff --git a/pkg/options/options.go b/pkg/options/options.go index 066d3f8aa347a4b08fb901c87e2fc9afee7aa15f..d18ca338c01a7d0e2117a0e09f47d1a21421bdd1 100644 --- a/pkg/options/options.go +++ b/pkg/options/options.go @@ -13,10 +13,6 @@ type SortOptions struct { // PaginationOptions настройки возвращаемых страниц результатов type PaginationOptions struct { - //Deprecated - PageNum int - PageSize int - Limit int Offset int } @@ -39,12 +35,18 @@ type FindOptions struct { FieldOptions } +// Deprecated использовать New // NewFindOptions создает новые результаты поиска func NewFindOptions(pageNum, pageSize int, sort ...string) *FindOptions { + return New(pageNum*pageSize, pageSize, sort...) +} + +// New создает новые параметры поиска +func New(offset, limit int, sort ...string) *FindOptions { return &FindOptions{ PaginationOptions: PaginationOptions{ - PageNum: pageNum, - PageSize: pageSize, + Offset: offset, + Limit: limit, }, SortOptions: SortOptions{ Sort: sort, @@ -95,8 +97,8 @@ func FindOptionsFromPB(protoOpts *commonpb.FindOptions) *FindOptions { Sort: protoOpts.Sort, }, PaginationOptions: PaginationOptions{ - Offset: int(protoOpts.Offset), - Limit: int(protoOpts.Limit), + Limit: int(protoOpts.Limit), + Offset: int(protoOpts.Offset), }, FieldOptions: FieldOptions{ Fields: protoOpts.Fields, @@ -104,9 +106,9 @@ func FindOptionsFromPB(protoOpts *commonpb.FindOptions) *FindOptions { }, } - if fo.Offset == 0 && fo.Limit == 0 && fo.PageSize != 0 { - fo.Offset = fo.PageSize * (fo.PageNum - 1) - fo.Limit = fo.PageSize + if fo.Offset == 0 && fo.Limit == 0 { + fo.Offset = int(protoOpts.PageSize * protoOpts.PageNum) + fo.Limit = int(protoOpts.PageSize) } return fo @@ -118,21 +120,11 @@ func FindOptionsToPB(opts *FindOptions) *commonpb.FindOptions { } fo := &commonpb.FindOptions{ Sort: opts.Sort, - PageNum: int32(opts.PageNum), - PageSize: int32(opts.PageSize), Offset: int32(opts.Offset), Limit: int32(opts.Limit), Fields: opts.Fields, ExcludeFields: opts.ExcludeFields, } - if fo.PageSize != 0 && fo.Limit == 0 { - fo.Limit = fo.PageSize - fo.Offset = fo.PageSize * (fo.PageNum - 1) - } - if fo.Limit != 0 && fo.PageSize == 0 { - fo.PageSize = fo.Limit - fo.PageNum = fo.Offset / fo.Limit - } return fo } @@ -156,11 +148,9 @@ func MergeSortOptions(options ...SortOptions) SortOptions { func MergePaginationOptions(options ...PaginationOptions) PaginationOptions { fo := PaginationOptions{} for _, opt := range options { - if opt.PageSize == 0 && opt.PageNum == 0 && opt.Offset == 0 && opt.Limit == 0 { + if opt.Offset == 0 && opt.Limit == 0 { continue } - fo.PageNum = opt.PageNum - fo.PageSize = opt.PageSize fo.Offset = opt.Offset fo.Limit = opt.Limit } diff --git a/pkg/options/options_test.go b/pkg/options/options_test.go index 981849a0e2625a8bd7e796a22eaa8529d606ef01..d2227a875a837c67006eab028f235afcbd1efe5e 100644 --- a/pkg/options/options_test.go +++ b/pkg/options/options_test.go @@ -7,7 +7,6 @@ import ( ) func TestOptions_MergePaginationOptions(t *testing.T) { - var tt = []struct { name string options []PaginationOptions @@ -24,29 +23,29 @@ func TestOptions_MergePaginationOptions(t *testing.T) { expected: PaginationOptions{}, }, { - name: "One option", - options: []PaginationOptions{{PageNum: 10, PageSize: 100}}, - expected: PaginationOptions{PageNum: 10, PageSize: 100}, + name: "One limit/offset option", + options: []PaginationOptions{{Limit: 10, Offset: 100}}, + expected: PaginationOptions{Limit: 10, Offset: 100}, }, { - name: "Merge #1", - options: []PaginationOptions{{PageNum: 0, PageSize: 0}, {PageNum: 10, PageSize: 100}}, - expected: PaginationOptions{PageNum: 10, PageSize: 100}, + name: "Merge limit/offset #1", + options: []PaginationOptions{{Limit: 0, Offset: 0}, {Limit: 10, Offset: 100}}, + expected: PaginationOptions{Limit: 10, Offset: 100}, }, { - name: "Merge #2", - options: []PaginationOptions{{PageNum: 10, PageSize: 100}, {PageNum: 0, PageSize: 0}}, - expected: PaginationOptions{PageNum: 10, PageSize: 100}, + name: "Merge limit/offset #2", + options: []PaginationOptions{{Limit: 10, Offset: 100}, {Limit: 0, Offset: 0}}, + expected: PaginationOptions{Limit: 10, Offset: 100}, }, { - name: "Merge #3", - options: []PaginationOptions{{PageNum: 0, PageSize: 0}, {PageNum: 10, PageSize: 100}, {PageNum: 0, PageSize: 0}}, - expected: PaginationOptions{PageNum: 10, PageSize: 100}, + name: "Merge limit/offset #3", + options: []PaginationOptions{{Limit: 0, Offset: 0}, {Limit: 10, Offset: 100}, {Limit: 0, Offset: 0}}, + expected: PaginationOptions{Limit: 10, Offset: 100}, }, { - name: "Merge #4", - options: []PaginationOptions{{PageNum: 10, PageSize: 100}, {}}, - expected: PaginationOptions{PageNum: 10, PageSize: 100}, + name: "Merge limit/offset #4", + options: []PaginationOptions{{Limit: 10, Offset: 100}, {}}, + expected: PaginationOptions{Limit: 10, Offset: 100}, }, } diff --git a/pkg/organizations/transport/grpc/protobuf_type_converters.microgen.go b/pkg/organizations/transport/grpc/protobuf_type_converters.microgen.go index 2c024a9e6973181ccb5ff683b14be4aaad98792c..9a35f86e871d4e9b7792aa31590fd8f1b1fd0e12 100644 --- a/pkg/organizations/transport/grpc/protobuf_type_converters.microgen.go +++ b/pkg/organizations/transport/grpc/protobuf_type_converters.microgen.go @@ -61,33 +61,11 @@ func ProtoToPtrFilter(protoFilter *pb.Filter) (*organizations.Filter, error) { } func PtrServicesFindOptionsToProto(opts *options.FindOptions) (*common.FindOptions, error) { - if opts == nil { - return nil, nil - } - return &common.FindOptions{ - Sort: opts.Sort, - PageNum: int32(opts.PageNum), - PageSize: int32(opts.PageSize), - Offset: int32(opts.Offset), - Limit: int32(opts.Limit), - }, nil + return options.FindOptionsToPB(opts), nil } func ProtoToPtrServicesFindOptions(protoOpts *common.FindOptions) (*options.FindOptions, error) { - if protoOpts == nil { - return nil, nil - } - return &options.FindOptions{ - SortOptions: options.SortOptions{ - Sort: protoOpts.Sort, - }, - PaginationOptions: options.PaginationOptions{ - PageNum: int(protoOpts.PageNum), - PageSize: int(protoOpts.PageSize), - Offset: int(protoOpts.Offset), - Limit: int(protoOpts.Limit), - }, - }, nil + return options.FindOptionsFromPB(protoOpts), nil } func ListPtrOrganizationToProto(orgs []*organizations.Organization) ([]*pb.Organization, error) { diff --git a/pkg/users/transport/grpc/protobuf_type_converters.microgen.go b/pkg/users/transport/grpc/protobuf_type_converters.microgen.go index 3a73ddd7680439be98f1e8ca6ec0f4dbb70b076a..5f98e2486e50a16049db5ee136cc4d2c943264d7 100644 --- a/pkg/users/transport/grpc/protobuf_type_converters.microgen.go +++ b/pkg/users/transport/grpc/protobuf_type_converters.microgen.go @@ -127,27 +127,9 @@ func ProtoToListPtrUser(protoCreates []*pb.User) ([]*service.User, error) { } func PtrServicesFindOptionsToProto(opts *options.FindOptions) (*common.FindOptions, error) { - if opts == nil { - return nil, nil - } - return &common.FindOptions{ - Sort: opts.Sort, - PageNum: int32(opts.PageNum), - PageSize: int32(opts.PageSize), - }, nil + return options.FindOptionsToPB(opts), nil } func ProtoToPtrServicesFindOptions(protoOpts *common.FindOptions) (*options.FindOptions, error) { - if protoOpts == nil { - return nil, nil - } - return &options.FindOptions{ - SortOptions: options.SortOptions{ - Sort: protoOpts.Sort, - }, - PaginationOptions: options.PaginationOptions{ - PageNum: int(protoOpts.PageNum), - PageSize: int(protoOpts.PageSize), - }, - }, nil + return options.FindOptionsFromPB(protoOpts), nil } diff --git a/zap/channels.go b/zap/channels.go index c67d275541c28739dd45b04d8c643534e39dba16..92b3d823e3aef22c30736942c0aa8931c7e19b31 100644 --- a/zap/channels.go +++ b/zap/channels.go @@ -1,20 +1,24 @@ package zap import ( - "strings" - + "git.perx.ru/perxis/perxis-go/pkg/data" "go.uber.org/zap/zapcore" ) -const channelKey = "channel" +const ( + channelKey = "channel" + + Syslog = "syslog" + Userlog = "userlog" + // ChannelsAll = "*" +) -func HasChannel(channel string) FilterFunc { +func ContainsChannels(channels ...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 { + if f.Key == channelKey && f.Type == zapcore.ArrayMarshalerType { + for _, v := range f.Interface.(stringArray) { + if data.Contains(v, channels) { return true } } @@ -24,20 +28,24 @@ func HasChannel(channel string) FilterFunc { } } -// NewDefaultChannelCore аналогичен NewChannelCore, но также устанавливает переданный канал в качестве канала по умолчанию. -// Это означает, что если поле Channel в записи не указано, запись все равно будет передана в zapcore.Core. -func NewDefaultChannelCore(core zapcore.Core, channel string) zapcore.Core { - return RegisterFilters( - core, - Or( - HasChannel(channel), - Not(ContainsKey(channelKey)), - ), - ) +// WithDefaultChannel аналогичен WithChannel, но также устанавливает переданный канал в качестве канала по умолчанию. +// Это означает, что если поле Channels в записи не указано, запись все равно будет передана в zapcore.Core. +func WithDefaultChannel(core zapcore.Core, channel string) zapcore.Core { + return WithChannel(core, channel, true) +} + +// WithChannel добавляет к переданному Core фильтрацию записей по каналам. +// Это означает, что если запись содержит поле Channels и значение соответствует +// переданному каналу, то запись будет передана в zapcore.Core. +func WithChannel(core zapcore.Core, channel string, isDefault ...bool) zapcore.Core { + filterFn := ContainsChannels(channel) + if len(isDefault) > 0 && isDefault[0] { + filterFn = Or(filterFn, Not(ContainsKey(channelKey))) + } + return WithFilters(core, filterFn) } -// NewChannelCore добавляет к переданному Core фильтрацию записей по каналам. -// Это означает, что если запись содержит поле Channel и значение соответствует переданному каналу, то запись будет передана в zapcore.Core. -func NewChannelCore(core zapcore.Core, channel string) zapcore.Core { - return RegisterFilters(core, HasChannel(channel)) +func WithChannels(core zapcore.Core, channels ...string) zapcore.Core { + filterFn := ContainsChannels(channels...) + return WithFilters(core, filterFn) } diff --git a/zap/channels_test.go b/zap/channels_test.go index 51fa290785a258dcb9c5faa372afa5ec1c228072..ac4c5c9a33797413a7744e439a9d31f38191540e 100644 --- a/zap/channels_test.go +++ b/zap/channels_test.go @@ -8,46 +8,51 @@ import ( "go.uber.org/zap/zaptest/observer" ) -func TestNewChannelCore_WriteSingleChannel(t *testing.T) { +func TestWithChannel_WriteSingleChannel(t *testing.T) { core, logs := observer.New(zapcore.InfoLevel) - core = NewChannelCore(core, "test") + core = WithChannel(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.NoError(t, core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channels("test")})) + require.NoError(t, core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channels("empty")})) // запись не попадет в лог require.Equal(t, 1, logs.Len()) } -func TestNewChannelCore_WriteMultiplyChannels(t *testing.T) { +func TestWithChannel_WriteMultiplyChannels(t *testing.T) { core, logs := observer.New(zapcore.InfoLevel) core = zapcore.NewTee( - NewChannelCore(core, "test1"), - NewChannelCore(core, "test2"), + WithChannel(core, "test1"), + WithChannel(core, "test2"), ) - err := core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channel("test1", "test2")}) // запись попадет сразу в 2 core - require.NoError(t, err) + require.NoError(t, core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channels("test1", "test2")})) // запись попадет сразу в 2 core require.Equal(t, 2, logs.Len()) } -func TestNewDefaultChannelCore(t *testing.T) { +func TestWithDefaultChannels(t *testing.T) { core, logs := observer.New(zapcore.InfoLevel) - core = NewDefaultChannelCore(core, "test1") + core = zapcore.NewTee( + WithChannel(core, "test1", true), + WithChannel(core, "test2"), + ) + + require.NoError(t, core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channels("test1")})) + require.NoError(t, core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channels("test3")})) // эта запись не попадет в лог + require.NoError(t, core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{})) - err := core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channel("test1")}) - require.NoError(t, err) + require.Equal(t, 2, logs.Len()) +} + +func TestWithChannels(t *testing.T) { + core, logs := observer.New(zapcore.InfoLevel) - err = core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channel("test2")}) // эта запись не попадет в лог - require.NoError(t, err) + core = WithChannels(core, "test1", "test2") - err = core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{}) - require.NoError(t, err) + require.NoError(t, core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channels("test1")})) + require.NoError(t, core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{Channels("test2")})) require.Equal(t, 2, logs.Len()) } diff --git a/zap/field.go b/zap/field.go index b439f51b05736b77ff0a991e9b828a2116cfa0e3..60a56235144b064b881d0705bdfe90b8c539719b 100644 --- a/zap/field.go +++ b/zap/field.go @@ -2,80 +2,62 @@ package zap import ( "context" - "strings" "git.perx.ru/perxis/perxis-go/id" _ "git.perx.ru/perxis/perxis-go/id/system" // регистрируем обработчики для системных объектов "git.perx.ru/perxis/perxis-go/pkg/auth" "go.uber.org/zap" + "go.uber.org/zap/zapcore" ) -func Channel(channels ...string) zap.Field { - if len(channels) == 0 { - return zap.Skip() +type stringArray []string + +func (ss stringArray) MarshalLogArray(arr zapcore.ArrayEncoder) error { + for i := range ss { + arr.AppendString(ss[i]) } - return zap.String(channelKey, strings.Join(channels, ",")) + return nil +} + +func Channels(channels ...string) zap.Field { + return zap.Array(channelKey, stringArray(channels)) } func Category(category string) zap.Field { - if category == "" { - return zap.Skip() - } return zap.String("category", category) } func Component(component string) zap.Field { - if component == "" { - return zap.Skip() - } return zap.String("component", component) } func Event(event string) zap.Field { - if event == "" { - return zap.Skip() - } return zap.String("event", event) } // Object возвращает поле и устанавливает передаваемый аргумент в качестве идентификатора объекта в формате ObjectId. // Поддерживает типы в формате ObjectId: id.Descriptor, string, map[string]any, системные объекты. func Object(v any) zap.Field { - oid, err := id.NewObjectId(v) - if err != nil { - return zap.Skip() - } + oid, _ := id.NewObjectId(v) return zap.Reflect("object", oid) } // Caller возвращает поле и устанавливает передаваемый аргумент в качестве "вызывающего" в формате ObjectId. // Поддерживает типы в формате ObjectId: id.Descriptor, string, map[string]any, системные объекты. func Caller(v any) zap.Field { - oid, err := id.NewObjectId(v) - if err != nil { - return zap.Skip() - } + oid, _ := id.NewObjectId(v) return zap.Reflect("caller", oid) } // CallerFromContext извлекает auth.Principal из контекста и устанавливает его в качестве "вызывающего" в формате Object. func CallerFromContext(ctx context.Context) zap.Field { - if ctx == nil { - return zap.Skip() - } return Caller(auth.GetPrincipal(ctx)) } func Attr(attr any) zap.Field { - if attr == nil { - return zap.Skip() - } return zap.Any("attr", attr) } func Tags(tags ...string) zap.Field { - if len(tags) == 0 { - return zap.Skip() - } return zap.Strings("tags", tags) } diff --git a/zap/field_test.go b/zap/field_test.go index ead5af2386b5606a3861dc563ba6e49a6ed43f7b..5c107d7bc769c04a066b636e0f7a79ca892420f8 100644 --- a/zap/field_test.go +++ b/zap/field_test.go @@ -19,7 +19,7 @@ func TestCategory(t *testing.T) { want zap.Field }{ {name: "ok", field: Category("update"), want: zap.String("category", "update")}, - {name: "invalid", field: Category(""), want: zap.Skip()}, + {name: "invalid", field: Category(""), want: zap.String("category", "")}, } for _, tc := range tests { @@ -36,7 +36,7 @@ func TestComponent(t *testing.T) { want zap.Field }{ {name: "ok", field: Component("Items"), want: zap.String("component", "Items")}, - {name: "invalid", field: Component(""), want: zap.Skip()}, + {name: "invalid", field: Component(""), want: zap.String("component", "")}, } for _, tc := range tests { @@ -53,7 +53,7 @@ func TestEvent(t *testing.T) { want zap.Field }{ {name: "ok", field: Event("items.create"), want: zap.String("event", "items.create")}, - {name: "invalid", field: Event(""), want: zap.Skip()}, + {name: "invalid", field: Event(""), want: zap.String("event", "")}, } for _, tc := range tests { @@ -63,7 +63,7 @@ func TestEvent(t *testing.T) { } } -func TestObjectID(t *testing.T) { +func TestObject(t *testing.T) { item := &items.Item{ ID: "c4ca4238a0b923820dcc509a6f75849b", SpaceID: "c81e728d9d4c2f636f067f89cc14862c", @@ -82,21 +82,24 @@ func TestObjectID(t *testing.T) { {name: "system object", field: Object(item), want: zap.Reflect("object", oid)}, {name: "object id", field: Object(itemId), want: zap.Reflect("object", oid)}, {name: "string", field: Object(oid.String()), want: zap.Reflect("object", oid)}, - {name: "invalid", field: Object(nil), want: zap.Skip()}, + {name: "invalid", field: Object(nil), want: zap.Reflect("object", (*id.ObjectId)(nil))}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - if tc.want.Equals(zap.Skip()) { - assert.True(t, tc.want.Equals(tc.field)) - return + wantObjectId, ok1 := tc.want.Interface.(*id.ObjectId) + fieldObjectId, ok2 := tc.field.Interface.(*id.ObjectId) + + if ok1 && ok2 && wantObjectId != nil && fieldObjectId != nil { + assert.Equal(t, wantObjectId.String(), fieldObjectId.String()) + } else { + assert.Equal(t, tc.want.Interface, tc.field.Interface) } - assert.Equal(t, tc.want.Interface.(id.Descriptor).String(), tc.field.Interface.(id.Descriptor).String()) }) } } -func TestCallerID(t *testing.T) { +func TestCaller(t *testing.T) { user := &users.User{ ID: "c4ca4238a0b923820dcc509a6f75849b", } @@ -112,21 +115,24 @@ func TestCallerID(t *testing.T) { {name: "system object", field: Caller(user), want: zap.Reflect("caller", oid)}, {name: "object id", field: Caller(userId), want: zap.Reflect("caller", oid)}, {name: "string", field: Caller(oid.String()), want: zap.Reflect("caller", oid)}, - {name: "invalid", field: Caller(nil), want: zap.Skip()}, + {name: "invalid", field: Caller(nil), want: zap.Reflect("caller", (*id.ObjectId)(nil))}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - if tc.want.Equals(zap.Skip()) { - assert.True(t, tc.want.Equals(tc.field)) - return + wantObjectId, ok1 := tc.want.Interface.(*id.ObjectId) + fieldObjectId, ok2 := tc.field.Interface.(*id.ObjectId) + + if ok1 && ok2 && wantObjectId != nil && fieldObjectId != nil { + assert.Equal(t, wantObjectId.String(), fieldObjectId.String()) + } else { + assert.Equal(t, tc.want.Interface, tc.field.Interface) } - assert.Equal(t, tc.want.Interface.(id.Descriptor).String(), tc.field.Interface.(id.Descriptor).String()) }) } } -func TestCallerIDFromContext(t *testing.T) { +func TestCallerFromContext(t *testing.T) { ctx := auth.WithSystem(context.Background()) oid := id.MustObjectId(auth.GetPrincipal(ctx)) @@ -136,16 +142,19 @@ func TestCallerIDFromContext(t *testing.T) { want zap.Field }{ {name: "ok", field: CallerFromContext(ctx), want: zap.Reflect("caller", oid)}, - {name: "invalid", field: CallerFromContext(context.TODO()), want: zap.Skip()}, + {name: "invalid", field: CallerFromContext(context.TODO()), want: zap.Reflect("caller", (*id.ObjectId)(nil))}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - if tc.want.Equals(zap.Skip()) { - assert.True(t, tc.want.Equals(tc.field)) - return + wantObjectId, ok1 := tc.want.Interface.(*id.ObjectId) + fieldObjectId, ok2 := tc.field.Interface.(*id.ObjectId) + + if ok1 && ok2 && wantObjectId != nil && fieldObjectId != nil { + assert.Equal(t, wantObjectId.String(), fieldObjectId.String()) + } else { + assert.Equal(t, tc.want.Interface, tc.field.Interface) } - assert.Equal(t, tc.want.Interface.(id.Descriptor).String(), tc.field.Interface.(id.Descriptor).String()) }) } } @@ -157,7 +166,7 @@ func TestAttr(t *testing.T) { want zap.Field }{ {name: "ok", field: Attr(map[string]string{"a": "b"}), want: zap.Reflect("attr", map[string]string{"a": "b"})}, - {name: "invalid", field: Attr(nil), want: zap.Skip()}, + {name: "invalid", field: Attr(nil), want: zap.Reflect("attr", nil)}, } for _, tc := range tests { @@ -174,7 +183,7 @@ func TestTags(t *testing.T) { want zap.Field }{ {name: "ok", field: Tags("a", "b", "c"), want: zap.Strings("tags", []string{"a", "b", "c"})}, - {name: "invalid", field: Tags(nil...), want: zap.Skip()}, + {name: "invalid", field: Tags(nil...), want: zap.Strings("tags", nil)}, } for _, tc := range tests { diff --git a/zap/filter_core.go b/zap/filter_core.go index 16888f583892b05bd379d5868ea5f58c6dbf4628..7e99d942e439afc8a05faaf55be29b8cb604b7fc 100644 --- a/zap/filter_core.go +++ b/zap/filter_core.go @@ -56,20 +56,20 @@ type filterCore struct { fields []zap.Field } -// RegisterFilters - добавить фильтры, которые будут применяться при записи лога (вызове `core.Write`) +// WithFilters - добавить фильтры, которые будут применяться при записи лога (вызове `core.Write`) // Метод `core.Write` будет вызван только в случае, когда результат всех фильтров `true` // // Обратить внимание, фильтр не применяется к полям, которые были добавлены в `core` через вызов `core.With` -// до вызова RegisterFilters. Пример: +// до вызова WithFilters. Пример: // // l, _ := zap.NewDevelopment() // core := l.Core().With([]zapcore.Field{zap.Int("a", 5)}) -// core = RegisterFilters(core, ContainsField(zap.Int("a", 5))) +// core = WithFilters(core, ContainsField(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 { +func WithFilters(core zapcore.Core, filters ...FilterFunc) zapcore.Core { return &filterCore{ Core: core, filters: filters, diff --git a/zap/filter_core_test.go b/zap/filter_core_test.go index cb38f41cd2f0c5bab0aabea75112d9f1a57fd109..21c906f24f5b7458c7628985871f1480564a3164 100644 --- a/zap/filter_core_test.go +++ b/zap/filter_core_test.go @@ -11,7 +11,7 @@ import ( func TestFilterCore_Write(t *testing.T) { core, logs := observer.New(zapcore.InfoLevel) - core = RegisterFilters(core, ContainsField(zap.Bool("check", true))) + core = WithFilters(core, ContainsField(zap.Bool("check", true))) err := core.With([]zapcore.Field{zap.Bool("check", true)}).Write(zapcore.Entry{Message: "msg"}, nil) require.NoError(t, err) @@ -25,9 +25,9 @@ func TestFilterCore_Write(t *testing.T) { require.Equal(t, 2, logs.Len()) } -func TestNotHasField(t *testing.T) { +func TestNotContainsField(t *testing.T) { core, logs := observer.New(zapcore.InfoLevel) - core = RegisterFilters(core, NotHasField(zap.Int("b", 2))) + core = WithFilters(core, Not(ContainsField(zap.Int("b", 2)))) err := core.Write(zapcore.Entry{Message: "msg"}, []zapcore.Field{ zap.Int("a", 1),