diff --git a/assets/templates/middleware/metrics b/assets/templates/middleware/metrics index 42483bc0f834f12349a028344111675ac7722ed0..9e1406280e5f19c4535e0ca6ca9d77d4f2206ef6 100644 --- a/assets/templates/middleware/metrics +++ b/assets/templates/middleware/metrics @@ -26,11 +26,14 @@ func {{ $funcName }} (requestMetrics *metrics.RequestMetrics) Middleware { {{ range $method := .Interface.Methods }} // {{ $method.Name }} implements {{ $.Interface.Type }} func (m {{ $decorator }}) {{ $method.Declaration }} { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("{{ $.Interface.Name }}", "{{ $method.Name }}")) + m.requestMetrics.Total.WithLabelValues("{{ $method.Name }}").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("{{ $method.Name }}")) defer func() { - timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("{{ $.Interface.Name }}", "{{ $method.Name }}").Inc() - }() + timer.ObserveDuration() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("{{ $method.Name }}").Inc() + } + }() {{ $method.Pass "m.next." }} } {{ end }} \ No newline at end of file diff --git a/pkg/items/middleware/metrics_middleware.go b/pkg/items/middleware/metrics_middleware.go index 360716b94373564dbb2a508ed0f01f6c7779f969..72fb917b0ab4afc128c65adfc3a2891de685f1ad 100644 --- a/pkg/items/middleware/metrics_middleware.go +++ b/pkg/items/middleware/metrics_middleware.go @@ -33,180 +33,234 @@ func MetricsMiddleware(requestMetrics *metrics.RequestMetrics) Middleware { // Aggregate implements items.Items func (m metricsMiddleware) Aggregate(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregateOptions) (result map[string]interface{}, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Aggregate")) + m.requestMetrics.Total.WithLabelValues("Aggregate").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Aggregate")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Aggregate").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Aggregate").Inc() + } }() return m.next.Aggregate(ctx, spaceId, envId, collectionId, filter, options...) } // AggregatePublished implements items.Items func (m metricsMiddleware) AggregatePublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.AggregatePublishedOptions) (result map[string]interface{}, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "AggregatePublished")) + m.requestMetrics.Total.WithLabelValues("AggregatePublished").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("AggregatePublished")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "AggregatePublished").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("AggregatePublished").Inc() + } }() return m.next.AggregatePublished(ctx, spaceId, envId, collectionId, filter, options...) } // Archive implements items.Items func (m metricsMiddleware) Archive(ctx context.Context, item *items.Item, options ...*items.ArchiveOptions) (err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Archive")) + m.requestMetrics.Total.WithLabelValues("Archive").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Archive")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Archive").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Archive").Inc() + } }() return m.next.Archive(ctx, item, options...) } // Create implements items.Items func (m metricsMiddleware) Create(ctx context.Context, item *items.Item, opts ...*items.CreateOptions) (created *items.Item, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Create")) + m.requestMetrics.Total.WithLabelValues("Create").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Create")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Create").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Create").Inc() + } }() return m.next.Create(ctx, item, opts...) } // Delete implements items.Items func (m metricsMiddleware) Delete(ctx context.Context, item *items.Item, options ...*items.DeleteOptions) (err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Delete")) + m.requestMetrics.Total.WithLabelValues("Delete").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Delete")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Delete").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Delete").Inc() + } }() return m.next.Delete(ctx, item, options...) } // Find implements items.Items func (m metricsMiddleware) Find(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindOptions) (items []*items.Item, total int, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Find")) + m.requestMetrics.Total.WithLabelValues("Find").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Find")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Find").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Find").Inc() + } }() return m.next.Find(ctx, spaceId, envId, collectionId, filter, options...) } // FindArchived implements items.Items func (m metricsMiddleware) FindArchived(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindArchivedOptions) (items []*items.Item, total int, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "FindArchived")) + m.requestMetrics.Total.WithLabelValues("FindArchived").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("FindArchived")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "FindArchived").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("FindArchived").Inc() + } }() return m.next.FindArchived(ctx, spaceId, envId, collectionId, filter, options...) } // FindPublished implements items.Items func (m metricsMiddleware) FindPublished(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindPublishedOptions) (items []*items.Item, total int, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "FindPublished")) + m.requestMetrics.Total.WithLabelValues("FindPublished").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("FindPublished")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "FindPublished").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("FindPublished").Inc() + } }() return m.next.FindPublished(ctx, spaceId, envId, collectionId, filter, options...) } // Get implements items.Items func (m metricsMiddleware) Get(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetOptions) (item *items.Item, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Get")) + m.requestMetrics.Total.WithLabelValues("Get").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Get")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Get").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Get").Inc() + } }() return m.next.Get(ctx, spaceId, envId, collectionId, itemId, options...) } // GetPublished implements items.Items func (m metricsMiddleware) GetPublished(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetPublishedOptions) (item *items.Item, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "GetPublished")) + m.requestMetrics.Total.WithLabelValues("GetPublished").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("GetPublished")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "GetPublished").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("GetPublished").Inc() + } }() return m.next.GetPublished(ctx, spaceId, envId, collectionId, itemId, options...) } // GetRevision implements items.Items func (m metricsMiddleware) GetRevision(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, revisionId string, options ...*items.GetRevisionOptions) (item *items.Item, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "GetRevision")) + m.requestMetrics.Total.WithLabelValues("GetRevision").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("GetRevision")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "GetRevision").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("GetRevision").Inc() + } }() return m.next.GetRevision(ctx, spaceId, envId, collectionId, itemId, revisionId, options...) } // Introspect implements items.Items func (m metricsMiddleware) Introspect(ctx context.Context, item *items.Item, opts ...*items.IntrospectOptions) (itm *items.Item, sch *schema.Schema, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Introspect")) + m.requestMetrics.Total.WithLabelValues("Introspect").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Introspect")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Introspect").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Introspect").Inc() + } }() return m.next.Introspect(ctx, item, opts...) } // ListRevisions implements items.Items func (m metricsMiddleware) ListRevisions(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.ListRevisionsOptions) (items []*items.Item, err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "ListRevisions")) + m.requestMetrics.Total.WithLabelValues("ListRevisions").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("ListRevisions")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "ListRevisions").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("ListRevisions").Inc() + } }() return m.next.ListRevisions(ctx, spaceId, envId, collectionId, itemId, options...) } // Publish implements items.Items func (m metricsMiddleware) Publish(ctx context.Context, item *items.Item, options ...*items.PublishOptions) (err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Publish")) + m.requestMetrics.Total.WithLabelValues("Publish").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Publish")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Publish").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Publish").Inc() + } }() return m.next.Publish(ctx, item, options...) } // Unarchive implements items.Items func (m metricsMiddleware) Unarchive(ctx context.Context, item *items.Item, options ...*items.UnarchiveOptions) (err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Unarchive")) + m.requestMetrics.Total.WithLabelValues("Unarchive").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Unarchive")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Unarchive").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Unarchive").Inc() + } }() return m.next.Unarchive(ctx, item, options...) } // Undelete implements items.Items func (m metricsMiddleware) Undelete(ctx context.Context, item *items.Item, options ...*items.UndeleteOptions) (err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Undelete")) + m.requestMetrics.Total.WithLabelValues("Undelete").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Undelete")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Undelete").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Undelete").Inc() + } }() return m.next.Undelete(ctx, item, options...) } // Unpublish implements items.Items func (m metricsMiddleware) Unpublish(ctx context.Context, item *items.Item, options ...*items.UnpublishOptions) (err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Unpublish")) + m.requestMetrics.Total.WithLabelValues("Unpublish").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Unpublish")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Unpublish").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Unpublish").Inc() + } }() return m.next.Unpublish(ctx, item, options...) } // Update implements items.Items func (m metricsMiddleware) Update(ctx context.Context, item *items.Item, options ...*items.UpdateOptions) (err error) { - timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Items", "Update")) + m.requestMetrics.Total.WithLabelValues("Update").Inc() + timer := prometheus.NewTimer(m.requestMetrics.DurationSeconds.WithLabelValues("Update")) defer func() { timer.ObserveDuration() - m.requestMetrics.Total.WithLabelValues("Items", "Update").Inc() + if err != nil { + m.requestMetrics.FailedTotal.WithLabelValues("Update").Inc() + } }() return m.next.Update(ctx, item, options...) } diff --git a/pkg/metrics/request.go b/pkg/metrics/request.go index fbfb63fa8e4b43a435e0a0e5e2a04764ae9e2797..01837bf956aef3ad6172050f444ee67bb52d6de8 100644 --- a/pkg/metrics/request.go +++ b/pkg/metrics/request.go @@ -2,33 +2,34 @@ package metrics import ( "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" ) type RequestMetrics struct { Total *prometheus.CounterVec + FailedTotal *prometheus.CounterVec DurationSeconds *prometheus.HistogramVec } -// NewRequestMetrics -// -// # Example metrics -// -// svc_request_duration_seconds_bucket{service="Collections",method="Get",le="+Inf"} 2 -// -// svc_request_duration_seconds_sum{service="Collections",method="Get"} 0.711158607 -// -// svc_request_duration_seconds_count{service="Collections",method="Get"} 2 -// -// svc_requests_total{service="Collections",method="Get"} 2 -func NewRequestMetrics(registry prometheus.Registerer, buckets []float64) *RequestMetrics { - return &RequestMetrics{ - Total: promauto.With(registry).NewCounterVec(prometheus.CounterOpts{ - Name: "svc_requests_total", - }, []string{"service", "method"}), - DurationSeconds: promauto.With(registry).NewHistogramVec(prometheus.HistogramOpts{ - Name: "svc_request_duration_seconds", - Buckets: buckets, - }, []string{"service", "method"}), +func NewRequestMetrics(subsystem string, durationBuckets []float64, labels ...string) *RequestMetrics { + metrics := &RequestMetrics{ + Total: prometheus.NewCounterVec(prometheus.CounterOpts{ + Subsystem: subsystem, + Name: "service_requests_total", + }, []string{"method"}), + FailedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{ + Subsystem: subsystem, + Name: "service_requests_failed_total", + }, []string{"method"}), + DurationSeconds: prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Subsystem: subsystem, + Name: "service_request_duration_seconds", + Buckets: durationBuckets, + }, []string{"method"}), } + prometheus.WrapRegistererWith(GetLabelsFromKV(labels), prometheus.DefaultRegisterer).MustRegister( + metrics.Total, + metrics.FailedTotal, + metrics.DurationSeconds, + ) + return metrics }