From 8808371cc465b0c16e6c41bd1ab5bf89a466a0ef Mon Sep 17 00:00:00 2001
From: ensiouel <ensiouel@gmail.com>
Date: Tue, 19 Dec 2023 19:27:55 +0300
Subject: [PATCH] =?UTF-8?q?feature:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?=
 =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20metrics=20middleware=20=D0=B4=D0=BB=D1=8F?=
 =?UTF-8?q?=20=D0=BE=D1=81=D1=82=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D1=85=20?=
 =?UTF-8?q?=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81=D0=BE=D0=B2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 images/middleware/metrics_middleware.go       |  45 +++++
 pkg/clients/middleware/metrics_middleware.go  | 122 +++++++++++++
 .../middleware/metrics_middleware.go          |  96 +++++++++++
 .../middleware/metrics_middleware.go          | 123 +++++++++++++
 .../middleware/metrics_middleware.go          | 135 +++++++++++++++
 .../middleware/metrics_middleware.go          |  97 +++++++++++
 pkg/locales/middleware/metrics_middleware.go  |  70 ++++++++
 pkg/members/middleware/metrics_middleware.go  | 109 ++++++++++++
 .../middleware/metrics_middleware.go          |  97 +++++++++++
 pkg/roles/middleware/metrics_middleware.go    |  96 +++++++++++
 pkg/spaces/middleware/metrics_middleware.go   | 161 ++++++++++++++++++
 pkg/users/middleware/metrics_middleware.go    | 110 ++++++++++++
 12 files changed, 1261 insertions(+)
 create mode 100644 images/middleware/metrics_middleware.go
 create mode 100644 pkg/clients/middleware/metrics_middleware.go
 create mode 100644 pkg/collaborators/middleware/metrics_middleware.go
 create mode 100644 pkg/collections/middleware/metrics_middleware.go
 create mode 100644 pkg/environments/middleware/metrics_middleware.go
 create mode 100644 pkg/invitations/middleware/metrics_middleware.go
 create mode 100644 pkg/locales/middleware/metrics_middleware.go
 create mode 100644 pkg/members/middleware/metrics_middleware.go
 create mode 100644 pkg/organizations/middleware/metrics_middleware.go
 create mode 100644 pkg/roles/middleware/metrics_middleware.go
 create mode 100644 pkg/spaces/middleware/metrics_middleware.go
 create mode 100644 pkg/users/middleware/metrics_middleware.go

