From 707c4f4d79e0d1a024896f12668e98f5240825cd Mon Sep 17 00:00:00 2001
From: Semyon Krestyaninov <ensiouel@gmail.com>
Date: Tue, 20 Feb 2024 15:51:40 +0300
Subject: [PATCH] Revert "Merge branch
 'feature/PRXS-951-1891-LogServiceMiddlewares' into 'feature/PRXS-951-Log'"

This reverts commit 5aa0842bb66ed0a3656e27451644bd01a2d55b4f, reversing
changes made to 10b458ed4865487667b57c47ae7954e63936baee.
---
 assets/templates/middleware/access_log        |  65 ++
 assets/templates/middleware/access_log.tmpl   |  58 --
 assets/templates/middleware/log.tmpl          |  73 --
 .../{middleware.tmpl => middleware}           |  14 +-
 log/service.go                                |   2 -
 log/zap/core.go                               |   6 -
 pkg/collections/events.go                     |   8 -
 .../middleware/access_logging_middleware.go   | 175 -----
 .../middleware/error_logging_middleware.go    | 101 +++
 .../middleware/logging_middleware.go          | 283 +++++--
 pkg/collections/middleware/middleware.go      |   9 +-
 pkg/items/events.go                           |  13 +-
 .../middleware/access_logging_middleware.go   | 418 ----------
 .../middleware/error_logging_middleware.go    | 211 ++++++
 pkg/items/middleware/logging_middleware.go    | 716 ++++++++++++++----
 pkg/items/middleware/middleware.go            |   9 +-
 zap/channels.go                               |   4 -
 17 files changed, 1196 insertions(+), 969 deletions(-)
 create mode 100755 assets/templates/middleware/access_log
 delete mode 100755 assets/templates/middleware/access_log.tmpl
 delete mode 100644 assets/templates/middleware/log.tmpl
 rename assets/templates/middleware/{middleware.tmpl => middleware} (57%)
 delete mode 100644 pkg/collections/events.go
 delete mode 100644 pkg/collections/middleware/access_logging_middleware.go
 create mode 100644 pkg/collections/middleware/error_logging_middleware.go
 delete mode 100644 pkg/items/middleware/access_logging_middleware.go
 create mode 100644 pkg/items/middleware/error_logging_middleware.go

