diff --git a/pkg/extension/middleware/telemetry_middleware.go b/pkg/extension/middleware/telemetry_middleware.go
new file mode 100644
index 0000000000000000000000000000000000000000..764e7cbd2de929e5550b8175a5ec7713b361f3cb
--- /dev/null
+++ b/pkg/extension/middleware/telemetry_middleware.go
@@ -0,0 +1,318 @@
+// Code generated by gowrap. DO NOT EDIT.
+// template: ../../../assets/templates/middleware/telemetry
+// gowrap: http://github.com/hexdigest/gowrap
+
+package middleware
+
+//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/extension -i Manager -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l ""
+
+// source template: https://github.com/hexdigest/gowrap/blob/master/templates/opentelemetry
+
+import (
+	"context"
+	"time"
+
+	"git.perx.ru/perxis/perxis-go/pkg/extension"
+	"git.perx.ru/perxis/perxis-go/pkg/telemetry/metrics"
+	"go.opentelemetry.io/otel"
+	"go.opentelemetry.io/otel/attribute"
+	otelmetric "go.opentelemetry.io/otel/metric"
+	"go.opentelemetry.io/otel/trace"
+)
+
+// telemetryMiddleware implements extension.Manager interface instrumented with opentracing spans
+type telemetryMiddleware struct {
+	extension.Manager
+	_instance      string
+	requestMetrics *metrics.RequestMetrics
+	_spanDecorator func(span trace.Span, params, results map[string]interface{})
+}
+
+// TelemetryMiddleware returns telemetryMiddleware
+func TelemetryMiddleware(base extension.Manager, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware {
+	requestMetrics, err := metrics.GetRequestMetrics()
+	if err != nil {
+		panic(err)
+	}
+
+	d := telemetryMiddleware{
+		Manager:        base,
+		_instance:      instance,
+		requestMetrics: requestMetrics,
+	}
+
+	if len(spanDecorator) > 0 && spanDecorator[0] != nil {
+		d._spanDecorator = spanDecorator[0]
+	}
+
+	return d
+}
+
+// Action implements extension.Manager
+func (_d telemetryMiddleware) Action(ctx context.Context, in *extension.ActionRequest) (ap1 *extension.ActionResponse, err error) {
+	attributes := otelmetric.WithAttributeSet(attribute.NewSet(
+		attribute.String("service", "Manager"),
+		attribute.String("method", "Action"),
+	))
+
+	_d.requestMetrics.Total.Add(ctx, 1, attributes)
+
+	start := time.Now()
+	ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Manager.Action")
+
+	defer func() {
+		_d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes)
+
+		if _d._spanDecorator != nil {
+			_d._spanDecorator(_span, map[string]interface{}{
+				"ctx": ctx,
+				"in":  in}, map[string]interface{}{
+				"ap1": ap1,
+				"err": err})
+		} else if err != nil {
+			_d.requestMetrics.FailedTotal.Add(ctx, 1, attributes)
+
+			_span.RecordError(err)
+			_span.SetAttributes(attribute.String("event", "error"))
+			_span.SetAttributes(attribute.String("message", err.Error()))
+		}
+
+		_span.End()
+	}()
+	return _d.Manager.Action(ctx, in)
+}
+
+// Check implements extension.Manager
+func (_d telemetryMiddleware) Check(ctx context.Context, in *extension.CheckRequest) (err error) {
+	attributes := otelmetric.WithAttributeSet(attribute.NewSet(
+		attribute.String("service", "Manager"),
+		attribute.String("method", "Check"),
+	))
+
+	_d.requestMetrics.Total.Add(ctx, 1, attributes)
+
+	start := time.Now()
+	ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Manager.Check")
+
+	defer func() {
+		_d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes)
+
+		if _d._spanDecorator != nil {
+			_d._spanDecorator(_span, map[string]interface{}{
+				"ctx": ctx,
+				"in":  in}, map[string]interface{}{
+				"err": err})
+		} else if err != nil {
+			_d.requestMetrics.FailedTotal.Add(ctx, 1, attributes)
+
+			_span.RecordError(err)
+			_span.SetAttributes(attribute.String("event", "error"))
+			_span.SetAttributes(attribute.String("message", err.Error()))
+		}
+
+		_span.End()
+	}()
+	return _d.Manager.Check(ctx, in)
+}
+
+// Install implements extension.Manager
+func (_d telemetryMiddleware) Install(ctx context.Context, in *extension.InstallRequest) (err error) {
+	attributes := otelmetric.WithAttributeSet(attribute.NewSet(
+		attribute.String("service", "Manager"),
+		attribute.String("method", "Install"),
+	))
+
+	_d.requestMetrics.Total.Add(ctx, 1, attributes)
+
+	start := time.Now()
+	ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Manager.Install")
+
+	defer func() {
+		_d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes)
+
+		if _d._spanDecorator != nil {
+			_d._spanDecorator(_span, map[string]interface{}{
+				"ctx": ctx,
+				"in":  in}, map[string]interface{}{
+				"err": err})
+		} else if err != nil {
+			_d.requestMetrics.FailedTotal.Add(ctx, 1, attributes)
+
+			_span.RecordError(err)
+			_span.SetAttributes(attribute.String("event", "error"))
+			_span.SetAttributes(attribute.String("message", err.Error()))
+		}
+
+		_span.End()
+	}()
+	return _d.Manager.Install(ctx, in)
+}
+
+// ListExtensions implements extension.Manager
+func (_d telemetryMiddleware) ListExtensions(ctx context.Context, space string, env string, filter *extension.ListExtensionsFilter) (ipa1 []*extension.Info, err error) {
+	attributes := otelmetric.WithAttributeSet(attribute.NewSet(
+		attribute.String("service", "Manager"),
+		attribute.String("method", "ListExtensions"),
+	))
+
+	_d.requestMetrics.Total.Add(ctx, 1, attributes)
+
+	start := time.Now()
+	ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Manager.ListExtensions")
+
+	defer func() {
+		_d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes)
+
+		if _d._spanDecorator != nil {
+			_d._spanDecorator(_span, map[string]interface{}{
+				"ctx":    ctx,
+				"space":  space,
+				"env":    env,
+				"filter": filter}, map[string]interface{}{
+				"ipa1": ipa1,
+				"err":  err})
+		} else if err != nil {
+			_d.requestMetrics.FailedTotal.Add(ctx, 1, attributes)
+
+			_span.RecordError(err)
+			_span.SetAttributes(attribute.String("event", "error"))
+			_span.SetAttributes(attribute.String("message", err.Error()))
+		}
+
+		_span.End()
+	}()
+	return _d.Manager.ListExtensions(ctx, space, env, filter)
+}
+
+// ListRegisteredExtensions implements extension.Manager
+func (_d telemetryMiddleware) ListRegisteredExtensions(ctx context.Context, extensions ...string) (epa1 []*extension.ExtensionConnector, err error) {
+	attributes := otelmetric.WithAttributeSet(attribute.NewSet(
+		attribute.String("service", "Manager"),
+		attribute.String("method", "ListRegisteredExtensions"),
+	))
+
+	_d.requestMetrics.Total.Add(ctx, 1, attributes)
+
+	start := time.Now()
+	ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Manager.ListRegisteredExtensions")
+
+	defer func() {
+		_d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes)
+
+		if _d._spanDecorator != nil {
+			_d._spanDecorator(_span, map[string]interface{}{
+				"ctx":        ctx,
+				"extensions": extensions}, map[string]interface{}{
+				"epa1": epa1,
+				"err":  err})
+		} else if err != nil {
+			_d.requestMetrics.FailedTotal.Add(ctx, 1, attributes)
+
+			_span.RecordError(err)
+			_span.SetAttributes(attribute.String("event", "error"))
+			_span.SetAttributes(attribute.String("message", err.Error()))
+		}
+
+		_span.End()
+	}()
+	return _d.Manager.ListRegisteredExtensions(ctx, extensions...)
+}
+
+// RegisterExtensions implements extension.Manager
+func (_d telemetryMiddleware) RegisterExtensions(ctx context.Context, ext ...*extension.ExtensionConnector) (err error) {
+	attributes := otelmetric.WithAttributeSet(attribute.NewSet(
+		attribute.String("service", "Manager"),
+		attribute.String("method", "RegisterExtensions"),
+	))
+
+	_d.requestMetrics.Total.Add(ctx, 1, attributes)
+
+	start := time.Now()
+	ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Manager.RegisterExtensions")
+
+	defer func() {
+		_d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes)
+
+		if _d._spanDecorator != nil {
+			_d._spanDecorator(_span, map[string]interface{}{
+				"ctx": ctx,
+				"ext": ext}, map[string]interface{}{
+				"err": err})
+		} else if err != nil {
+			_d.requestMetrics.FailedTotal.Add(ctx, 1, attributes)
+
+			_span.RecordError(err)
+			_span.SetAttributes(attribute.String("event", "error"))
+			_span.SetAttributes(attribute.String("message", err.Error()))
+		}
+
+		_span.End()
+	}()
+	return _d.Manager.RegisterExtensions(ctx, ext...)
+}
+
+// Uninstall implements extension.Manager
+func (_d telemetryMiddleware) Uninstall(ctx context.Context, in *extension.UninstallRequest) (err error) {
+	attributes := otelmetric.WithAttributeSet(attribute.NewSet(
+		attribute.String("service", "Manager"),
+		attribute.String("method", "Uninstall"),
+	))
+
+	_d.requestMetrics.Total.Add(ctx, 1, attributes)
+
+	start := time.Now()
+	ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Manager.Uninstall")
+
+	defer func() {
+		_d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes)
+
+		if _d._spanDecorator != nil {
+			_d._spanDecorator(_span, map[string]interface{}{
+				"ctx": ctx,
+				"in":  in}, map[string]interface{}{
+				"err": err})
+		} else if err != nil {
+			_d.requestMetrics.FailedTotal.Add(ctx, 1, attributes)
+
+			_span.RecordError(err)
+			_span.SetAttributes(attribute.String("event", "error"))
+			_span.SetAttributes(attribute.String("message", err.Error()))
+		}
+
+		_span.End()
+	}()
+	return _d.Manager.Uninstall(ctx, in)
+}
+
+// UnregisterExtensions implements extension.Manager
+func (_d telemetryMiddleware) UnregisterExtensions(ctx context.Context, ext ...*extension.ExtensionConnector) (err error) {
+	attributes := otelmetric.WithAttributeSet(attribute.NewSet(
+		attribute.String("service", "Manager"),
+		attribute.String("method", "UnregisterExtensions"),
+	))
+
+	_d.requestMetrics.Total.Add(ctx, 1, attributes)
+
+	start := time.Now()
+	ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Manager.UnregisterExtensions")
+
+	defer func() {
+		_d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes)
+
+		if _d._spanDecorator != nil {
+			_d._spanDecorator(_span, map[string]interface{}{
+				"ctx": ctx,
+				"ext": ext}, map[string]interface{}{
+				"err": err})
+		} else if err != nil {
+			_d.requestMetrics.FailedTotal.Add(ctx, 1, attributes)
+
+			_span.RecordError(err)
+			_span.SetAttributes(attribute.String("event", "error"))
+			_span.SetAttributes(attribute.String("message", err.Error()))
+		}
+
+		_span.End()
+	}()
+	return _d.Manager.UnregisterExtensions(ctx, ext...)
+}