diff --git a/images/middleware/metrics_middleware.go b/images/middleware/metrics_middleware.go
new file mode 100644
index 00000000..2ed5e6ad
--- /dev/null
+++ b/images/middleware/metrics_middleware.go
@@ -0,0 +1,45 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/images -i Images -t ../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/images"
+	"git.perx.ru/perxis/perxis-go/pkg/files"
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements images.Images that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           images.Images
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next images.Images) images.Images {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Get implements images.Images
+func (m metricsMiddleware) Get(ctx context.Context, source *files.File, opts *images.GetOptions) (result *files.File, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, source, opts)
+}
diff --git a/pkg/clients/middleware/metrics_middleware.go b/pkg/clients/middleware/metrics_middleware.go
new file mode 100644
index 00000000..b96bac06
--- /dev/null
+++ b/pkg/clients/middleware/metrics_middleware.go
@@ -0,0 +1,122 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/clients -i Clients -t ../../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/clients"
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements clients.Clients that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           clients.Clients
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next clients.Clients) clients.Clients {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Create implements clients.Clients
+func (m metricsMiddleware) Create(ctx context.Context, client *clients.Client) (created *clients.Client, err error) {
+	m.requestMetrics.Total.WithLabelValues("Create").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc()
+		}
+	}()
+	return m.next.Create(ctx, client)
+}
+
+// Delete implements clients.Clients
+func (m metricsMiddleware) Delete(ctx context.Context, spaceId string, id string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Delete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc()
+		}
+	}()
+	return m.next.Delete(ctx, spaceId, id)
+}
+
+// Enable implements clients.Clients
+func (m metricsMiddleware) Enable(ctx context.Context, spaceId string, id string, enable bool) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Enable").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Enable"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Enable").Inc()
+		}
+	}()
+	return m.next.Enable(ctx, spaceId, id, enable)
+}
+
+// Get implements clients.Clients
+func (m metricsMiddleware) Get(ctx context.Context, spaceId string, id string) (client *clients.Client, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, spaceId, id)
+}
+
+// GetBy implements clients.Clients
+func (m metricsMiddleware) GetBy(ctx context.Context, spaceId string, params *clients.GetByParams) (client *clients.Client, err error) {
+	m.requestMetrics.Total.WithLabelValues("GetBy").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("GetBy"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("GetBy").Inc()
+		}
+	}()
+	return m.next.GetBy(ctx, spaceId, params)
+}
+
+// List implements clients.Clients
+func (m metricsMiddleware) List(ctx context.Context, spaceId string) (clients []*clients.Client, err error) {
+	m.requestMetrics.Total.WithLabelValues("List").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("List"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("List").Inc()
+		}
+	}()
+	return m.next.List(ctx, spaceId)
+}
+
+// Update implements clients.Clients
+func (m metricsMiddleware) Update(ctx context.Context, client *clients.Client) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Update").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Update"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Update").Inc()
+		}
+	}()
+	return m.next.Update(ctx, client)
+}
diff --git a/pkg/collaborators/middleware/metrics_middleware.go b/pkg/collaborators/middleware/metrics_middleware.go
new file mode 100644
index 00000000..00eb495f
--- /dev/null
+++ b/pkg/collaborators/middleware/metrics_middleware.go
@@ -0,0 +1,96 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/collaborators -i Collaborators -t ../../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/collaborators"
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements collaborators.Collaborators that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           collaborators.Collaborators
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next collaborators.Collaborators) collaborators.Collaborators {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Get implements collaborators.Collaborators
+func (m metricsMiddleware) Get(ctx context.Context, spaceId string, subject string) (role string, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, spaceId, subject)
+}
+
+// ListCollaborators implements collaborators.Collaborators
+func (m metricsMiddleware) ListCollaborators(ctx context.Context, spaceId string) (collaborators []*collaborators.Collaborator, err error) {
+	m.requestMetrics.Total.WithLabelValues("ListCollaborators").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("ListCollaborators"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("ListCollaborators").Inc()
+		}
+	}()
+	return m.next.ListCollaborators(ctx, spaceId)
+}
+
+// ListSpaces implements collaborators.Collaborators
+func (m metricsMiddleware) ListSpaces(ctx context.Context, subject string) (spaces []*collaborators.Collaborator, err error) {
+	m.requestMetrics.Total.WithLabelValues("ListSpaces").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("ListSpaces"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("ListSpaces").Inc()
+		}
+	}()
+	return m.next.ListSpaces(ctx, subject)
+}
+
+// Remove implements collaborators.Collaborators
+func (m metricsMiddleware) Remove(ctx context.Context, spaceId string, subject string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Remove").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Remove"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Remove").Inc()
+		}
+	}()
+	return m.next.Remove(ctx, spaceId, subject)
+}
+
+// Set implements collaborators.Collaborators
+func (m metricsMiddleware) Set(ctx context.Context, spaceId string, subject string, role string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Set").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Set"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Set").Inc()
+		}
+	}()
+	return m.next.Set(ctx, spaceId, subject, role)
+}
diff --git a/pkg/collections/middleware/metrics_middleware.go b/pkg/collections/middleware/metrics_middleware.go
new file mode 100644
index 00000000..b98b6266
--- /dev/null
+++ b/pkg/collections/middleware/metrics_middleware.go
@@ -0,0 +1,123 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// 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/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/collections"
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"git.perx.ru/perxis/perxis-go/pkg/schema"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements collections.Collections that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           collections.Collections
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next collections.Collections) collections.Collections {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Create implements collections.Collections
+func (m metricsMiddleware) Create(ctx context.Context, collection *collections.Collection) (created *collections.Collection, err error) {
+	m.requestMetrics.Total.WithLabelValues("Create").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc()
+		}
+	}()
+	return m.next.Create(ctx, collection)
+}
+
+// Delete implements collections.Collections
+func (m metricsMiddleware) Delete(ctx context.Context, spaceId string, envId string, collectionId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Delete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc()
+		}
+	}()
+	return m.next.Delete(ctx, spaceId, envId, collectionId)
+}
+
+// Get implements collections.Collections
+func (m metricsMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, options ...*collections.GetOptions) (collection *collections.Collection, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, spaceId, envId, collectionId, options...)
+}
+
+// List implements collections.Collections
+func (m metricsMiddleware) List(ctx context.Context, spaceId string, envId string, filter *collections.Filter) (collections []*collections.Collection, err error) {
+	m.requestMetrics.Total.WithLabelValues("List").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("List"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("List").Inc()
+		}
+	}()
+	return m.next.List(ctx, spaceId, envId, filter)
+}
+
+// SetSchema implements collections.Collections
+func (m metricsMiddleware) SetSchema(ctx context.Context, spaceId string, envId string, collectionId string, schema *schema.Schema) (err error) {
+	m.requestMetrics.Total.WithLabelValues("SetSchema").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("SetSchema"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("SetSchema").Inc()
+		}
+	}()
+	return m.next.SetSchema(ctx, spaceId, envId, collectionId, schema)
+}
+
+// SetState implements collections.Collections
+func (m metricsMiddleware) SetState(ctx context.Context, spaceId string, envId string, collectionId string, state *collections.StateInfo) (err error) {
+	m.requestMetrics.Total.WithLabelValues("SetState").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("SetState"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("SetState").Inc()
+		}
+	}()
+	return m.next.SetState(ctx, spaceId, envId, collectionId, state)
+}
+
+// Update implements collections.Collections
+func (m metricsMiddleware) Update(ctx context.Context, coll *collections.Collection) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Update").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Update"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Update").Inc()
+		}
+	}()
+	return m.next.Update(ctx, coll)
+}
diff --git a/pkg/environments/middleware/metrics_middleware.go b/pkg/environments/middleware/metrics_middleware.go
new file mode 100644
index 00000000..da593edc
--- /dev/null
+++ b/pkg/environments/middleware/metrics_middleware.go
@@ -0,0 +1,135 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/environments -i Environments -t ../../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/environments"
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements environments.Environments that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           environments.Environments
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next environments.Environments) environments.Environments {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Create implements environments.Environments
+func (m metricsMiddleware) Create(ctx context.Context, env *environments.Environment) (created *environments.Environment, err error) {
+	m.requestMetrics.Total.WithLabelValues("Create").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc()
+		}
+	}()
+	return m.next.Create(ctx, env)
+}
+
+// Delete implements environments.Environments
+func (m metricsMiddleware) Delete(ctx context.Context, spaceId string, envId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Delete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc()
+		}
+	}()
+	return m.next.Delete(ctx, spaceId, envId)
+}
+
+// Get implements environments.Environments
+func (m metricsMiddleware) Get(ctx context.Context, spaceId string, envId string) (env *environments.Environment, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, spaceId, envId)
+}
+
+// List implements environments.Environments
+func (m metricsMiddleware) List(ctx context.Context, spaceId string) (envs []*environments.Environment, err error) {
+	m.requestMetrics.Total.WithLabelValues("List").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("List"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("List").Inc()
+		}
+	}()
+	return m.next.List(ctx, spaceId)
+}
+
+// Migrate implements environments.Environments
+func (m metricsMiddleware) Migrate(ctx context.Context, spaceId string, envId string, options ...*environments.MigrateOptions) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Migrate").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Migrate"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Migrate").Inc()
+		}
+	}()
+	return m.next.Migrate(ctx, spaceId, envId, options...)
+}
+
+// RemoveAlias implements environments.Environments
+func (m metricsMiddleware) RemoveAlias(ctx context.Context, spaceId string, envId string, alias string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("RemoveAlias").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("RemoveAlias"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("RemoveAlias").Inc()
+		}
+	}()
+	return m.next.RemoveAlias(ctx, spaceId, envId, alias)
+}
+
+// SetAlias implements environments.Environments
+func (m metricsMiddleware) SetAlias(ctx context.Context, spaceId string, envId string, alias string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("SetAlias").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("SetAlias"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("SetAlias").Inc()
+		}
+	}()
+	return m.next.SetAlias(ctx, spaceId, envId, alias)
+}
+
+// Update implements environments.Environments
+func (m metricsMiddleware) Update(ctx context.Context, env *environments.Environment) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Update").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Update"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Update").Inc()
+		}
+	}()
+	return m.next.Update(ctx, env)
+}
diff --git a/pkg/invitations/middleware/metrics_middleware.go b/pkg/invitations/middleware/metrics_middleware.go
new file mode 100644
index 00000000..8ce2d3b7
--- /dev/null
+++ b/pkg/invitations/middleware/metrics_middleware.go
@@ -0,0 +1,97 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/invitations -i Invitations -t ../../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/invitations"
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"git.perx.ru/perxis/perxis-go/pkg/options"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements invitations.Invitations that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           invitations.Invitations
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next invitations.Invitations) invitations.Invitations {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Accept implements invitations.Invitations
+func (m metricsMiddleware) Accept(ctx context.Context, invitationId string, userId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Accept").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Accept"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Accept").Inc()
+		}
+	}()
+	return m.next.Accept(ctx, invitationId, userId)
+}
+
+// Create implements invitations.Invitations
+func (m metricsMiddleware) Create(ctx context.Context, invitation *invitations.Invitation) (created *invitations.Invitation, err error) {
+	m.requestMetrics.Total.WithLabelValues("Create").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc()
+		}
+	}()
+	return m.next.Create(ctx, invitation)
+}
+
+// Delete implements invitations.Invitations
+func (m metricsMiddleware) Delete(ctx context.Context, invitationId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Delete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc()
+		}
+	}()
+	return m.next.Delete(ctx, invitationId)
+}
+
+// Find implements invitations.Invitations
+func (m metricsMiddleware) Find(ctx context.Context, filter *invitations.Filter, opts *options.FindOptions) (invitations []*invitations.Invitation, total int, err error) {
+	m.requestMetrics.Total.WithLabelValues("Find").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Find"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Find").Inc()
+		}
+	}()
+	return m.next.Find(ctx, filter, opts)
+}
+
+// Get implements invitations.Invitations
+func (m metricsMiddleware) Get(ctx context.Context, invitationId string) (invitation *invitations.Invitation, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, invitationId)
+}
diff --git a/pkg/locales/middleware/metrics_middleware.go b/pkg/locales/middleware/metrics_middleware.go
new file mode 100644
index 00000000..cdd45c97
--- /dev/null
+++ b/pkg/locales/middleware/metrics_middleware.go
@@ -0,0 +1,70 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/locales -i Locales -t ../../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/locales"
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements locales.Locales that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           locales.Locales
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next locales.Locales) locales.Locales {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Create implements locales.Locales
+func (m metricsMiddleware) Create(ctx context.Context, locale *locales.Locale) (created *locales.Locale, err error) {
+	m.requestMetrics.Total.WithLabelValues("Create").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc()
+		}
+	}()
+	return m.next.Create(ctx, locale)
+}
+
+// Delete implements locales.Locales
+func (m metricsMiddleware) Delete(ctx context.Context, spaceId string, localeId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Delete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc()
+		}
+	}()
+	return m.next.Delete(ctx, spaceId, localeId)
+}
+
+// List implements locales.Locales
+func (m metricsMiddleware) List(ctx context.Context, spaceId string) (locales []*locales.Locale, err error) {
+	m.requestMetrics.Total.WithLabelValues("List").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("List"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("List").Inc()
+		}
+	}()
+	return m.next.List(ctx, spaceId)
+}
diff --git a/pkg/members/middleware/metrics_middleware.go b/pkg/members/middleware/metrics_middleware.go
new file mode 100644
index 00000000..27b28e64
--- /dev/null
+++ b/pkg/members/middleware/metrics_middleware.go
@@ -0,0 +1,109 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/members -i Members -t ../../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/members"
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements members.Members that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           members.Members
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next members.Members) members.Members {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Get implements members.Members
+func (m metricsMiddleware) Get(ctx context.Context, orgId string, userId string) (role members.Role, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, orgId, userId)
+}
+
+// ListMembers implements members.Members
+func (m metricsMiddleware) ListMembers(ctx context.Context, orgId string) (members []*members.Member, err error) {
+	m.requestMetrics.Total.WithLabelValues("ListMembers").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("ListMembers"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("ListMembers").Inc()
+		}
+	}()
+	return m.next.ListMembers(ctx, orgId)
+}
+
+// ListOrganizations implements members.Members
+func (m metricsMiddleware) ListOrganizations(ctx context.Context, userId string) (organizations []*members.Member, err error) {
+	m.requestMetrics.Total.WithLabelValues("ListOrganizations").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("ListOrganizations"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("ListOrganizations").Inc()
+		}
+	}()
+	return m.next.ListOrganizations(ctx, userId)
+}
+
+// Remove implements members.Members
+func (m metricsMiddleware) Remove(ctx context.Context, orgId string, userId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Remove").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Remove"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Remove").Inc()
+		}
+	}()
+	return m.next.Remove(ctx, orgId, userId)
+}
+
+// RemoveAll implements members.Members
+func (m metricsMiddleware) RemoveAll(ctx context.Context, orgId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("RemoveAll").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("RemoveAll"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("RemoveAll").Inc()
+		}
+	}()
+	return m.next.RemoveAll(ctx, orgId)
+}
+
+// Set implements members.Members
+func (m metricsMiddleware) Set(ctx context.Context, orgId string, userId string, role members.Role) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Set").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Set"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Set").Inc()
+		}
+	}()
+	return m.next.Set(ctx, orgId, userId, role)
+}
diff --git a/pkg/organizations/middleware/metrics_middleware.go b/pkg/organizations/middleware/metrics_middleware.go
new file mode 100644
index 00000000..c7cbccc6
--- /dev/null
+++ b/pkg/organizations/middleware/metrics_middleware.go
@@ -0,0 +1,97 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/organizations -i Organizations -t ../../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"git.perx.ru/perxis/perxis-go/pkg/options"
+	"git.perx.ru/perxis/perxis-go/pkg/organizations"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements organizations.Organizations that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           organizations.Organizations
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next organizations.Organizations) organizations.Organizations {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Create implements organizations.Organizations
+func (m metricsMiddleware) Create(ctx context.Context, org *organizations.Organization) (created *organizations.Organization, err error) {
+	m.requestMetrics.Total.WithLabelValues("Create").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc()
+		}
+	}()
+	return m.next.Create(ctx, org)
+}
+
+// Delete implements organizations.Organizations
+func (m metricsMiddleware) Delete(ctx context.Context, orgId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Delete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc()
+		}
+	}()
+	return m.next.Delete(ctx, orgId)
+}
+
+// Find implements organizations.Organizations
+func (m metricsMiddleware) Find(ctx context.Context, filter *organizations.Filter, opts *options.FindOptions) (orgs []*organizations.Organization, total int, err error) {
+	m.requestMetrics.Total.WithLabelValues("Find").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Find"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Find").Inc()
+		}
+	}()
+	return m.next.Find(ctx, filter, opts)
+}
+
+// Get implements organizations.Organizations
+func (m metricsMiddleware) Get(ctx context.Context, orgId string) (org *organizations.Organization, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, orgId)
+}
+
+// Update implements organizations.Organizations
+func (m metricsMiddleware) Update(ctx context.Context, org *organizations.Organization) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Update").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Update"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Update").Inc()
+		}
+	}()
+	return m.next.Update(ctx, org)
+}
diff --git a/pkg/roles/middleware/metrics_middleware.go b/pkg/roles/middleware/metrics_middleware.go
new file mode 100644
index 00000000..1df246c1
--- /dev/null
+++ b/pkg/roles/middleware/metrics_middleware.go
@@ -0,0 +1,96 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/roles -i Roles -t ../../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"git.perx.ru/perxis/perxis-go/pkg/roles"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements roles.Roles that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           roles.Roles
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next roles.Roles) roles.Roles {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Create implements roles.Roles
+func (m metricsMiddleware) Create(ctx context.Context, role *roles.Role) (created *roles.Role, err error) {
+	m.requestMetrics.Total.WithLabelValues("Create").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc()
+		}
+	}()
+	return m.next.Create(ctx, role)
+}
+
+// Delete implements roles.Roles
+func (m metricsMiddleware) Delete(ctx context.Context, spaceId string, roleId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Delete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc()
+		}
+	}()
+	return m.next.Delete(ctx, spaceId, roleId)
+}
+
+// Get implements roles.Roles
+func (m metricsMiddleware) Get(ctx context.Context, spaceId string, roleId string) (role *roles.Role, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, spaceId, roleId)
+}
+
+// List implements roles.Roles
+func (m metricsMiddleware) List(ctx context.Context, spaceId string) (roles []*roles.Role, err error) {
+	m.requestMetrics.Total.WithLabelValues("List").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("List"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("List").Inc()
+		}
+	}()
+	return m.next.List(ctx, spaceId)
+}
+
+// Update implements roles.Roles
+func (m metricsMiddleware) Update(ctx context.Context, role *roles.Role) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Update").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Update"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Update").Inc()
+		}
+	}()
+	return m.next.Update(ctx, role)
+}
diff --git a/pkg/spaces/middleware/metrics_middleware.go b/pkg/spaces/middleware/metrics_middleware.go
new file mode 100644
index 00000000..ba8d95a6
--- /dev/null
+++ b/pkg/spaces/middleware/metrics_middleware.go
@@ -0,0 +1,161 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/spaces -i Spaces -t ../../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"git.perx.ru/perxis/perxis-go/pkg/spaces"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements spaces.Spaces that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           spaces.Spaces
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next spaces.Spaces) spaces.Spaces {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// AbortTransfer implements spaces.Spaces
+func (m metricsMiddleware) AbortTransfer(ctx context.Context, spaceID string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("AbortTransfer").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("AbortTransfer"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("AbortTransfer").Inc()
+		}
+	}()
+	return m.next.AbortTransfer(ctx, spaceID)
+}
+
+// Create implements spaces.Spaces
+func (m metricsMiddleware) Create(ctx context.Context, space *spaces.Space) (created *spaces.Space, err error) {
+	m.requestMetrics.Total.WithLabelValues("Create").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc()
+		}
+	}()
+	return m.next.Create(ctx, space)
+}
+
+// Delete implements spaces.Spaces
+func (m metricsMiddleware) Delete(ctx context.Context, spaceId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Delete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc()
+		}
+	}()
+	return m.next.Delete(ctx, spaceId)
+}
+
+// Get implements spaces.Spaces
+func (m metricsMiddleware) Get(ctx context.Context, spaceId string) (space *spaces.Space, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, spaceId)
+}
+
+// List implements spaces.Spaces
+func (m metricsMiddleware) List(ctx context.Context, orgId string) (spaces []*spaces.Space, err error) {
+	m.requestMetrics.Total.WithLabelValues("List").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("List"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("List").Inc()
+		}
+	}()
+	return m.next.List(ctx, orgId)
+}
+
+// ListTransfers implements spaces.Spaces
+func (m metricsMiddleware) ListTransfers(ctx context.Context, orgID string) (spaces []*spaces.Space, err error) {
+	m.requestMetrics.Total.WithLabelValues("ListTransfers").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("ListTransfers"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("ListTransfers").Inc()
+		}
+	}()
+	return m.next.ListTransfers(ctx, orgID)
+}
+
+// Move implements spaces.Spaces
+func (m metricsMiddleware) Move(ctx context.Context, spaceID string, orgID string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Move").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Move"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Move").Inc()
+		}
+	}()
+	return m.next.Move(ctx, spaceID, orgID)
+}
+
+// Transfer implements spaces.Spaces
+func (m metricsMiddleware) Transfer(ctx context.Context, spaceID string, transferToOrg string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Transfer").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Transfer"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Transfer").Inc()
+		}
+	}()
+	return m.next.Transfer(ctx, spaceID, transferToOrg)
+}
+
+// Update implements spaces.Spaces
+func (m metricsMiddleware) Update(ctx context.Context, space *spaces.Space) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Update").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Update"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Update").Inc()
+		}
+	}()
+	return m.next.Update(ctx, space)
+}
+
+// UpdateConfig implements spaces.Spaces
+func (m metricsMiddleware) UpdateConfig(ctx context.Context, spaceId string, config *spaces.Config) (err error) {
+	m.requestMetrics.Total.WithLabelValues("UpdateConfig").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("UpdateConfig"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("UpdateConfig").Inc()
+		}
+	}()
+	return m.next.UpdateConfig(ctx, spaceId, config)
+}
diff --git a/pkg/users/middleware/metrics_middleware.go b/pkg/users/middleware/metrics_middleware.go
new file mode 100644
index 00000000..df214661
--- /dev/null
+++ b/pkg/users/middleware/metrics_middleware.go
@@ -0,0 +1,110 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/metrics
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/users -i Users -t ../../../assets/templates/middleware/metrics -o metrics_middleware.go -l ""
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/metrics"
+	"git.perx.ru/perxis/perxis-go/pkg/options"
+	"git.perx.ru/perxis/perxis-go/pkg/users"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+// metricsMiddleware implements users.Users that is instrumented with metrics
+type metricsMiddleware struct {
+	requestMetrics *metrics.RequestMetrics
+	next           users.Users
+}
+
+// MetricsMiddleware instruments an implementation of the metricsMiddleware with metrics
+func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware {
+	return func(next users.Users) users.Users {
+		return &metricsMiddleware{
+			requestMetrics: requestMetrics,
+			next:           next,
+		}
+	}
+}
+
+// Create implements users.Users
+func (m metricsMiddleware) Create(ctx context.Context, create *users.User) (user *users.User, err error) {
+	m.requestMetrics.Total.WithLabelValues("Create").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc()
+		}
+	}()
+	return m.next.Create(ctx, create)
+}
+
+// Delete implements users.Users
+func (m metricsMiddleware) Delete(ctx context.Context, userId string) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Delete").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc()
+		}
+	}()
+	return m.next.Delete(ctx, userId)
+}
+
+// Find implements users.Users
+func (m metricsMiddleware) Find(ctx context.Context, filter *users.Filter, options *options.FindOptions) (users []*users.User, total int, err error) {
+	m.requestMetrics.Total.WithLabelValues("Find").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Find"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Find").Inc()
+		}
+	}()
+	return m.next.Find(ctx, filter, options)
+}
+
+// Get implements users.Users
+func (m metricsMiddleware) Get(ctx context.Context, userId string) (user *users.User, err error) {
+	m.requestMetrics.Total.WithLabelValues("Get").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc()
+		}
+	}()
+	return m.next.Get(ctx, userId)
+}
+
+// GetByIdentity implements users.Users
+func (m metricsMiddleware) GetByIdentity(ctx context.Context, identity string) (user *users.User, err error) {
+	m.requestMetrics.Total.WithLabelValues("GetByIdentity").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("GetByIdentity"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("GetByIdentity").Inc()
+		}
+	}()
+	return m.next.GetByIdentity(ctx, identity)
+}
+
+// Update implements users.Users
+func (m metricsMiddleware) Update(ctx context.Context, update *users.User) (err error) {
+	m.requestMetrics.Total.WithLabelValues("Update").Inc()
+	timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Update"))
+	defer func() {
+		timer.ObserveDuration()
+		if err != nil {
+			m.requestMetrics.FailedTotal.WithLabelValues("Update").Inc()
+		}
+	}()
+	return m.next.Update(ctx, update)
+}
-- 
GitLab