diff --git a/assets/templates/middleware/access_log b/assets/templates/middleware/access_log
new file mode 100755
index 00000000..86b4fe25
--- /dev/null
+++ b/assets/templates/middleware/access_log
@@ -0,0 +1,65 @@
+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
deleted file mode 100755
index 9f9899b8..00000000
--- a/assets/templates/middleware/access_log.tmpl
+++ /dev/null
@@ -1,58 +0,0 @@
-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
deleted file mode 100644
index ab91909f..00000000
--- a/assets/templates/middleware/log.tmpl
+++ /dev/null
@@ -1,73 +0,0 @@
-{{/*
-Этот шаблон предназначен только для первичной генерации 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.tmpl b/assets/templates/middleware/middleware
similarity index 57%
rename from assets/templates/middleware/middleware.tmpl
rename to assets/templates/middleware/middleware
index c717d577..89877774 100755
--- a/assets/templates/middleware/middleware.tmpl
+++ b/assets/templates/middleware/middleware
@@ -2,26 +2,20 @@ import (
 	"go.uber.org/zap"
 )
 
-{{ $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 }}")
-    {{- if (has $serviceName (list "Items" "Collections") ) }}
-	if log_access {
-		s = AccessLoggingMiddleware(logger)(s)
-	}
-	s = LoggingMiddleware(logger)(s)
-	{{ else }}
+
+	logger = logger.Named("{{ .Interface.Name }}")
 	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 46e30607..8a39ca53 100644
--- a/log/service.go
+++ b/log/service.go
@@ -8,8 +8,6 @@ import (
 	pb "git.perx.ru/perxis/perxis-go/proto/log"
 )
 
-const ServiceName = "logs"
-
 type Service interface {
 
 	// Log метод записи логов
diff --git a/log/zap/core.go b/log/zap/core.go
index 070e6fb8..f2b220ea 100644
--- a/log/zap/core.go
+++ b/log/zap/core.go
@@ -1,8 +1,6 @@
 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"
@@ -78,10 +76,6 @@ 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/pkg/collections/events.go b/pkg/collections/events.go
deleted file mode 100644
index bdc92e77..00000000
--- a/pkg/collections/events.go
+++ /dev/null
@@ -1,8 +0,0 @@
-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
deleted file mode 100644
index 3624955b..00000000
--- a/pkg/collections/middleware/access_logging_middleware.go
+++ /dev/null
@@ -1,175 +0,0 @@
-// 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
new file mode 100644
index 00000000..04912506
--- /dev/null
+++ b/pkg/collections/middleware/error_logging_middleware.go
@@ -0,0 +1,101 @@
+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 c5e2e2fb..bc3e4107 100644
--- a/pkg/collections/middleware/logging_middleware.go
+++ b/pkg/collections/middleware/logging_middleware.go
@@ -1,140 +1,303 @@
+package middleware
+
 // Code generated by gowrap. DO NOT EDIT.
-// template: ../../../assets/templates/middleware/log.tmpl
+// 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/collections -i Collections -t ../../../assets/templates/middleware/log.tmpl -o logging_middleware.go -l ""
+//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 ""
 
 import (
 	"context"
+	"fmt"
+	"time"
 
-	"git.perx.ru/perxis/perxis-go/id"
+	"git.perx.ru/perxis/perxis-go/pkg/auth"
 	"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.With(logzap.Component("collections")),
+			logger: logger,
 		}
 	}
 }
 
 func (m *loggingMiddleware) Create(ctx context.Context, collection *collections.Collection) (created *collections.Collection, err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(collections.EventCollectionCreate),
-	)
+	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...)
 
 	created, err = m.next.Create(ctx, collection)
-	if err != nil {
-		logger.Error("Failed to create", zap.Error(err), logzap.Object(collection), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
-	logger.Info("Successfully created", logzap.Object(created), logzap.Channels(logzap.Userlog))
+	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...)
+
 	return created, err
 }
 
 func (m *loggingMiddleware) Delete(ctx context.Context, spaceId string, envId string, collectionId string) (err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(collections.EventCollectionDelete),
-		logzap.Object(id.NewCollectionId(spaceId, envId, collectionId)),
-	)
+	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...)
 
 	err = m.next.Delete(ctx, spaceId, envId, collectionId)
-	if err != nil {
-		logger.Error("Failed to delete", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	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))
 	}
 
-	logger.Info("Successfully deleted", logzap.Channels(logzap.Userlog))
+	m.logger.Debug("Delete.Response", fields...)
+
 	return err
 }
 
 func (m *loggingMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, options ...*collections.GetOptions) (collection *collections.Collection, err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-	)
+	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...)
 
 	collection, err = m.next.Get(ctx, spaceId, envId, collectionId, options...)
-	if err != nil {
-		logger.Error("Failed to get", zap.Error(err))
-		return
+
+	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))
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-	)
+	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...)
 
 	collections, err = m.next.List(ctx, spaceId, envId, filter)
-	if err != nil {
-		logger.Error("Failed to list", zap.Error(err))
-		return
+
+	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))
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(collections.EventCollectionSetSchema),
-		logzap.Object(id.NewCollectionId(spaceId, envId, collectionId)),
-	)
+	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...)
 
 	err = m.next.SetSchema(ctx, spaceId, envId, collectionId, schema)
-	if err != nil {
-		logger.Error("Failed to setschema", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
-	logger.Info("Successfully setschemaed", logzap.Channels(logzap.Userlog))
+	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...)
+
 	return err
 }
 
 func (m *loggingMiddleware) SetState(ctx context.Context, spaceId string, envId string, collectionId string, state *collections.StateInfo) (err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-	)
+	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...)
 
 	err = m.next.SetState(ctx, spaceId, envId, collectionId, state)
-	if err != nil {
-		logger.Error("Failed to setstate", zap.Error(err))
-		return
+
+	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))
 	}
 
+	m.logger.Debug("SetState.Response", fields...)
+
 	return err
 }
 
 func (m *loggingMiddleware) Update(ctx context.Context, coll *collections.Collection) (err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(collections.EventCollectionUpdate),
-		logzap.Object(coll),
-	)
+	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...)
 
 	err = m.next.Update(ctx, coll)
-	if err != nil {
-		logger.Error("Failed to update", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
-	logger.Info("Successfully updated", logzap.Channels(logzap.Userlog))
+	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...)
+
 	return err
 }
diff --git a/pkg/collections/middleware/middleware.go b/pkg/collections/middleware/middleware.go
index 22514e7c..b581ce74 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.tmpl
+// template: ../../../assets/templates/middleware/middleware
 // 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.tmpl -o middleware.go -l ""
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/collections -i Collections -t ../../../assets/templates/middleware/middleware -o middleware.go -l ""
 
 import (
 	"git.perx.ru/perxis/perxis-go/pkg/collections"
@@ -17,11 +17,12 @@ 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 = AccessLoggingMiddleware(logger)(s)
+		s = LoggingMiddleware(logger)(s)
 	}
-	s = LoggingMiddleware(logger)(s)
 	s = RecoveringMiddleware(logger)(s)
 	return s
 }
diff --git a/pkg/items/events.go b/pkg/items/events.go
index 9a1eb924..b697d607 100644
--- a/pkg/items/events.go
+++ b/pkg/items/events.go
@@ -7,14 +7,11 @@ import (
 )
 
 const (
-	EventItemCreate    = "create_item"
-	EventItemUpdate    = "update_item"
-	EventItemPublish   = "publish_item"
-	EventItemUnpublish = "unpublish_item"
-	EventItemDelete    = "delete_item"
-	EventItemUndelete  = "item_undelete"
-	EventItemArchive   = "item_archive"
-	EventItemUnarchive = "item_unarchive"
+	EventCreateItem    = "create_item"
+	EventUpdateItem    = "update_item"
+	EventPublishItem   = "publish_item"
+	EventUnpublishItem = "unpublish_item"
+	EventDeleteItem    = "delete_item"
 
 	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
deleted file mode 100644
index 2342a6d9..00000000
--- a/pkg/items/middleware/access_logging_middleware.go
+++ /dev/null
@@ -1,418 +0,0 @@
-// 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
new file mode 100644
index 00000000..345d22ca
--- /dev/null
+++ b/pkg/items/middleware/error_logging_middleware.go
@@ -0,0 +1,211 @@
+// 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 8870912f..6ed28f90 100644
--- a/pkg/items/middleware/logging_middleware.go
+++ b/pkg/items/middleware/logging_middleware.go
@@ -1,306 +1,744 @@
+// 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/id"
+	"git.perx.ru/perxis/perxis-go/pkg/auth"
 	"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.With(logzap.Component("items")),
+			logger: logger,
 		}
 	}
 }
 
 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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-	)
+	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...)
 
 	result, err = m.next.Aggregate(ctx, spaceId, envId, collectionId, filter, options...)
-	if err != nil {
-		logger.Error("Failed to aggregate", zap.Error(err))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-	)
+	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...)
 
 	result, err = m.next.AggregatePublished(ctx, spaceId, envId, collectionId, filter, options...)
-	if err != nil {
-		logger.Error("Failed to aggregate_published", zap.Error(err))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(items.EventItemArchive),
-		logzap.Object(item),
-	)
+	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...)
 
 	err = m.next.Archive(ctx, item, options...)
-	if err != nil {
-		logger.Error("Failed to archive", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
-	logger.Info("Successfully archived", logzap.Channels(logzap.Userlog))
+	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...)
+
 	return err
 }
 
 func (m *loggingMiddleware) Create(ctx context.Context, item *items.Item, opts ...*items.CreateOptions) (created *items.Item, err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(items.EventItemCreate),
-	)
+	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...)
 
 	created, err = m.next.Create(ctx, item, opts...)
-	if err != nil {
-		logger.Error("Failed to create", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog), logzap.Object(item))
-		return
+
+	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))
 	}
 
-	logger.Info("Successfully created", logzap.Channels(logzap.Userlog), logzap.Object(created))
+	m.logger.Debug("Create.Response", fields...)
+
 	return created, err
 }
 
 func (m *loggingMiddleware) Delete(ctx context.Context, item *items.Item, options ...*items.DeleteOptions) (err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(items.EventItemDelete),
-		logzap.Object(item),
-	)
+	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...)
 
 	err = m.next.Delete(ctx, item, options...)
-	if err != nil {
-		logger.Error("Failed to delete", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
-	logger.Info("Successfully deleted", logzap.Channels(logzap.Userlog))
+	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...)
+
 	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-	)
+	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...)
 
 	items, total, err = m.next.Find(ctx, spaceId, envId, collectionId, filter, options...)
 
-	if err != nil {
-		logger.Error("Failed to find", zap.Error(err))
-		return
+	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))
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-	)
+	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...)
 
 	items, total, err = m.next.FindArchived(ctx, spaceId, envId, collectionId, filter, options...)
-	if err != nil {
-		logger.Error("Failed to find_archived", zap.Error(err))
-		return
+
+	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))
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-	)
+	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...)
 
 	items, total, err = m.next.FindPublished(ctx, spaceId, envId, collectionId, filter, options...)
-	if err != nil {
-		logger.Error("Failed to findpublished", zap.Error(err))
-		return
+
+	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))
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)),
-	)
+	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...)
 
 	item, err = m.next.Get(ctx, spaceId, envId, collectionId, itemId, options...)
-	if err != nil {
-		logger.Error("Failed to get", zap.Error(err))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)),
-	)
+	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...)
 
 	item, err = m.next.GetPublished(ctx, spaceId, envId, collectionId, itemId, options...)
-	if err != nil {
-		logger.Error("Failed to get published", zap.Error(err))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)),
-	)
+	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...)
 
 	item, err = m.next.GetRevision(ctx, spaceId, envId, collectionId, itemId, revisionId, options...)
-	if err != nil {
-		logger.Error("Failed to get revision", zap.Error(err))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Object(item),
-	)
+	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...)
 
 	itm, sch, err = m.next.Introspect(ctx, item, opts...)
-	if err != nil {
-		logger.Error("Failed to introspect", zap.Error(err))
-		return
+
+	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))
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Object(id.NewItemId(spaceId, envId, collectionId, itemId)),
-	)
+	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...)
 
 	items, err = m.next.ListRevisions(ctx, spaceId, envId, collectionId, itemId, options...)
-	if err != nil {
-		logger.Error("Failed to list revisions", zap.Error(err))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
+	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) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(items.EventItemPublish),
-		logzap.Object(item),
-	)
+	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...)
 
 	err = m.next.Publish(ctx, item, options...)
-	if err != nil {
-		logger.Error("Failed to publish", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
-	logger.Info("Successfully published", logzap.Channels(logzap.Userlog))
+	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...)
+
 	return err
 }
 
 func (m *loggingMiddleware) Unarchive(ctx context.Context, item *items.Item, options ...*items.UnarchiveOptions) (err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(items.EventItemUnarchive),
-		logzap.Object(item),
-	)
+	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...)
 
 	err = m.next.Unarchive(ctx, item, options...)
-	if err != nil {
-		logger.Error("Failed to unarchive", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	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))
 	}
 
-	logger.Info("Successfully unarchived", logzap.Channels(logzap.Userlog))
+	m.logger.Debug("Unarchive.Response", fields...)
+
 	return err
 }
 
 func (m *loggingMiddleware) Undelete(ctx context.Context, item *items.Item, options ...*items.UndeleteOptions) (err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(items.EventItemUndelete),
-		logzap.Object(item),
-	)
+	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...)
 
 	err = m.next.Undelete(ctx, item, options...)
-	if err != nil {
-		logger.Error("Failed to undelete", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	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))
 	}
 
-	logger.Info("Successfully undeleted", logzap.Channels(logzap.Userlog))
+	m.logger.Debug("Undelete.Response", fields...)
+
 	return err
 }
 
 func (m *loggingMiddleware) Unpublish(ctx context.Context, item *items.Item, options ...*items.UnpublishOptions) (err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(items.EventItemUnpublish),
-		logzap.Object(item),
-	)
+	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...)
 
 	err = m.next.Unpublish(ctx, item, options...)
-	if err != nil {
-		logger.Error("Failed to unpublish", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	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))
 	}
 
-	logger.Info("Successfully unpublished", logzap.Channels(logzap.Userlog))
+	m.logger.Debug("Unpublish.Response", fields...)
+
 	return err
 }
 
 func (m *loggingMiddleware) Update(ctx context.Context, item *items.Item, options ...*items.UpdateOptions) (err error) {
-	logger := m.logger.With(
-		logzap.CallerFromContext(ctx),
-		logzap.Event(items.EventItemUpdate),
-		logzap.Object(item),
-	)
+	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...)
 
 	err = m.next.Update(ctx, item, options...)
-	if err != nil {
-		logger.Error("Failed to update", zap.Error(err), logzap.Channels(logzap.Userlog, logzap.Syslog))
-		return
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
 	}
 
-	logger.Info("Successfully updated", logzap.Channels(logzap.Userlog))
+	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...)
+
 	return err
 }
diff --git a/pkg/items/middleware/middleware.go b/pkg/items/middleware/middleware.go
index 2ce07ef9..52a1c121 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.tmpl
+// template: ../../../assets/templates/middleware/middleware
 // 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.tmpl -o middleware.go -l ""
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/items -i Items -t ../../../assets/templates/middleware/middleware -o middleware.go -l ""
 
 import (
 	"git.perx.ru/perxis/perxis-go/pkg/items"
@@ -17,11 +17,12 @@ 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 = AccessLoggingMiddleware(logger)(s)
+		s = LoggingMiddleware(logger)(s)
 	}
-	s = LoggingMiddleware(logger)(s)
 	s = RecoveringMiddleware(logger)(s)
 	return s
 }
diff --git a/zap/channels.go b/zap/channels.go
index 92b3d823..6d323aa8 100644
--- a/zap/channels.go
+++ b/zap/channels.go
@@ -7,10 +7,6 @@ import (
 
 const (
 	channelKey = "channel"
-
-	Syslog  = "syslog"
-	Userlog = "userlog"
-	// ChannelsAll   = "*"
 )
 
 func ContainsChannels(channels ...string) FilterFunc {
-- 
GitLab