diff --git a/services/search/pkg/metrics/metrics.go b/services/search/pkg/metrics/metrics.go index 437dc544ce..7cd600fe59 100644 --- a/services/search/pkg/metrics/metrics.go +++ b/services/search/pkg/metrics/metrics.go @@ -2,6 +2,7 @@ package metrics import ( "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" ) var ( @@ -19,41 +20,52 @@ type Metrics struct { EventsOutstandingAcks prometheus.Gauge EventsUnprocessed prometheus.Gauge EventsRedelivered prometheus.Gauge + SearchDuration *prometheus.HistogramVec + IndexDuration *prometheus.HistogramVec } // New initializes the available metrics. func New() *Metrics { m := &Metrics{ - BuildInfo: prometheus.NewGaugeVec(prometheus.GaugeOpts{ + BuildInfo: promauto.NewGaugeVec(prometheus.GaugeOpts{ Namespace: Namespace, Subsystem: Subsystem, Name: "build_info", Help: "Build information", }, []string{"version"}), - EventsOutstandingAcks: prometheus.NewGauge(prometheus.GaugeOpts{ + EventsOutstandingAcks: promauto.NewGauge(prometheus.GaugeOpts{ Namespace: Namespace, Subsystem: Subsystem, Name: "events_outstanding_acks", Help: "Number of outstanding acks for events", }), - EventsUnprocessed: prometheus.NewGauge(prometheus.GaugeOpts{ + EventsUnprocessed: promauto.NewGauge(prometheus.GaugeOpts{ Namespace: Namespace, Subsystem: Subsystem, Name: "events_unprocessed", Help: "Number of unprocessed events", }), - EventsRedelivered: prometheus.NewGauge(prometheus.GaugeOpts{ + EventsRedelivered: promauto.NewGauge(prometheus.GaugeOpts{ Namespace: Namespace, Subsystem: Subsystem, Name: "events_redelivered", Help: "Number of redelivered events", }), + SearchDuration: promauto.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: Namespace, + Subsystem: Subsystem, + Name: "search_duration_seconds", + Help: "Duration of search operations in seconds", + Buckets: []float64{0.1, 0.5, 1, 2.5, 5, 10, 30, 60}, + }, []string{"status"}), + IndexDuration: promauto.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: Namespace, + Subsystem: Subsystem, + Name: "index_duration_seconds", + Help: "Duration of indexing operations in seconds", + Buckets: []float64{0.1, 0.5, 1, 2.5, 5, 10, 30, 60, 120, 300, 600, 1200}, + }, []string{"status"}), } - _ = prometheus.Register(m.BuildInfo) - _ = prometheus.Register(m.EventsOutstandingAcks) - _ = prometheus.Register(m.EventsUnprocessed) - _ = prometheus.Register(m.EventsRedelivered) - return m } diff --git a/services/search/pkg/search/service.go b/services/search/pkg/search/service.go index 95591db78b..0ef9eb37fc 100644 --- a/services/search/pkg/search/service.go +++ b/services/search/pkg/search/service.go @@ -14,6 +14,7 @@ import ( rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" collaborationv1beta1 "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + libregraph "github.com/opencloud-eu/libre-graph-api-go" revactx "github.com/opencloud-eu/reva/v2/pkg/ctx" "github.com/opencloud-eu/reva/v2/pkg/errtypes" "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" @@ -21,7 +22,6 @@ import ( "github.com/opencloud-eu/reva/v2/pkg/storage/utils/walker" "github.com/opencloud-eu/reva/v2/pkg/storagespace" "github.com/opencloud-eu/reva/v2/pkg/utils" - libregraph "github.com/opencloud-eu/libre-graph-api-go" "golang.org/x/sync/errgroup" "google.golang.org/protobuf/types/known/fieldmaskpb" @@ -31,6 +31,7 @@ import ( "github.com/opencloud-eu/opencloud/services/search/pkg/config" "github.com/opencloud-eu/opencloud/services/search/pkg/content" "github.com/opencloud-eu/opencloud/services/search/pkg/engine" + "github.com/opencloud-eu/opencloud/services/search/pkg/metrics" ) const ( @@ -59,6 +60,7 @@ type Service struct { gatewaySelector pool.Selectable[gateway.GatewayAPIClient] engine engine.Engine extractor content.Extractor + metrics *metrics.Metrics serviceAccountID string serviceAccountSecret string @@ -67,12 +69,13 @@ type Service struct { var errSkipSpace error // NewService creates a new Provider instance. -func NewService(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], eng engine.Engine, extractor content.Extractor, logger log.Logger, cfg *config.Config) *Service { +func NewService(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], eng engine.Engine, extractor content.Extractor, metrics *metrics.Metrics, logger log.Logger, cfg *config.Config) *Service { var s = &Service{ gatewaySelector: gatewaySelector, engine: eng, logger: logger, extractor: extractor, + metrics: metrics, serviceAccountID: cfg.ServiceAccount.ServiceAccountID, serviceAccountSecret: cfg.ServiceAccount.ServiceAccountSecret, @@ -85,6 +88,17 @@ func NewService(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], eng e func (s *Service) Search(ctx context.Context, req *searchsvc.SearchRequest) (*searchsvc.SearchResponse, error) { s.logger.Debug().Str("query", req.Query).Msg("performing a search") + // collect metrics + startTime := time.Now() + success := false + defer func() { + status := "success" + if !success { + status = "error" + } + s.metrics.SearchDuration.WithLabelValues(status).Observe(time.Since(startTime).Seconds()) + }() + gatewayClient, err := s.gatewaySelector.Next() if err != nil { return nil, err @@ -255,6 +269,7 @@ func (s *Service) Search(ctx context.Context, req *searchsvc.SearchRequest) (*se matches = matches[0:limit] } + success = true return &searchsvc.SearchResponse{ Matches: matches, TotalMatches: total, @@ -425,6 +440,17 @@ func (s *Service) IndexSpace(spaceID *provider.StorageSpaceId) error { } rootID.OpaqueId = rootID.SpaceId + // Collect metrics + startTime := time.Now() + success := false + defer func() { + status := "success" + if !success { + status = "error" + } + s.metrics.IndexDuration.WithLabelValues(status).Observe(time.Since(startTime).Seconds()) + }() + w := walker.NewWalker(s.gatewaySelector) err = w.Walk(ownerCtx, &rootID, func(wd string, info *provider.ResourceInfo, err error) error { if err != nil { @@ -465,6 +491,7 @@ func (s *Service) IndexSpace(spaceID *provider.StorageSpaceId) error { } logDocCount(s.engine, s.logger) + success = true return nil } diff --git a/services/search/pkg/service/grpc/v0/service.go b/services/search/pkg/service/grpc/v0/service.go index bb410e5645..a89efd4dac 100644 --- a/services/search/pkg/service/grpc/v0/service.go +++ b/services/search/pkg/service/grpc/v0/service.go @@ -79,7 +79,7 @@ func NewHandler(opts ...Option) (searchsvc.SearchProviderHandler, func(), error) return nil, teardown, fmt.Errorf("unknown search extractor: %s", cfg.Extractor.Type) } - ss := search.NewService(selector, eng, extractor, logger, cfg) + ss := search.NewService(selector, eng, extractor, options.Metrics, logger, cfg) // setup event handling