From 7f2714823f8b6caac9a19229a77ca59ddda19350 Mon Sep 17 00:00:00 2001
From: Valera Shaitorov <shaitorov@perx.ru>
Date: Mon, 17 Apr 2023 19:01:09 +0700
Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?=
 =?UTF-8?q?=D0=BD=D1=8B=20References=20middlewares?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../middleware/client_encode_middleware.go    | 42 +++++++++++
 .../middleware/error_logging_middleware.go    | 41 ++++++++++
 .../middleware/logging_middleware.go          | 74 +++++++++++++++++++
 pkg/references/middleware/middleware.go       | 28 +++++++
 .../middleware/recovering_middleware.go       | 44 +++++++++++
 5 files changed, 229 insertions(+)
 create mode 100644 pkg/references/middleware/client_encode_middleware.go
 create mode 100644 pkg/references/middleware/error_logging_middleware.go
 create mode 100644 pkg/references/middleware/logging_middleware.go
 create mode 100644 pkg/references/middleware/middleware.go
 create mode 100644 pkg/references/middleware/recovering_middleware.go

diff --git a/pkg/references/middleware/client_encode_middleware.go b/pkg/references/middleware/client_encode_middleware.go
new file mode 100644
index 00000000..1cd9cb2f
--- /dev/null
+++ b/pkg/references/middleware/client_encode_middleware.go
@@ -0,0 +1,42 @@
+package service
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/collections"
+	"git.perx.ru/perxis/perxis-go/pkg/items"
+	"git.perx.ru/perxis/perxis-go/pkg/references"
+)
+
+// ClientEncodeMiddleware выполняет операции encode/decode для передаваемых данных
+func ClientEncodeMiddleware(colls collections.Collections) Middleware {
+	return func(refs references.References) references.References {
+		return &encodeDecodeMiddleware{
+			next:  refs,
+			colls: colls,
+		}
+	}
+}
+
+type encodeDecodeMiddleware struct {
+	next  references.References
+	colls collections.Collections
+}
+
+func (m *encodeDecodeMiddleware) Get(ctx context.Context, spaceId, envId string, refs []*references.Reference) (items []*items.Item, notfound []*references.Reference, err error) {
+	items, notfound, err = m.next.Get(ctx, spaceId, envId, refs)
+	if err == nil && len(items) > 0 {
+		for i, item := range items {
+			col, err := m.colls.Get(ctx, item.SpaceID, item.EnvID, item.CollectionID)
+			if err != nil {
+				return nil, nil, err
+			}
+
+			if item, err = item.Decode(ctx, col.Schema); err != nil {
+				return nil, nil, err
+			}
+			items[i] = item
+		}
+	}
+	return
+}
diff --git a/pkg/references/middleware/error_logging_middleware.go b/pkg/references/middleware/error_logging_middleware.go
new file mode 100644
index 00000000..e68bade9
--- /dev/null
+++ b/pkg/references/middleware/error_logging_middleware.go
@@ -0,0 +1,41 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/error_log
+// gowrap: http://github.com/hexdigest/gowrap
+
+package service
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/references -i References -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/references"
+	"go.uber.org/zap"
+)
+
+// errorLoggingMiddleware implements references.References that is instrumented with logging
+type errorLoggingMiddleware struct {
+	logger *zap.Logger
+	next   references.References
+}
+
+// ErrorLoggingMiddleware instruments an implementation of the references.References with simple logging
+func ErrorLoggingMiddleware(logger *zap.Logger) Middleware {
+	return func(next references.References) references.References {
+		return &errorLoggingMiddleware{
+			next:   next,
+			logger: logger,
+		}
+	}
+}
+
+func (m *errorLoggingMiddleware) Get(ctx context.Context, spaceId string, envId string, references []*references.Reference) (items []*items.Item, notfound []*references.Reference, err error) {
+	logger := m.logger
+	defer func() {
+		if err != nil {
+			logger.Warn("response error", zap.Error(err))
+		}
+	}()
+	return m.next.Get(ctx, spaceId, envId, references)
+}
diff --git a/pkg/references/middleware/logging_middleware.go b/pkg/references/middleware/logging_middleware.go
new file mode 100644
index 00000000..692e298d
--- /dev/null
+++ b/pkg/references/middleware/logging_middleware.go
@@ -0,0 +1,74 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/access_log
+// gowrap: http://github.com/hexdigest/gowrap
+
+package service
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/references -i References -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/pkg/items"
+	"git.perx.ru/perxis/perxis-go/pkg/references"
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+)
+
+// loggingMiddleware implements references.References that is instrumented with logging
+type loggingMiddleware struct {
+	logger *zap.Logger
+	next   references.References
+}
+
+// LoggingMiddleware instruments an implementation of the references.References with simple logging
+func LoggingMiddleware(logger *zap.Logger) Middleware {
+	return func(next references.References) references.References {
+		return &loggingMiddleware{
+			next:   next,
+			logger: logger,
+		}
+	}
+}
+
+func (m *loggingMiddleware) Get(ctx context.Context, spaceId string, envId string, references []*references.Reference) (items []*items.Item, notfound []*references.Reference, err error) {
+	begin := time.Now()
+	var fields []zapcore.Field
+	for k, v := range map[string]interface{}{
+		"ctx":        ctx,
+		"spaceId":    spaceId,
+		"envId":      envId,
+		"references": references} {
+		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...)
+
+	items, notfound, err = m.next.Get(ctx, spaceId, envId, references)
+
+	fields = []zapcore.Field{
+		zap.Duration("time", time.Since(begin)),
+		zap.Error(err),
+	}
+
+	for k, v := range map[string]interface{}{
+		"items":    items,
+		"notfound": notfound,
+		"err":      err} {
+		if k == "err" {
+			continue
+		}
+		fields = append(fields, zap.Reflect(k, v))
+	}
+
+	m.logger.Debug("Get.Response", fields...)
+
+	return items, notfound, err
+}
diff --git a/pkg/references/middleware/middleware.go b/pkg/references/middleware/middleware.go
new file mode 100644
index 00000000..dfed8dc0
--- /dev/null
+++ b/pkg/references/middleware/middleware.go
@@ -0,0 +1,28 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/middleware
+// gowrap: http://github.com/hexdigest/gowrap
+
+package service
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/references -i References -t ../../../assets/templates/middleware/middleware -o middleware.go -l ""
+
+import (
+	"git.perx.ru/perxis/perxis-go/pkg/references"
+	"go.uber.org/zap"
+)
+
+type Middleware func(references.References) references.References
+
+func WithLog(s references.References, logger *zap.Logger, log_access bool) references.References {
+	if logger == nil {
+		logger = zap.NewNop()
+	}
+
+	logger = logger.Named("References")
+	s = ErrorLoggingMiddleware(logger)(s)
+	if log_access {
+		s = LoggingMiddleware(logger)(s)
+	}
+	s = RecoveringMiddleware(logger)(s)
+	return s
+}
diff --git a/pkg/references/middleware/recovering_middleware.go b/pkg/references/middleware/recovering_middleware.go
new file mode 100644
index 00000000..b1a4eb6b
--- /dev/null
+++ b/pkg/references/middleware/recovering_middleware.go
@@ -0,0 +1,44 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/recovery
+// gowrap: http://github.com/hexdigest/gowrap
+
+package service
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/references -i References -t ../../../assets/templates/middleware/recovery -o recovering_middleware.go -l ""
+
+import (
+	"context"
+	"fmt"
+
+	"git.perx.ru/perxis/perxis-go/pkg/items"
+	"git.perx.ru/perxis/perxis-go/pkg/references"
+	"go.uber.org/zap"
+)
+
+// recoveringMiddleware implements references.References that is instrumented with logging
+type recoveringMiddleware struct {
+	logger *zap.Logger
+	next   references.References
+}
+
+// RecoveringMiddleware instruments an implementation of the references.References with simple logging
+func RecoveringMiddleware(logger *zap.Logger) Middleware {
+	return func(next references.References) references.References {
+		return &recoveringMiddleware{
+			next:   next,
+			logger: logger,
+		}
+	}
+}
+
+func (m *recoveringMiddleware) Get(ctx context.Context, spaceId string, envId string, references []*references.Reference) (items []*items.Item, notfound []*references.Reference, err error) {
+	logger := m.logger
+	defer func() {
+		if r := recover(); r != nil {
+			logger.Error("panic", zap.Error(fmt.Errorf("%v", r)))
+			err = fmt.Errorf("%v", r)
+		}
+	}()
+
+	return m.next.Get(ctx, spaceId, envId, references)
+}
-- 
GitLab