diff --git a/assets/templates/middleware/telemetry b/assets/templates/middleware/telemetry index 3e893c09f161d2e832544f8bca625b6d63b3d990..f35cde213c9523050d863351757fb0ee560c73fe 100644 --- a/assets/templates/middleware/telemetry +++ b/assets/templates/middleware/telemetry @@ -1,8 +1,13 @@ +// source template: https://github.com/hexdigest/gowrap/blob/master/templates/opentelemetry + import ( "context" + "time" + "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" ) @@ -13,14 +18,21 @@ import ( type {{$decorator}} struct { {{.Interface.Type}} _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // {{$funcName}} returns {{$decorator}} func {{$funcName}} (base {{.Interface.Type}}, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) {{$decorator}} { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := {{$decorator}} { {{.Interface.Name}}: base, _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -34,11 +46,24 @@ func {{$funcName}} (base {{.Interface.Type}}, instance string, spanDecorator ... {{if $method.AcceptsContext}} // {{$method.Name}} implements {{$.Interface.Type}} func (_d {{$decorator}}) {{$method.Declaration}} { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "{{ $.Interface.Name }}"), + attribute.String("method", "{{ $method.Name }}"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "{{$.Interface.Name}}.{{$method.Name}}") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, {{$method.ParamsMap}}, {{$method.ResultsMap}}) }{{- if $method.ReturnsError}} 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())) diff --git a/go.mod b/go.mod index fcffea8fcde51f29c2f1f78523643a4b9cdd0329..8cd52d3b3533422183a392bd755566f2090087d5 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,11 @@ require ( gopkg.in/yaml.v3 v3.0.1 ) +require ( + github.com/kr/pretty v0.3.1 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect +) + require ( cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect @@ -43,20 +48,18 @@ require ( github.com/gosimple/unidecode v1.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/klauspost/compress v1.17.3 // indirect - github.com/kr/pretty v0.3.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/montanaflynn/stats v0.7.1 // indirect github.com/nats-io/nkeys v0.4.6 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/stretchr/objx v0.5.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.21.0 go.uber.org/multierr v1.11.0 // indirect golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.14.0 // indirect diff --git a/images/middleware/telemetry_middleware.go b/images/middleware/telemetry_middleware.go index 2c0aac8eeaa3507d16ee852fd47b4a46569bc827..72d38c2e1d91813383116398e5c41b9bb93004f4 100644 --- a/images/middleware/telemetry_middleware.go +++ b/images/middleware/telemetry_middleware.go @@ -1,18 +1,23 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// template: ..\..\assets\templates\middleware\telemetry // 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/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/images -i Images -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/images" "git.perx.ru/perxis/perxis-go/pkg/files" + "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" ) @@ -20,14 +25,21 @@ import ( type telemetryMiddleware struct { images.Images _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base images.Images, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Images: base, - _instance: instance, + Images: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -39,8 +51,19 @@ func TelemetryMiddleware(base images.Images, instance string, spanDecorator ...f // Get implements images.Images func (_d telemetryMiddleware) Get(ctx context.Context, source *files.File, opts *images.GetOptions) (result *files.File, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Images"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Images.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -49,6 +72,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, source *files.File, opts "result": result, "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())) diff --git a/pkg/cache/telemetry_middleware.go b/pkg/cache/telemetry_middleware.go new file mode 100644 index 0000000000000000000000000000000000000000..5c22fccef41c3068bfc4631fe8819dd39f31e43a --- /dev/null +++ b/pkg/cache/telemetry_middleware.go @@ -0,0 +1,48 @@ +package cache + +import ( + "context" + + "git.perx.ru/perxis/perxis-go/pkg/telemetry/metrics" + "go.opentelemetry.io/otel/attribute" + otelmetric "go.opentelemetry.io/otel/metric" +) + +type telemetryMiddleware struct { + next Cache + cacheMetrics *metrics.CacheMetrics + attributes otelmetric.MeasurementOption +} + +// TelemetryMiddleware возвращает обертку над кэшем, которая используется для отслеживания количества хитов и промахов в кэше. +func TelemetryMiddleware(next Cache, keyValues ...attribute.KeyValue) Cache { + cacheMetrics, err := metrics.GetCacheMetrics() + if err != nil { + panic(err) + } + + return &telemetryMiddleware{ + next: next, + cacheMetrics: cacheMetrics, + attributes: otelmetric.WithAttributes(keyValues...), + } +} + +func (c *telemetryMiddleware) Set(key, value any) error { + return c.next.Set(key, value) +} + +func (c *telemetryMiddleware) Get(key any) (any, error) { + value, err := c.next.Get(key) + if err != nil { + c.cacheMetrics.MissesTotal.Add(context.TODO(), 1, c.attributes) + return nil, err + } + c.cacheMetrics.HitsTotal.Add(context.TODO(), 1, c.attributes) + return value, nil +} + +func (c *telemetryMiddleware) Remove(key any) error { + c.cacheMetrics.InvalidatesTotal.Add(context.TODO(), 1, c.attributes) + return c.next.Remove(key) +} diff --git a/pkg/clients/middleware/telemetry_middleware.go b/pkg/clients/middleware/telemetry_middleware.go index d8536b10fcac0a1f237c688fe9a8bde3db93fdcf..22c604f2d5be413681ccdb933eb5c33a61517cc6 100644 --- a/pkg/clients/middleware/telemetry_middleware.go +++ b/pkg/clients/middleware/telemetry_middleware.go @@ -1,17 +1,22 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/clients -i Clients -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/clients -i Clients -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/clients" + "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" ) @@ -19,14 +24,21 @@ import ( type telemetryMiddleware struct { clients.Clients _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base clients.Clients, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Clients: base, - _instance: instance, + Clients: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -38,8 +50,19 @@ func TelemetryMiddleware(base clients.Clients, instance string, spanDecorator .. // Create implements clients.Clients func (_d telemetryMiddleware) Create(ctx context.Context, client *clients.Client) (created *clients.Client, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Clients"), + attribute.String("method", "Create"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Clients.Create") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -47,6 +70,8 @@ func (_d telemetryMiddleware) Create(ctx context.Context, client *clients.Client "created": created, "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())) @@ -59,8 +84,19 @@ func (_d telemetryMiddleware) Create(ctx context.Context, client *clients.Client // Delete implements clients.Clients func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, id string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Clients"), + attribute.String("method", "Delete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Clients.Delete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -68,6 +104,8 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, id str "id": id}, 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())) @@ -80,8 +118,19 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, id str // Enable implements clients.Clients func (_d telemetryMiddleware) Enable(ctx context.Context, spaceId string, id string, enable bool) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Clients"), + attribute.String("method", "Enable"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Clients.Enable") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -90,6 +139,8 @@ func (_d telemetryMiddleware) Enable(ctx context.Context, spaceId string, id str "enable": enable}, 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())) @@ -102,8 +153,19 @@ func (_d telemetryMiddleware) Enable(ctx context.Context, spaceId string, id str // Get implements clients.Clients func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, id string) (client *clients.Client, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Clients"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Clients.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -112,6 +174,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, id string "client": client, "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())) @@ -124,8 +188,19 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, id string // GetBy implements clients.Clients func (_d telemetryMiddleware) GetBy(ctx context.Context, spaceId string, params *clients.GetByParams) (client *clients.Client, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Clients"), + attribute.String("method", "GetBy"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Clients.GetBy") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -134,6 +209,8 @@ func (_d telemetryMiddleware) GetBy(ctx context.Context, spaceId string, params "client": client, "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())) @@ -146,8 +223,19 @@ func (_d telemetryMiddleware) GetBy(ctx context.Context, spaceId string, params // List implements clients.Clients func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (clients []*clients.Client, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Clients"), + attribute.String("method", "List"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Clients.List") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -155,6 +243,8 @@ func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (clients "clients": clients, "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())) @@ -167,14 +257,27 @@ func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (clients // Update implements clients.Clients func (_d telemetryMiddleware) Update(ctx context.Context, client *clients.Client) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Clients"), + attribute.String("method", "Update"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Clients.Update") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "client": client}, 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())) diff --git a/pkg/collaborators/middleware/telemetry_middleware.go b/pkg/collaborators/middleware/telemetry_middleware.go index 6a824f1e0a31c585d07b7ebb1bbf391963b0ca63..cd95016628ed34da1c6fdd5c951a14c766a8cabc 100644 --- a/pkg/collaborators/middleware/telemetry_middleware.go +++ b/pkg/collaborators/middleware/telemetry_middleware.go @@ -1,17 +1,22 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/collaborators -i Collaborators -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/collaborators -i Collaborators -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/collaborators" + "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" ) @@ -19,14 +24,21 @@ import ( type telemetryMiddleware struct { collaborators.Collaborators _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base collaborators.Collaborators, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Collaborators: base, - _instance: instance, + Collaborators: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -38,8 +50,19 @@ func TelemetryMiddleware(base collaborators.Collaborators, instance string, span // Get implements collaborators.Collaborators func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, subject string) (role string, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collaborators"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collaborators.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -48,6 +71,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, subject s "role": role, "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())) @@ -60,8 +85,19 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, subject s // ListCollaborators implements collaborators.Collaborators func (_d telemetryMiddleware) ListCollaborators(ctx context.Context, spaceId string) (collaborators []*collaborators.Collaborator, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collaborators"), + attribute.String("method", "ListCollaborators"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collaborators.ListCollaborators") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -69,6 +105,8 @@ func (_d telemetryMiddleware) ListCollaborators(ctx context.Context, spaceId str "collaborators": collaborators, "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())) @@ -81,8 +119,19 @@ func (_d telemetryMiddleware) ListCollaborators(ctx context.Context, spaceId str // ListSpaces implements collaborators.Collaborators func (_d telemetryMiddleware) ListSpaces(ctx context.Context, subject string) (spaces []*collaborators.Collaborator, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collaborators"), + attribute.String("method", "ListSpaces"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collaborators.ListSpaces") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -90,6 +139,8 @@ func (_d telemetryMiddleware) ListSpaces(ctx context.Context, subject string) (s "spaces": spaces, "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())) @@ -102,8 +153,19 @@ func (_d telemetryMiddleware) ListSpaces(ctx context.Context, subject string) (s // Remove implements collaborators.Collaborators func (_d telemetryMiddleware) Remove(ctx context.Context, spaceId string, subject string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collaborators"), + attribute.String("method", "Remove"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collaborators.Remove") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -111,6 +173,8 @@ func (_d telemetryMiddleware) Remove(ctx context.Context, spaceId string, subjec "subject": subject}, 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())) @@ -123,8 +187,19 @@ func (_d telemetryMiddleware) Remove(ctx context.Context, spaceId string, subjec // Set implements collaborators.Collaborators func (_d telemetryMiddleware) Set(ctx context.Context, spaceId string, subject string, role string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collaborators"), + attribute.String("method", "Set"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collaborators.Set") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -133,6 +208,8 @@ func (_d telemetryMiddleware) Set(ctx context.Context, spaceId string, subject s "role": role}, 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())) diff --git a/pkg/collections/middleware/telemetry_middleware.go b/pkg/collections/middleware/telemetry_middleware.go index 74a0d685c37c6b6d8bdb0b6453f50cfea83e7f07..306570dba01ac1d7faaf193d92f97820369a6ad2 100644 --- a/pkg/collections/middleware/telemetry_middleware.go +++ b/pkg/collections/middleware/telemetry_middleware.go @@ -1,18 +1,23 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/collections -i Collections -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/collections -i Collections -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/collections" "git.perx.ru/perxis/perxis-go/pkg/schema" + "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" ) @@ -20,14 +25,21 @@ import ( type telemetryMiddleware struct { collections.Collections _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base collections.Collections, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Collections: base, - _instance: instance, + Collections: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -39,8 +51,19 @@ func TelemetryMiddleware(base collections.Collections, instance string, spanDeco // Create implements collections.Collections func (_d telemetryMiddleware) Create(ctx context.Context, collection *collections.Collection) (created *collections.Collection, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collections"), + attribute.String("method", "Create"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collections.Create") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -48,6 +71,8 @@ func (_d telemetryMiddleware) Create(ctx context.Context, collection *collection "created": created, "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())) @@ -60,8 +85,19 @@ func (_d telemetryMiddleware) Create(ctx context.Context, collection *collection // Delete implements collections.Collections func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, envId string, collectionId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collections"), + attribute.String("method", "Delete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collections.Delete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -70,6 +106,8 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, envId "collectionId": collectionId}, 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())) @@ -82,8 +120,19 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, envId // Get implements collections.Collections func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, options ...*collections.GetOptions) (collection *collections.Collection, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collections"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collections.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -94,6 +143,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId str "collection": collection, "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())) @@ -106,8 +157,19 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId str // List implements collections.Collections func (_d telemetryMiddleware) List(ctx context.Context, spaceId string, envId string, filter *collections.Filter) (collections []*collections.Collection, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collections"), + attribute.String("method", "List"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collections.List") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -117,6 +179,8 @@ func (_d telemetryMiddleware) List(ctx context.Context, spaceId string, envId st "collections": collections, "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())) @@ -129,8 +193,19 @@ func (_d telemetryMiddleware) List(ctx context.Context, spaceId string, envId st // SetSchema implements collections.Collections func (_d telemetryMiddleware) SetSchema(ctx context.Context, spaceId string, envId string, collectionId string, schema *schema.Schema) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collections"), + attribute.String("method", "SetSchema"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collections.SetSchema") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -140,6 +215,8 @@ func (_d telemetryMiddleware) SetSchema(ctx context.Context, spaceId string, env "schema": schema}, 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())) @@ -152,8 +229,19 @@ func (_d telemetryMiddleware) SetSchema(ctx context.Context, spaceId string, env // SetState implements collections.Collections func (_d telemetryMiddleware) SetState(ctx context.Context, spaceId string, envId string, collectionId string, state *collections.StateInfo) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collections"), + attribute.String("method", "SetState"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collections.SetState") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -163,6 +251,8 @@ func (_d telemetryMiddleware) SetState(ctx context.Context, spaceId string, envI "state": state}, 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())) @@ -175,14 +265,27 @@ func (_d telemetryMiddleware) SetState(ctx context.Context, spaceId string, envI // Update implements collections.Collections func (_d telemetryMiddleware) Update(ctx context.Context, coll *collections.Collection) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Collections"), + attribute.String("method", "Update"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Collections.Update") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "coll": coll}, 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())) diff --git a/pkg/delivery/middleware/telemetry_middleware.go b/pkg/delivery/middleware/telemetry_middleware.go index 9468782004efd635902eea18b2a174e411a49be4..05a017300c0b2d60c0cc03df333c62365babffa6 100644 --- a/pkg/delivery/middleware/telemetry_middleware.go +++ b/pkg/delivery/middleware/telemetry_middleware.go @@ -1,21 +1,26 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/delivery -i Delivery -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/delivery -i Delivery -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/collections" "git.perx.ru/perxis/perxis-go/pkg/delivery" "git.perx.ru/perxis/perxis-go/pkg/environments" "git.perx.ru/perxis/perxis-go/pkg/items" "git.perx.ru/perxis/perxis-go/pkg/locales" + "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" ) @@ -23,14 +28,21 @@ import ( type telemetryMiddleware struct { delivery.Delivery _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base delivery.Delivery, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Delivery: base, - _instance: instance, + Delivery: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -42,8 +54,19 @@ func TelemetryMiddleware(base delivery.Delivery, instance string, spanDecorator // Aggregate implements delivery.Delivery func (_d telemetryMiddleware) Aggregate(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregatePublishedOptions) (result map[string]interface{}, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Delivery"), + attribute.String("method", "Aggregate"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Delivery.Aggregate") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -55,6 +78,8 @@ func (_d telemetryMiddleware) Aggregate(ctx context.Context, spaceId string, env "result": result, "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())) @@ -67,8 +92,19 @@ func (_d telemetryMiddleware) Aggregate(ctx context.Context, spaceId string, env // FindItems implements delivery.Delivery func (_d telemetryMiddleware) FindItems(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindPublishedOptions) (items []*items.Item, total int, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Delivery"), + attribute.String("method", "FindItems"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Delivery.FindItems") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -81,6 +117,8 @@ func (_d telemetryMiddleware) FindItems(ctx context.Context, spaceId string, env "total": total, "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())) @@ -93,8 +131,19 @@ func (_d telemetryMiddleware) FindItems(ctx context.Context, spaceId string, env // GetCollection implements delivery.Delivery func (_d telemetryMiddleware) GetCollection(ctx context.Context, spaceId string, envId string, collectionId string) (collection *collections.Collection, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Delivery"), + attribute.String("method", "GetCollection"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Delivery.GetCollection") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -104,6 +153,8 @@ func (_d telemetryMiddleware) GetCollection(ctx context.Context, spaceId string, "collection": collection, "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())) @@ -116,8 +167,19 @@ func (_d telemetryMiddleware) GetCollection(ctx context.Context, spaceId string, // GetEnvironment implements delivery.Delivery func (_d telemetryMiddleware) GetEnvironment(ctx context.Context, spaceId string, envId string) (env *environments.Environment, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Delivery"), + attribute.String("method", "GetEnvironment"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Delivery.GetEnvironment") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -126,6 +188,8 @@ func (_d telemetryMiddleware) GetEnvironment(ctx context.Context, spaceId string "env": env, "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())) @@ -138,8 +202,19 @@ func (_d telemetryMiddleware) GetEnvironment(ctx context.Context, spaceId string // GetItem implements delivery.Delivery func (_d telemetryMiddleware) GetItem(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetPublishedOptions) (item *items.Item, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Delivery"), + attribute.String("method", "GetItem"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Delivery.GetItem") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -151,6 +226,8 @@ func (_d telemetryMiddleware) GetItem(ctx context.Context, spaceId string, envId "item": item, "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())) @@ -163,8 +240,19 @@ func (_d telemetryMiddleware) GetItem(ctx context.Context, spaceId string, envId // ListCollections implements delivery.Delivery func (_d telemetryMiddleware) ListCollections(ctx context.Context, spaceId string, envId string) (collections []*collections.Collection, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Delivery"), + attribute.String("method", "ListCollections"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Delivery.ListCollections") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -173,6 +261,8 @@ func (_d telemetryMiddleware) ListCollections(ctx context.Context, spaceId strin "collections": collections, "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())) @@ -185,8 +275,19 @@ func (_d telemetryMiddleware) ListCollections(ctx context.Context, spaceId strin // ListEnvironments implements delivery.Delivery func (_d telemetryMiddleware) ListEnvironments(ctx context.Context, spaceId string) (envs []*environments.Environment, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Delivery"), + attribute.String("method", "ListEnvironments"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Delivery.ListEnvironments") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -194,6 +295,8 @@ func (_d telemetryMiddleware) ListEnvironments(ctx context.Context, spaceId stri "envs": envs, "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())) @@ -206,8 +309,19 @@ func (_d telemetryMiddleware) ListEnvironments(ctx context.Context, spaceId stri // ListLocales implements delivery.Delivery func (_d telemetryMiddleware) ListLocales(ctx context.Context, spaceId string) (locales []*locales.Locale, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Delivery"), + attribute.String("method", "ListLocales"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Delivery.ListLocales") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -215,6 +329,8 @@ func (_d telemetryMiddleware) ListLocales(ctx context.Context, spaceId string) ( "locales": locales, "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())) diff --git a/pkg/environments/middleware/telemetry_middleware.go b/pkg/environments/middleware/telemetry_middleware.go index 3e27536fb5458dc05dd2f81bbd3ff85830f09c03..95b50dbc590f134386747a2fb4810455e7f2a800 100644 --- a/pkg/environments/middleware/telemetry_middleware.go +++ b/pkg/environments/middleware/telemetry_middleware.go @@ -1,17 +1,22 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/environments -i Environments -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/environments -i Environments -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/environments" + "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" ) @@ -19,14 +24,21 @@ import ( type telemetryMiddleware struct { environments.Environments _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base environments.Environments, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Environments: base, - _instance: instance, + Environments: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -38,8 +50,19 @@ func TelemetryMiddleware(base environments.Environments, instance string, spanDe // Create implements environments.Environments func (_d telemetryMiddleware) Create(ctx context.Context, env *environments.Environment) (created *environments.Environment, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Environments"), + attribute.String("method", "Create"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Environments.Create") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -47,6 +70,8 @@ func (_d telemetryMiddleware) Create(ctx context.Context, env *environments.Envi "created": created, "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())) @@ -59,8 +84,19 @@ func (_d telemetryMiddleware) Create(ctx context.Context, env *environments.Envi // Delete implements environments.Environments func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, envId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Environments"), + attribute.String("method", "Delete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Environments.Delete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -68,6 +104,8 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, envId "envId": envId}, 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())) @@ -80,8 +118,19 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, envId // Get implements environments.Environments func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId string) (env *environments.Environment, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Environments"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Environments.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -90,6 +139,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId str "env": env, "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())) @@ -102,8 +153,19 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId str // List implements environments.Environments func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (envs []*environments.Environment, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Environments"), + attribute.String("method", "List"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Environments.List") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -111,6 +173,8 @@ func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (envs [] "envs": envs, "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())) @@ -123,8 +187,19 @@ func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (envs [] // Migrate implements environments.Environments func (_d telemetryMiddleware) Migrate(ctx context.Context, spaceId string, envId string, options ...*environments.MigrateOptions) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Environments"), + attribute.String("method", "Migrate"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Environments.Migrate") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -133,6 +208,8 @@ func (_d telemetryMiddleware) Migrate(ctx context.Context, spaceId string, envId "options": options}, 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())) @@ -145,8 +222,19 @@ func (_d telemetryMiddleware) Migrate(ctx context.Context, spaceId string, envId // RemoveAlias implements environments.Environments func (_d telemetryMiddleware) RemoveAlias(ctx context.Context, spaceId string, envId string, alias string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Environments"), + attribute.String("method", "RemoveAlias"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Environments.RemoveAlias") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -155,6 +243,8 @@ func (_d telemetryMiddleware) RemoveAlias(ctx context.Context, spaceId string, e "alias": alias}, 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())) @@ -167,8 +257,19 @@ func (_d telemetryMiddleware) RemoveAlias(ctx context.Context, spaceId string, e // SetAlias implements environments.Environments func (_d telemetryMiddleware) SetAlias(ctx context.Context, spaceId string, envId string, alias string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Environments"), + attribute.String("method", "SetAlias"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Environments.SetAlias") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -177,6 +278,8 @@ func (_d telemetryMiddleware) SetAlias(ctx context.Context, spaceId string, envI "alias": alias}, 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())) @@ -189,14 +292,27 @@ func (_d telemetryMiddleware) SetAlias(ctx context.Context, spaceId string, envI // Update implements environments.Environments func (_d telemetryMiddleware) Update(ctx context.Context, env *environments.Environment) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Environments"), + attribute.String("method", "Update"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Environments.Update") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "env": env}, 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())) diff --git a/pkg/files/middleware/telemetry_middleware.go b/pkg/files/middleware/telemetry_middleware.go index 21e10e8df709561cc9234df1a2621754c29ebe49..bed97ea15eba2acd026249d698195835ee6a9db1 100644 --- a/pkg/files/middleware/telemetry_middleware.go +++ b/pkg/files/middleware/telemetry_middleware.go @@ -1,17 +1,22 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/files -i Files -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/files -i Files -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/files" + "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" ) @@ -19,14 +24,21 @@ import ( type telemetryMiddleware struct { files.Files _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base files.Files, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Files: base, - _instance: instance, + Files: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -38,14 +50,27 @@ func TelemetryMiddleware(base files.Files, instance string, spanDecorator ...fun // AbortUpload implements files.Files func (_d telemetryMiddleware) AbortUpload(ctx context.Context, upload *files.MultipartUpload) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Files"), + attribute.String("method", "AbortUpload"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Files.AbortUpload") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "upload": upload}, 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())) @@ -58,8 +83,19 @@ func (_d telemetryMiddleware) AbortUpload(ctx context.Context, upload *files.Mul // CompleteUpload implements files.Files func (_d telemetryMiddleware) CompleteUpload(ctx context.Context, upload *files.MultipartUpload) (u *files.MultipartUpload, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Files"), + attribute.String("method", "CompleteUpload"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Files.CompleteUpload") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -67,6 +103,8 @@ func (_d telemetryMiddleware) CompleteUpload(ctx context.Context, upload *files. "u": u, "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())) @@ -79,14 +117,27 @@ func (_d telemetryMiddleware) CompleteUpload(ctx context.Context, upload *files. // DeleteFile implements files.Files func (_d telemetryMiddleware) DeleteFile(ctx context.Context, file *files.File) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Files"), + attribute.String("method", "DeleteFile"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Files.DeleteFile") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "file": file}, 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())) @@ -99,8 +150,19 @@ func (_d telemetryMiddleware) DeleteFile(ctx context.Context, file *files.File) // GetFile implements files.Files func (_d telemetryMiddleware) GetFile(ctx context.Context, file *files.File) (f *files.File, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Files"), + attribute.String("method", "GetFile"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Files.GetFile") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -108,6 +170,8 @@ func (_d telemetryMiddleware) GetFile(ctx context.Context, file *files.File) (f "f": f, "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())) @@ -120,8 +184,19 @@ func (_d telemetryMiddleware) GetFile(ctx context.Context, file *files.File) (f // MoveUpload implements files.Files func (_d telemetryMiddleware) MoveUpload(ctx context.Context, upload *files.MultipartUpload) (file *files.File, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Files"), + attribute.String("method", "MoveUpload"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Files.MoveUpload") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -129,6 +204,8 @@ func (_d telemetryMiddleware) MoveUpload(ctx context.Context, upload *files.Mult "file": file, "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())) @@ -141,8 +218,19 @@ func (_d telemetryMiddleware) MoveUpload(ctx context.Context, upload *files.Mult // StartUpload implements files.Files func (_d telemetryMiddleware) StartUpload(ctx context.Context, upload *files.MultipartUpload) (u *files.MultipartUpload, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Files"), + attribute.String("method", "StartUpload"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Files.StartUpload") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -150,6 +238,8 @@ func (_d telemetryMiddleware) StartUpload(ctx context.Context, upload *files.Mul "u": u, "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())) @@ -162,8 +252,19 @@ func (_d telemetryMiddleware) StartUpload(ctx context.Context, upload *files.Mul // Upload implements files.Files func (_d telemetryMiddleware) Upload(ctx context.Context, file *files.File) (u *files.Upload, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Files"), + attribute.String("method", "Upload"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Files.Upload") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -171,6 +272,8 @@ func (_d telemetryMiddleware) Upload(ctx context.Context, file *files.File) (u * "u": u, "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())) diff --git a/pkg/invitations/middleware/telemetry_middleware.go b/pkg/invitations/middleware/telemetry_middleware.go index cf79342a3ee7ef978c18b1d785ec40e4d47523bc..44b7d2683137884f330946cce8d39a0eb3617d15 100644 --- a/pkg/invitations/middleware/telemetry_middleware.go +++ b/pkg/invitations/middleware/telemetry_middleware.go @@ -1,18 +1,23 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/invitations -i Invitations -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/invitations -i Invitations -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/invitations" "git.perx.ru/perxis/perxis-go/pkg/options" + "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" ) @@ -20,14 +25,21 @@ import ( type telemetryMiddleware struct { invitations.Invitations _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base invitations.Invitations, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Invitations: base, - _instance: instance, + Invitations: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -39,8 +51,19 @@ func TelemetryMiddleware(base invitations.Invitations, instance string, spanDeco // Accept implements invitations.Invitations func (_d telemetryMiddleware) Accept(ctx context.Context, invitationId string, userId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Invitations"), + attribute.String("method", "Accept"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Invitations.Accept") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -48,6 +71,8 @@ func (_d telemetryMiddleware) Accept(ctx context.Context, invitationId string, u "userId": userId}, 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())) @@ -60,8 +85,19 @@ func (_d telemetryMiddleware) Accept(ctx context.Context, invitationId string, u // Create implements invitations.Invitations func (_d telemetryMiddleware) Create(ctx context.Context, invitation *invitations.Invitation) (created *invitations.Invitation, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Invitations"), + attribute.String("method", "Create"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Invitations.Create") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -69,6 +105,8 @@ func (_d telemetryMiddleware) Create(ctx context.Context, invitation *invitation "created": created, "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())) @@ -81,14 +119,27 @@ func (_d telemetryMiddleware) Create(ctx context.Context, invitation *invitation // Delete implements invitations.Invitations func (_d telemetryMiddleware) Delete(ctx context.Context, invitationId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Invitations"), + attribute.String("method", "Delete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Invitations.Delete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "invitationId": invitationId}, 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())) @@ -101,8 +152,19 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, invitationId string) ( // Find implements invitations.Invitations func (_d telemetryMiddleware) Find(ctx context.Context, filter *invitations.Filter, opts *options.FindOptions) (invitations []*invitations.Invitation, total int, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Invitations"), + attribute.String("method", "Find"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Invitations.Find") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -112,6 +174,8 @@ func (_d telemetryMiddleware) Find(ctx context.Context, filter *invitations.Filt "total": total, "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())) @@ -124,8 +188,19 @@ func (_d telemetryMiddleware) Find(ctx context.Context, filter *invitations.Filt // Get implements invitations.Invitations func (_d telemetryMiddleware) Get(ctx context.Context, invitationId string) (invitation *invitations.Invitation, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Invitations"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Invitations.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -133,6 +208,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, invitationId string) (inv "invitation": invitation, "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())) diff --git a/pkg/items/middleware/telemetry_middleware.go b/pkg/items/middleware/telemetry_middleware.go index efbbc479d3b4ac1484d169376497aa20a1f034cc..98891f9f4f957ffe12626150c58e8bb7df67389a 100644 --- a/pkg/items/middleware/telemetry_middleware.go +++ b/pkg/items/middleware/telemetry_middleware.go @@ -1,18 +1,23 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/items -i Items -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/items -i Items -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/items" "git.perx.ru/perxis/perxis-go/pkg/schema" + "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" ) @@ -20,14 +25,21 @@ import ( type telemetryMiddleware struct { items.Items _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base items.Items, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Items: base, - _instance: instance, + Items: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -39,8 +51,19 @@ func TelemetryMiddleware(base items.Items, instance string, spanDecorator ...fun // Aggregate implements items.Items func (_d telemetryMiddleware) Aggregate(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregateOptions) (result map[string]interface{}, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Aggregate"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Aggregate") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -52,6 +75,8 @@ func (_d telemetryMiddleware) Aggregate(ctx context.Context, spaceId string, env "result": result, "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())) @@ -64,8 +89,19 @@ func (_d telemetryMiddleware) Aggregate(ctx context.Context, spaceId string, env // AggregatePublished implements items.Items func (_d telemetryMiddleware) AggregatePublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregatePublishedOptions) (result map[string]interface{}, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "AggregatePublished"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.AggregatePublished") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -77,6 +113,8 @@ func (_d telemetryMiddleware) AggregatePublished(ctx context.Context, spaceId st "result": result, "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())) @@ -89,8 +127,19 @@ func (_d telemetryMiddleware) AggregatePublished(ctx context.Context, spaceId st // Archive implements items.Items func (_d telemetryMiddleware) Archive(ctx context.Context, item *items.Item, options ...*items.ArchiveOptions) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Archive"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Archive") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -98,6 +147,8 @@ func (_d telemetryMiddleware) Archive(ctx context.Context, item *items.Item, opt "options": options}, 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())) @@ -110,8 +161,19 @@ func (_d telemetryMiddleware) Archive(ctx context.Context, item *items.Item, opt // Create implements items.Items func (_d telemetryMiddleware) Create(ctx context.Context, item *items.Item, opts ...*items.CreateOptions) (created *items.Item, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Create"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Create") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -120,6 +182,8 @@ func (_d telemetryMiddleware) Create(ctx context.Context, item *items.Item, opts "created": created, "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())) @@ -132,8 +196,19 @@ func (_d telemetryMiddleware) Create(ctx context.Context, item *items.Item, opts // Delete implements items.Items func (_d telemetryMiddleware) Delete(ctx context.Context, item *items.Item, options ...*items.DeleteOptions) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Delete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Delete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -141,6 +216,8 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, item *items.Item, opti "options": options}, 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())) @@ -153,8 +230,19 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, item *items.Item, opti // Find implements items.Items func (_d telemetryMiddleware) Find(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindOptions) (items []*items.Item, total int, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Find"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Find") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -167,6 +255,8 @@ func (_d telemetryMiddleware) Find(ctx context.Context, spaceId string, envId st "total": total, "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())) @@ -179,8 +269,19 @@ func (_d telemetryMiddleware) Find(ctx context.Context, spaceId string, envId st // FindArchived implements items.Items func (_d telemetryMiddleware) FindArchived(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindArchivedOptions) (items []*items.Item, total int, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "FindArchived"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.FindArchived") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -193,6 +294,8 @@ func (_d telemetryMiddleware) FindArchived(ctx context.Context, spaceId string, "total": total, "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())) @@ -205,8 +308,19 @@ func (_d telemetryMiddleware) FindArchived(ctx context.Context, spaceId string, // FindPublished implements items.Items func (_d telemetryMiddleware) FindPublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindPublishedOptions) (items []*items.Item, total int, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "FindPublished"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.FindPublished") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -219,6 +333,8 @@ func (_d telemetryMiddleware) FindPublished(ctx context.Context, spaceId string, "total": total, "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())) @@ -231,8 +347,19 @@ func (_d telemetryMiddleware) FindPublished(ctx context.Context, spaceId string, // Get implements items.Items func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetOptions) (item *items.Item, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -244,6 +371,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId str "item": item, "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())) @@ -256,8 +385,19 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId str // GetPublished implements items.Items func (_d telemetryMiddleware) GetPublished(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetPublishedOptions) (item *items.Item, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "GetPublished"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.GetPublished") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -269,6 +409,8 @@ func (_d telemetryMiddleware) GetPublished(ctx context.Context, spaceId string, "item": item, "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())) @@ -281,8 +423,19 @@ func (_d telemetryMiddleware) GetPublished(ctx context.Context, spaceId string, // GetRevision implements items.Items func (_d telemetryMiddleware) GetRevision(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, revisionId string, options ...*items.GetRevisionOptions) (item *items.Item, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "GetRevision"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.GetRevision") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -295,6 +448,8 @@ func (_d telemetryMiddleware) GetRevision(ctx context.Context, spaceId string, e "item": item, "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())) @@ -307,8 +462,19 @@ func (_d telemetryMiddleware) GetRevision(ctx context.Context, spaceId string, e // Introspect implements items.Items func (_d telemetryMiddleware) Introspect(ctx context.Context, item *items.Item, opts ...*items.IntrospectOptions) (itm *items.Item, sch *schema.Schema, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Introspect"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Introspect") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -318,6 +484,8 @@ func (_d telemetryMiddleware) Introspect(ctx context.Context, item *items.Item, "sch": sch, "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())) @@ -330,8 +498,19 @@ func (_d telemetryMiddleware) Introspect(ctx context.Context, item *items.Item, // ListRevisions implements items.Items func (_d telemetryMiddleware) ListRevisions(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.ListRevisionsOptions) (items []*items.Item, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "ListRevisions"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.ListRevisions") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -343,6 +522,8 @@ func (_d telemetryMiddleware) ListRevisions(ctx context.Context, spaceId string, "items": items, "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())) @@ -355,8 +536,19 @@ func (_d telemetryMiddleware) ListRevisions(ctx context.Context, spaceId string, // Publish implements items.Items func (_d telemetryMiddleware) Publish(ctx context.Context, item *items.Item, options ...*items.PublishOptions) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Publish"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Publish") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -364,6 +556,8 @@ func (_d telemetryMiddleware) Publish(ctx context.Context, item *items.Item, opt "options": options}, 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())) @@ -376,8 +570,19 @@ func (_d telemetryMiddleware) Publish(ctx context.Context, item *items.Item, opt // Unarchive implements items.Items func (_d telemetryMiddleware) Unarchive(ctx context.Context, item *items.Item, options ...*items.UnarchiveOptions) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Unarchive"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Unarchive") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -385,6 +590,8 @@ func (_d telemetryMiddleware) Unarchive(ctx context.Context, item *items.Item, o "options": options}, 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())) @@ -397,8 +604,19 @@ func (_d telemetryMiddleware) Unarchive(ctx context.Context, item *items.Item, o // Undelete implements items.Items func (_d telemetryMiddleware) Undelete(ctx context.Context, item *items.Item, options ...*items.UndeleteOptions) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Undelete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Undelete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -406,6 +624,8 @@ func (_d telemetryMiddleware) Undelete(ctx context.Context, item *items.Item, op "options": options}, 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())) @@ -418,8 +638,19 @@ func (_d telemetryMiddleware) Undelete(ctx context.Context, item *items.Item, op // Unpublish implements items.Items func (_d telemetryMiddleware) Unpublish(ctx context.Context, item *items.Item, options ...*items.UnpublishOptions) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Unpublish"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Unpublish") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -427,6 +658,8 @@ func (_d telemetryMiddleware) Unpublish(ctx context.Context, item *items.Item, o "options": options}, 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())) @@ -439,8 +672,19 @@ func (_d telemetryMiddleware) Unpublish(ctx context.Context, item *items.Item, o // Update implements items.Items func (_d telemetryMiddleware) Update(ctx context.Context, item *items.Item, options ...*items.UpdateOptions) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Items"), + attribute.String("method", "Update"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Items.Update") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -448,6 +692,8 @@ func (_d telemetryMiddleware) Update(ctx context.Context, item *items.Item, opti "options": options}, 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())) diff --git a/pkg/locales/middleware/telemetry_middleware.go b/pkg/locales/middleware/telemetry_middleware.go index 3e335e19574e238a02a69dc19f373c62e7fc65a2..4efc5293b78781aaa5d8cbf77f4da82c714a6137 100644 --- a/pkg/locales/middleware/telemetry_middleware.go +++ b/pkg/locales/middleware/telemetry_middleware.go @@ -1,17 +1,22 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/locales -i Locales -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/locales -i Locales -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/locales" + "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" ) @@ -19,14 +24,21 @@ import ( type telemetryMiddleware struct { locales.Locales _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base locales.Locales, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Locales: base, - _instance: instance, + Locales: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -38,8 +50,19 @@ func TelemetryMiddleware(base locales.Locales, instance string, spanDecorator .. // Create implements locales.Locales func (_d telemetryMiddleware) Create(ctx context.Context, locale *locales.Locale) (created *locales.Locale, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Locales"), + attribute.String("method", "Create"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Locales.Create") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -47,6 +70,8 @@ func (_d telemetryMiddleware) Create(ctx context.Context, locale *locales.Locale "created": created, "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())) @@ -59,8 +84,19 @@ func (_d telemetryMiddleware) Create(ctx context.Context, locale *locales.Locale // Delete implements locales.Locales func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, localeId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Locales"), + attribute.String("method", "Delete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Locales.Delete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -68,6 +104,8 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, locale "localeId": localeId}, 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())) @@ -80,8 +118,19 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, locale // List implements locales.Locales func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (locales []*locales.Locale, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Locales"), + attribute.String("method", "List"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Locales.List") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -89,6 +138,8 @@ func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (locales "locales": locales, "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())) diff --git a/pkg/members/middleware/telemetry_middleware.go b/pkg/members/middleware/telemetry_middleware.go index 4d13a5d794a57fd9c470bae42bbfed4fe81743cc..6193a4bacb41dcea61a1384e939bcdb2785f5e8a 100644 --- a/pkg/members/middleware/telemetry_middleware.go +++ b/pkg/members/middleware/telemetry_middleware.go @@ -1,17 +1,22 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/members -i Members -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/members -i Members -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/members" + "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" ) @@ -19,14 +24,21 @@ import ( type telemetryMiddleware struct { members.Members _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base members.Members, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Members: base, - _instance: instance, + Members: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -38,8 +50,19 @@ func TelemetryMiddleware(base members.Members, instance string, spanDecorator .. // Get implements members.Members func (_d telemetryMiddleware) Get(ctx context.Context, orgId string, userId string) (role members.Role, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Members"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Members.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -48,6 +71,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, orgId string, userId stri "role": role, "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())) @@ -60,8 +85,19 @@ func (_d telemetryMiddleware) Get(ctx context.Context, orgId string, userId stri // ListMembers implements members.Members func (_d telemetryMiddleware) ListMembers(ctx context.Context, orgId string) (members []*members.Member, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Members"), + attribute.String("method", "ListMembers"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Members.ListMembers") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -69,6 +105,8 @@ func (_d telemetryMiddleware) ListMembers(ctx context.Context, orgId string) (me "members": members, "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())) @@ -81,8 +119,19 @@ func (_d telemetryMiddleware) ListMembers(ctx context.Context, orgId string) (me // ListOrganizations implements members.Members func (_d telemetryMiddleware) ListOrganizations(ctx context.Context, userId string) (organizations []*members.Member, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Members"), + attribute.String("method", "ListOrganizations"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Members.ListOrganizations") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -90,6 +139,8 @@ func (_d telemetryMiddleware) ListOrganizations(ctx context.Context, userId stri "organizations": organizations, "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())) @@ -102,8 +153,19 @@ func (_d telemetryMiddleware) ListOrganizations(ctx context.Context, userId stri // Remove implements members.Members func (_d telemetryMiddleware) Remove(ctx context.Context, orgId string, userId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Members"), + attribute.String("method", "Remove"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Members.Remove") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -111,6 +173,8 @@ func (_d telemetryMiddleware) Remove(ctx context.Context, orgId string, userId s "userId": userId}, 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())) @@ -123,14 +187,27 @@ func (_d telemetryMiddleware) Remove(ctx context.Context, orgId string, userId s // RemoveAll implements members.Members func (_d telemetryMiddleware) RemoveAll(ctx context.Context, orgId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Members"), + attribute.String("method", "RemoveAll"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Members.RemoveAll") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "orgId": orgId}, 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())) @@ -143,8 +220,19 @@ func (_d telemetryMiddleware) RemoveAll(ctx context.Context, orgId string) (err // Set implements members.Members func (_d telemetryMiddleware) Set(ctx context.Context, orgId string, userId string, role members.Role) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Members"), + attribute.String("method", "Set"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Members.Set") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -153,6 +241,8 @@ func (_d telemetryMiddleware) Set(ctx context.Context, orgId string, userId stri "role": role}, 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())) diff --git a/pkg/optional/optional.go b/pkg/optional/optional.go index 94e89bf6a04708abf853f2e8aaf8d7dbd9e99371..b33d76b98a94b20ca357d6e42d2658ac389ee883 100644 --- a/pkg/optional/optional.go +++ b/pkg/optional/optional.go @@ -8,3 +8,7 @@ var ( func Bool(v bool) *bool { return &v } + +func Ptr[T any](v T) *T { + return &v +} diff --git a/pkg/organizations/middleware/telemetry_middleware.go b/pkg/organizations/middleware/telemetry_middleware.go index 6589ed10ba1ee502c6620f8cbef20ed6da22bb29..d728b1f10f4ba303b6469d3a1b8bf63cb24a7283 100644 --- a/pkg/organizations/middleware/telemetry_middleware.go +++ b/pkg/organizations/middleware/telemetry_middleware.go @@ -1,18 +1,23 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/organizations -i Organizations -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/organizations -i Organizations -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/options" "git.perx.ru/perxis/perxis-go/pkg/organizations" + "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" ) @@ -20,14 +25,21 @@ import ( type telemetryMiddleware struct { organizations.Organizations _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base organizations.Organizations, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Organizations: base, - _instance: instance, + Organizations: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -39,8 +51,19 @@ func TelemetryMiddleware(base organizations.Organizations, instance string, span // Create implements organizations.Organizations func (_d telemetryMiddleware) Create(ctx context.Context, org *organizations.Organization) (created *organizations.Organization, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Organizations"), + attribute.String("method", "Create"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Organizations.Create") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -48,6 +71,8 @@ func (_d telemetryMiddleware) Create(ctx context.Context, org *organizations.Org "created": created, "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())) @@ -60,14 +85,27 @@ func (_d telemetryMiddleware) Create(ctx context.Context, org *organizations.Org // Delete implements organizations.Organizations func (_d telemetryMiddleware) Delete(ctx context.Context, orgId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Organizations"), + attribute.String("method", "Delete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Organizations.Delete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "orgId": orgId}, 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())) @@ -80,8 +118,19 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, orgId string) (err err // Find implements organizations.Organizations func (_d telemetryMiddleware) Find(ctx context.Context, filter *organizations.Filter, opts *options.FindOptions) (orgs []*organizations.Organization, total int, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Organizations"), + attribute.String("method", "Find"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Organizations.Find") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -91,6 +140,8 @@ func (_d telemetryMiddleware) Find(ctx context.Context, filter *organizations.Fi "total": total, "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())) @@ -103,8 +154,19 @@ func (_d telemetryMiddleware) Find(ctx context.Context, filter *organizations.Fi // Get implements organizations.Organizations func (_d telemetryMiddleware) Get(ctx context.Context, orgId string) (org *organizations.Organization, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Organizations"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Organizations.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -112,6 +174,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, orgId string) (org *organ "org": org, "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())) @@ -124,14 +188,27 @@ func (_d telemetryMiddleware) Get(ctx context.Context, orgId string) (org *organ // Update implements organizations.Organizations func (_d telemetryMiddleware) Update(ctx context.Context, org *organizations.Organization) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Organizations"), + attribute.String("method", "Update"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Organizations.Update") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "org": org}, 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())) diff --git a/pkg/references/middleware/telemetry_middleware.go b/pkg/references/middleware/telemetry_middleware.go index 16fe5d30d2e5cc8dc82adfc7d7a3db87acf45636..f188bdc7ee04c13690ac0712e511508ccb2b12bc 100644 --- a/pkg/references/middleware/telemetry_middleware.go +++ b/pkg/references/middleware/telemetry_middleware.go @@ -1,18 +1,23 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/references -i References -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/references -i References -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/items" "git.perx.ru/perxis/perxis-go/pkg/references" + "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" ) @@ -20,14 +25,21 @@ import ( type telemetryMiddleware struct { references.References _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base references.References, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - References: base, - _instance: instance, + References: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -39,8 +51,19 @@ func TelemetryMiddleware(base references.References, instance string, spanDecora // Get implements references.References func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId string, references []*references.Reference) (items []*items.Item, notfound []*references.Reference, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "References"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "References.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -51,6 +74,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId str "notfound": notfound, "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())) @@ -63,8 +88,19 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, envId str // Publish implements references.References func (_d telemetryMiddleware) Publish(ctx context.Context, spaceId string, envId string, references []*references.Reference, recursive bool, force bool) (published []*references.Reference, notfound []*references.Reference, unpublished []*references.Reference, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "References"), + attribute.String("method", "Publish"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "References.Publish") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -78,6 +114,8 @@ func (_d telemetryMiddleware) Publish(ctx context.Context, spaceId string, envId "unpublished": unpublished, "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())) diff --git a/pkg/roles/middleware/telemetry_middleware.go b/pkg/roles/middleware/telemetry_middleware.go index fe487489348a421c611c16b24c8fe689908dcaa8..5d9d5e35cee66af5e24fb5888d52907ce35aadde 100644 --- a/pkg/roles/middleware/telemetry_middleware.go +++ b/pkg/roles/middleware/telemetry_middleware.go @@ -1,17 +1,22 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/roles -i Roles -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/roles -i Roles -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/roles" + "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" ) @@ -19,14 +24,21 @@ import ( type telemetryMiddleware struct { roles.Roles _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base roles.Roles, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Roles: base, - _instance: instance, + Roles: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -38,8 +50,19 @@ func TelemetryMiddleware(base roles.Roles, instance string, spanDecorator ...fun // Create implements roles.Roles func (_d telemetryMiddleware) Create(ctx context.Context, role *roles.Role) (created *roles.Role, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Roles"), + attribute.String("method", "Create"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Roles.Create") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -47,6 +70,8 @@ func (_d telemetryMiddleware) Create(ctx context.Context, role *roles.Role) (cre "created": created, "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())) @@ -59,8 +84,19 @@ func (_d telemetryMiddleware) Create(ctx context.Context, role *roles.Role) (cre // Delete implements roles.Roles func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, roleId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Roles"), + attribute.String("method", "Delete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Roles.Delete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -68,6 +104,8 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, roleId "roleId": roleId}, 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())) @@ -80,8 +118,19 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string, roleId // Get implements roles.Roles func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, roleId string) (role *roles.Role, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Roles"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Roles.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -90,6 +139,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, roleId st "role": role, "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())) @@ -102,8 +153,19 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string, roleId st // List implements roles.Roles func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (roles []*roles.Role, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Roles"), + attribute.String("method", "List"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Roles.List") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -111,6 +173,8 @@ func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (roles [ "roles": roles, "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())) @@ -123,14 +187,27 @@ func (_d telemetryMiddleware) List(ctx context.Context, spaceId string) (roles [ // Update implements roles.Roles func (_d telemetryMiddleware) Update(ctx context.Context, role *roles.Role) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Roles"), + attribute.String("method", "Update"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Roles.Update") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "role": role}, 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())) diff --git a/pkg/spaces/middleware/telemetry_middleware.go b/pkg/spaces/middleware/telemetry_middleware.go index ba64829909edddc0ed5fbf100265552f611ae584..90597815e8e7aa0a3a364c3e29aa208f3473d690 100644 --- a/pkg/spaces/middleware/telemetry_middleware.go +++ b/pkg/spaces/middleware/telemetry_middleware.go @@ -1,17 +1,22 @@ -package middleware - // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// template: ..\..\..\assets\templates\middleware\telemetry // gowrap: http://github.com/hexdigest/gowrap -//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/spaces -i Spaces -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +package middleware + +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/spaces -i Spaces -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/spaces" + "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" ) @@ -19,14 +24,21 @@ import ( type telemetryMiddleware struct { spaces.Spaces _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base spaces.Spaces, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Spaces: base, - _instance: instance, + Spaces: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -38,14 +50,27 @@ func TelemetryMiddleware(base spaces.Spaces, instance string, spanDecorator ...f // AbortTransfer implements spaces.Spaces func (_d telemetryMiddleware) AbortTransfer(ctx context.Context, spaceID string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Spaces"), + attribute.String("method", "AbortTransfer"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Spaces.AbortTransfer") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "spaceID": spaceID}, 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())) @@ -58,8 +83,19 @@ func (_d telemetryMiddleware) AbortTransfer(ctx context.Context, spaceID string) // Create implements spaces.Spaces func (_d telemetryMiddleware) Create(ctx context.Context, space *spaces.Space) (created *spaces.Space, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Spaces"), + attribute.String("method", "Create"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Spaces.Create") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -67,6 +103,8 @@ func (_d telemetryMiddleware) Create(ctx context.Context, space *spaces.Space) ( "created": created, "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())) @@ -79,14 +117,27 @@ func (_d telemetryMiddleware) Create(ctx context.Context, space *spaces.Space) ( // Delete implements spaces.Spaces func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Spaces"), + attribute.String("method", "Delete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Spaces.Delete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "spaceId": spaceId}, 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())) @@ -99,8 +150,19 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, spaceId string) (err e // Get implements spaces.Spaces func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string) (space *spaces.Space, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Spaces"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Spaces.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -108,6 +170,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string) (space *s "space": space, "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())) @@ -120,8 +184,19 @@ func (_d telemetryMiddleware) Get(ctx context.Context, spaceId string) (space *s // List implements spaces.Spaces func (_d telemetryMiddleware) List(ctx context.Context, orgId string) (spaces []*spaces.Space, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Spaces"), + attribute.String("method", "List"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Spaces.List") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -129,6 +204,8 @@ func (_d telemetryMiddleware) List(ctx context.Context, orgId string) (spaces [] "spaces": spaces, "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())) @@ -141,8 +218,19 @@ func (_d telemetryMiddleware) List(ctx context.Context, orgId string) (spaces [] // ListTransfers implements spaces.Spaces func (_d telemetryMiddleware) ListTransfers(ctx context.Context, orgID string) (spaces []*spaces.Space, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Spaces"), + attribute.String("method", "ListTransfers"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Spaces.ListTransfers") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -150,6 +238,8 @@ func (_d telemetryMiddleware) ListTransfers(ctx context.Context, orgID string) ( "spaces": spaces, "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())) @@ -162,8 +252,19 @@ func (_d telemetryMiddleware) ListTransfers(ctx context.Context, orgID string) ( // Move implements spaces.Spaces func (_d telemetryMiddleware) Move(ctx context.Context, spaceID string, orgID string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Spaces"), + attribute.String("method", "Move"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Spaces.Move") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -171,6 +272,8 @@ func (_d telemetryMiddleware) Move(ctx context.Context, spaceID string, orgID st "orgID": orgID}, 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())) @@ -183,8 +286,19 @@ func (_d telemetryMiddleware) Move(ctx context.Context, spaceID string, orgID st // Transfer implements spaces.Spaces func (_d telemetryMiddleware) Transfer(ctx context.Context, spaceID string, transferToOrg string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Spaces"), + attribute.String("method", "Transfer"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Spaces.Transfer") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -192,6 +306,8 @@ func (_d telemetryMiddleware) Transfer(ctx context.Context, spaceID string, tran "transferToOrg": transferToOrg}, 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())) @@ -204,14 +320,27 @@ func (_d telemetryMiddleware) Transfer(ctx context.Context, spaceID string, tran // Update implements spaces.Spaces func (_d telemetryMiddleware) Update(ctx context.Context, space *spaces.Space) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Spaces"), + attribute.String("method", "Update"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Spaces.Update") + 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}, 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())) @@ -224,8 +353,19 @@ func (_d telemetryMiddleware) Update(ctx context.Context, space *spaces.Space) ( // UpdateConfig implements spaces.Spaces func (_d telemetryMiddleware) UpdateConfig(ctx context.Context, spaceId string, config *spaces.Config) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Spaces"), + attribute.String("method", "UpdateConfig"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Spaces.UpdateConfig") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -233,6 +373,8 @@ func (_d telemetryMiddleware) UpdateConfig(ctx context.Context, spaceId string, "config": config}, 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())) diff --git a/pkg/telemetry/metrics/cache.go b/pkg/telemetry/metrics/cache.go new file mode 100644 index 0000000000000000000000000000000000000000..323fd26b840977b71b28dfcc1575f9479ed42013 --- /dev/null +++ b/pkg/telemetry/metrics/cache.go @@ -0,0 +1,40 @@ +package metrics + +import ( + "go.opentelemetry.io/otel" + otelmetric "go.opentelemetry.io/otel/metric" +) + +type CacheMetrics struct { + HitsTotal otelmetric.Int64Counter + MissesTotal otelmetric.Int64Counter + InvalidatesTotal otelmetric.Int64Counter +} + +func GetCacheMetrics() (*CacheMetrics, error) { + var ( + meter = otel.Meter("") + cacheMetrics = new(CacheMetrics) + err error + ) + + if cacheMetrics.HitsTotal, err = meter.Int64Counter("cache_hits", + otelmetric.WithDescription("Количество найденных в кэше значений"), + ); err != nil { + return nil, err + } + + if cacheMetrics.MissesTotal, err = meter.Int64Counter("cache_misses", + otelmetric.WithDescription("Количество не найденных в кэше значений"), + ); err != nil { + return nil, err + } + + if cacheMetrics.InvalidatesTotal, err = meter.Int64Counter("cache_invalidates", + otelmetric.WithDescription("Количество инвалидаций кэша"), + ); err != nil { + return nil, err + } + + return cacheMetrics, nil +} diff --git a/pkg/telemetry/metrics/request.go b/pkg/telemetry/metrics/request.go new file mode 100644 index 0000000000000000000000000000000000000000..58da49785b9cc97083c407bcbf45ef32a82f36c4 --- /dev/null +++ b/pkg/telemetry/metrics/request.go @@ -0,0 +1,44 @@ +package metrics + +import ( + "go.opentelemetry.io/otel" + otelmetric "go.opentelemetry.io/otel/metric" +) + +type RequestMetrics struct { + Total otelmetric.Int64Counter + FailedTotal otelmetric.Int64Counter + DurationMilliseconds otelmetric.Int64Histogram +} + +// GetRequestMetrics возвращает метрики для подсчета количества удачных/неудачных запросов, а так же длительности ответов. +// +// Для RequestMetrics.DurationMilliseconds значения buckets по умолчанию равно []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000} +func GetRequestMetrics() (*RequestMetrics, error) { + var ( + meter = otel.Meter("") + requestMetrics = new(RequestMetrics) + err error + ) + + if requestMetrics.Total, err = meter.Int64Counter("requests", + otelmetric.WithDescription("Количество запросов"), + ); err != nil { + return nil, err + } + + if requestMetrics.FailedTotal, err = meter.Int64Counter("requests_failed", + otelmetric.WithDescription("Количество запросов, вернувших ошибку"), + ); err != nil { + return nil, err + } + + if requestMetrics.DurationMilliseconds, err = meter.Int64Histogram("request_duration", + otelmetric.WithDescription("Длительность обработки запроса"), + otelmetric.WithUnit("ms"), + ); err != nil { + return nil, err + } + + return requestMetrics, nil +} diff --git a/pkg/users/middleware/telemetry_middleware.go b/pkg/users/middleware/telemetry_middleware.go index a68b365d63d4c7668daf80035ca0f82d3d4bd598..698b4f6b4f2928e5f466e7855defa4c2df96ef36 100644 --- a/pkg/users/middleware/telemetry_middleware.go +++ b/pkg/users/middleware/telemetry_middleware.go @@ -1,18 +1,23 @@ // Code generated by gowrap. DO NOT EDIT. -// template: ../../../assets/templates/middleware/telemetry +// 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/users -i Users -t ../../../assets/templates/middleware/telemetry -o telemetry_middleware.go -l "" +//go:generate gowrap gen -p git.perx.ru/perxis/perxis-go/pkg/users -i Users -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/options" + "git.perx.ru/perxis/perxis-go/pkg/telemetry/metrics" "git.perx.ru/perxis/perxis-go/pkg/users" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" + otelmetric "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" ) @@ -20,14 +25,21 @@ import ( type telemetryMiddleware struct { users.Users _instance string + requestMetrics *metrics.RequestMetrics _spanDecorator func(span trace.Span, params, results map[string]interface{}) } // TelemetryMiddleware returns telemetryMiddleware func TelemetryMiddleware(base users.Users, instance string, spanDecorator ...func(span trace.Span, params, results map[string]interface{})) telemetryMiddleware { + requestMetrics, err := metrics.GetRequestMetrics() + if err != nil { + panic(err) + } + d := telemetryMiddleware{ - Users: base, - _instance: instance, + Users: base, + _instance: instance, + requestMetrics: requestMetrics, } if len(spanDecorator) > 0 && spanDecorator[0] != nil { @@ -39,8 +51,19 @@ func TelemetryMiddleware(base users.Users, instance string, spanDecorator ...fun // Create implements users.Users func (_d telemetryMiddleware) Create(ctx context.Context, create *users.User) (user *users.User, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Users"), + attribute.String("method", "Create"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Users.Create") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -48,6 +71,8 @@ func (_d telemetryMiddleware) Create(ctx context.Context, create *users.User) (u "user": user, "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())) @@ -60,14 +85,27 @@ func (_d telemetryMiddleware) Create(ctx context.Context, create *users.User) (u // Delete implements users.Users func (_d telemetryMiddleware) Delete(ctx context.Context, userId string) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Users"), + attribute.String("method", "Delete"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Users.Delete") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "userId": userId}, 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())) @@ -80,8 +118,19 @@ func (_d telemetryMiddleware) Delete(ctx context.Context, userId string) (err er // Find implements users.Users func (_d telemetryMiddleware) Find(ctx context.Context, filter *users.Filter, options *options.FindOptions) (users []*users.User, total int, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Users"), + attribute.String("method", "Find"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Users.Find") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -91,6 +140,8 @@ func (_d telemetryMiddleware) Find(ctx context.Context, filter *users.Filter, op "total": total, "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())) @@ -103,8 +154,19 @@ func (_d telemetryMiddleware) Find(ctx context.Context, filter *users.Filter, op // Get implements users.Users func (_d telemetryMiddleware) Get(ctx context.Context, userId string) (user *users.User, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Users"), + attribute.String("method", "Get"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Users.Get") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -112,6 +174,8 @@ func (_d telemetryMiddleware) Get(ctx context.Context, userId string) (user *use "user": user, "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())) @@ -124,8 +188,19 @@ func (_d telemetryMiddleware) Get(ctx context.Context, userId string) (user *use // GetByIdentity implements users.Users func (_d telemetryMiddleware) GetByIdentity(ctx context.Context, identity string) (user *users.User, err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Users"), + attribute.String("method", "GetByIdentity"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Users.GetByIdentity") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, @@ -133,6 +208,8 @@ func (_d telemetryMiddleware) GetByIdentity(ctx context.Context, identity string "user": user, "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())) @@ -145,14 +222,27 @@ func (_d telemetryMiddleware) GetByIdentity(ctx context.Context, identity string // Update implements users.Users func (_d telemetryMiddleware) Update(ctx context.Context, update *users.User) (err error) { + attributes := otelmetric.WithAttributeSet(attribute.NewSet( + attribute.String("service", "Users"), + attribute.String("method", "Update"), + )) + + _d.requestMetrics.Total.Add(ctx, 1, attributes) + + start := time.Now() ctx, _span := otel.Tracer(_d._instance).Start(ctx, "Users.Update") + defer func() { + _d.requestMetrics.DurationMilliseconds.Record(ctx, time.Since(start).Milliseconds(), attributes) + if _d._spanDecorator != nil { _d._spanDecorator(_span, map[string]interface{}{ "ctx": ctx, "update": update}, 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()))