From b5d9f4a2856d19db37251f655082b8f482444bab Mon Sep 17 00:00:00 2001
From: Dmitrii Stepanov <d.stepanov@yadro.com>
Date: Fri, 9 Jun 2023 16:19:47 +0300
Subject: [PATCH] [#373] metrics: Add pilorama metrics

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
---
 cmd/frostfs-node/config.go                   |  3 ++
 pkg/local_object_storage/metrics/pilorama.go | 37 ++++++++++++++
 pkg/metrics/consts.go                        |  1 +
 pkg/metrics/node.go                          |  6 +++
 pkg/metrics/pilorama.go                      | 53 ++++++++++++++++++++
 5 files changed, 100 insertions(+)
 create mode 100644 pkg/local_object_storage/metrics/pilorama.go
 create mode 100644 pkg/metrics/pilorama.go

diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go
index 1c8c49606..2cb785d30 100644
--- a/cmd/frostfs-node/config.go
+++ b/cmd/frostfs-node/config.go
@@ -729,6 +729,9 @@ func (c *cfg) getPiloramaOpts(shCfg shardCfg) []pilorama.Option {
 			pilorama.WithMaxBatchSize(prRead.maxBatchSize),
 			pilorama.WithMaxBatchDelay(prRead.maxBatchDelay),
 		)
+		if c.metricsCollector != nil {
+			piloramaOpts = append(piloramaOpts, pilorama.WithMetrics(lsmetrics.NewPiloramaMetrics(c.metricsCollector.PiloramaMetrics())))
+		}
 	}
 	return piloramaOpts
 }
diff --git a/pkg/local_object_storage/metrics/pilorama.go b/pkg/local_object_storage/metrics/pilorama.go
new file mode 100644
index 000000000..21f027a6e
--- /dev/null
+++ b/pkg/local_object_storage/metrics/pilorama.go
@@ -0,0 +1,37 @@
+package metrics
+
+import (
+	"time"
+
+	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama"
+	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
+	metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics"
+)
+
+func NewPiloramaMetrics(m metrics_impl.PiloramaMetrics) pilorama.Metrics {
+	return &piloramaMetrics{
+		shardID: undefined,
+		m:       m,
+	}
+}
+
+type piloramaMetrics struct {
+	shardID string
+	m       metrics_impl.PiloramaMetrics
+}
+
+func (m *piloramaMetrics) SetParentID(id string) {
+	m.shardID = id
+}
+
+func (m *piloramaMetrics) SetMode(mode mode.Mode) {
+	m.m.SetMode(m.shardID, mode)
+}
+
+func (m *piloramaMetrics) Close() {
+	m.m.Close(m.shardID)
+}
+
+func (m *piloramaMetrics) AddMethodDuration(method string, d time.Duration, success bool) {
+	m.m.AddMethodDuration(m.shardID, method, d, success)
+}
diff --git a/pkg/metrics/consts.go b/pkg/metrics/consts.go
index a9781abe1..878e85a35 100644
--- a/pkg/metrics/consts.go
+++ b/pkg/metrics/consts.go
@@ -5,6 +5,7 @@ const (
 	blobstoreSubSystem      = "blobstore"
 	blobovnizaTreeSubSystem = "blobovniza_tree"
 	metabaseSubSystem       = "metabase"
+	piloramaSubSystem       = "pilorama"
 
 	successLabel       = "success"
 	shardIDLabel       = "shardID"
diff --git a/pkg/metrics/node.go b/pkg/metrics/node.go
index e4e98fe1f..3d3712450 100644
--- a/pkg/metrics/node.go
+++ b/pkg/metrics/node.go
@@ -18,6 +18,7 @@ type NodeMetrics struct {
 	blobstore     *blobstoreMetrics
 	blobobvnizca  *blobovnizca
 	metabase      *metabaseMetrics
+	pilorama      *piloramaMetrics
 }
 
 func NewNodeMetrics() *NodeMetrics {
@@ -37,6 +38,7 @@ func NewNodeMetrics() *NodeMetrics {
 		blobstore:    newBlobstoreMetrics(),
 		blobobvnizca: newBlobovnizca(),
 		metabase:     newMetabaseMetrics(),
+		pilorama:     newPiloramaMetrics(),
 	}
 }
 
@@ -80,3 +82,7 @@ func (m *NodeMetrics) BlobobvnizcaTreeMetrics() BlobobvnizcaMetrics {
 func (m *NodeMetrics) MetabaseMetrics() MetabaseMetrics {
 	return m.metabase
 }
+
+func (m *NodeMetrics) PiloramaMetrics() PiloramaMetrics {
+	return m.pilorama
+}
diff --git a/pkg/metrics/pilorama.go b/pkg/metrics/pilorama.go
new file mode 100644
index 000000000..41672a4b5
--- /dev/null
+++ b/pkg/metrics/pilorama.go
@@ -0,0 +1,53 @@
+package metrics
+
+import (
+	"strconv"
+	"time"
+
+	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
+	"git.frostfs.info/TrueCloudLab/frostfs-observability/metrics"
+	"github.com/prometheus/client_golang/prometheus"
+)
+
+type PiloramaMetrics interface {
+	SetMode(shardID string, m mode.Mode)
+	Close(shardID string)
+
+	AddMethodDuration(shardID string, method string, d time.Duration, success bool)
+}
+
+func newPiloramaMetrics() *piloramaMetrics {
+	return &piloramaMetrics{
+		mode: newShardIDMode(piloramaSubSystem, "mode", "Pilorama mode"),
+		reqDuration: metrics.NewHistogramVec(prometheus.HistogramOpts{
+			Namespace: namespace,
+			Subsystem: piloramaSubSystem,
+			Name:      "request_duration_seconds",
+			Help:      "Accumulated Pilorama request process duration",
+		}, []string{shardIDLabel, successLabel, methodLabel}),
+	}
+}
+
+type piloramaMetrics struct {
+	mode        *shardIDModeValue
+	reqDuration *prometheus.HistogramVec
+}
+
+func (m *piloramaMetrics) SetMode(shardID string, mode mode.Mode) {
+	m.mode.SetMode(shardID, mode.String())
+}
+
+func (m *piloramaMetrics) AddMethodDuration(shardID string, method string, d time.Duration, success bool) {
+	m.reqDuration.With(prometheus.Labels{
+		shardIDLabel: shardID,
+		successLabel: strconv.FormatBool(success),
+		methodLabel:  method,
+	}).Observe(d.Seconds())
+}
+
+func (m *piloramaMetrics) Close(shardID string) {
+	m.mode.SetMode(shardID, closedMode)
+	m.reqDuration.DeletePartialMatch(prometheus.Labels{
+		shardIDLabel: shardID,
+	})
+}