forked from TrueCloudLab/frostfs-node
WIP: Morph: Add unit tests #2
8 changed files with 236 additions and 6 deletions
|
@ -36,6 +36,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
|
||||||
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase"
|
||||||
|
lsmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metrics"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
|
||||||
shardmode "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
shardmode "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode"
|
||||||
|
@ -752,12 +753,22 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
case fstree.Type:
|
case fstree.Type:
|
||||||
|
fstreeOpts := []fstree.Option{
|
||||||
|
fstree.WithPath(sRead.path),
|
||||||
|
fstree.WithPerm(sRead.perm),
|
||||||
|
fstree.WithDepth(sRead.depth),
|
||||||
|
fstree.WithNoSync(sRead.noSync),
|
||||||
|
}
|
||||||
|
if c.metricsCollector != nil {
|
||||||
|
fstreeOpts = append(fstreeOpts,
|
||||||
|
fstree.WithMetrics(
|
||||||
|
lsmetrics.NewFSTreeMetricsWithoutShardID(sRead.path, c.metricsCollector.FSTree()),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
ss = append(ss, blobstor.SubStorage{
|
ss = append(ss, blobstor.SubStorage{
|
||||||
Storage: fstree.New(
|
Storage: fstree.New(fstreeOpts...),
|
||||||
fstree.WithPath(sRead.path),
|
|
||||||
fstree.WithPerm(sRead.perm),
|
|
||||||
fstree.WithDepth(sRead.depth),
|
|
||||||
fstree.WithNoSync(sRead.noSync)),
|
|
||||||
Policy: func(_ *objectSDK.Object, data []byte) bool {
|
Policy: func(_ *objectSDK.Object, data []byte) bool {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
|
3
pkg/local_object_storage/metrics/consts.go
Normal file
3
pkg/local_object_storage/metrics/consts.go
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
package metrics
|
||||||
|
|
||||||
|
const undefined = "undefined"
|
61
pkg/local_object_storage/metrics/fstree.go
Normal file
61
pkg/local_object_storage/metrics/fstree.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree"
|
||||||
|
metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewFSTreeMetricsWithoutShardID(path string, m metrics_impl.FSTreeMetrics) fstree.Metrics {
|
||||||
|
return &fstreeMetrics{
|
||||||
|
shardID: undefined,
|
||||||
|
path: path,
|
||||||
|
m: m,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fstreeMetrics struct {
|
||||||
|
shardID string
|
||||||
|
path string
|
||||||
|
m metrics_impl.FSTreeMetrics
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *fstreeMetrics) SetParentID(parentID string) {
|
||||||
|
m.shardID = parentID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *fstreeMetrics) SetMode(readOnly bool) {
|
||||||
|
m.m.SetMode(m.shardID, m.path, readOnly)
|
||||||
|
}
|
||||||
|
func (m *fstreeMetrics) Close() {
|
||||||
|
m.m.Close(m.shardID, m.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *fstreeMetrics) Iterate(d time.Duration, success bool) {
|
||||||
|
m.m.MethodDuration(m.shardID, m.path, "Iterate", d, success)
|
||||||
|
}
|
||||||
|
func (m *fstreeMetrics) Delete(d time.Duration, success bool) {
|
||||||
|
m.m.MethodDuration(m.shardID, m.path, "Delete", d, success)
|
||||||
|
}
|
||||||
|
func (m *fstreeMetrics) Exists(d time.Duration, success bool) {
|
||||||
|
m.m.MethodDuration(m.shardID, m.path, "Exists", d, success)
|
||||||
|
}
|
||||||
|
func (m *fstreeMetrics) Put(d time.Duration, size int, success bool) {
|
||||||
|
m.m.MethodDuration(m.shardID, m.path, "Put", d, success)
|
||||||
|
if success {
|
||||||
|
m.m.AddPut(m.shardID, m.path, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (m *fstreeMetrics) Get(d time.Duration, size int, success bool) {
|
||||||
|
m.m.MethodDuration(m.shardID, m.path, "Get", d, success)
|
||||||
|
if success {
|
||||||
|
m.m.AddGet(m.shardID, m.path, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (m *fstreeMetrics) GetRange(d time.Duration, size int, success bool) {
|
||||||
|
m.m.MethodDuration(m.shardID, m.path, "GetRange", d, success)
|
||||||
|
if success {
|
||||||
|
m.m.AddGet(m.shardID, m.path, size)
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,7 +57,9 @@ func (s *Shard) UpdateID() (err error) {
|
||||||
}
|
}
|
||||||
s.metaBase.SetParentID(s.info.ID.String())
|
s.metaBase.SetParentID(s.info.ID.String())
|
||||||
s.blobStor.SetParentID(s.info.ID.String())
|
s.blobStor.SetParentID(s.info.ID.String())
|
||||||
s.pilorama.SetParentID(s.info.ID.String())
|
if s.pilorama != nil {
|
||||||
|
s.pilorama.SetParentID(s.info.ID.String())
|
||||||
|
}
|
||||||
|
|
||||||
if len(id) != 0 {
|
if len(id) != 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
15
pkg/metrics/consts.go
Normal file
15
pkg/metrics/consts.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package metrics
|
||||||
|
|
||||||
|
const (
|
||||||
|
fstreeSubSystem = "fstree"
|
||||||
|
|
||||||
|
successLabel = "success"
|
||||||
|
shardIDLabel = "shardID"
|
||||||
|
modeLabel = "mode"
|
||||||
|
pathLabel = "path"
|
||||||
|
methodLabel = "method"
|
||||||
|
|
||||||
|
readWriteMode = "READ_WRITE"
|
||||||
|
readOnlyMode = "READ_ONLY"
|
||||||
|
closedMode = "CLOSED"
|
||||||
|
)
|
96
pkg/metrics/fstree.go
Normal file
96
pkg/metrics/fstree.go
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-observability/metrics"
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FSTreeMetrics interface {
|
||||||
|
SetMode(shardID, path string, readOnly bool)
|
||||||
|
Close(shardID, path string)
|
||||||
|
|
||||||
|
MethodDuration(shardID, path string, method string, d time.Duration, success bool)
|
||||||
|
AddGet(shardID, path string, size int)
|
||||||
|
AddPut(shardID, path string, size int)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fstreeMetrics struct {
|
||||||
|
mode *shardIDPathModeValue
|
||||||
|
reqDuration *prometheus.HistogramVec
|
||||||
|
put *prometheus.CounterVec
|
||||||
|
get *prometheus.CounterVec
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFSTreeMetrics() *fstreeMetrics {
|
||||||
|
return &fstreeMetrics{
|
||||||
|
mode: newShardIDPathMode(fstreeSubSystem, "mode", "FSTree mode value"),
|
||||||
|
reqDuration: metrics.NewHistogramVec(prometheus.HistogramOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Subsystem: fstreeSubSystem,
|
||||||
|
Name: "request_duration_seconds",
|
||||||
|
Help: "Accumulated FSTree request process duration",
|
||||||
|
}, []string{shardIDLabel, successLabel, pathLabel, methodLabel}),
|
||||||
|
put: metrics.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Subsystem: fstreeSubSystem,
|
||||||
|
Name: "put_bytes",
|
||||||
|
Help: "Accumulated payload size written to FSTree",
|
||||||
|
}, []string{shardIDLabel, pathLabel}),
|
||||||
|
get: metrics.NewCounterVec(prometheus.CounterOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Subsystem: fstreeSubSystem,
|
||||||
|
Name: "get_bytes",
|
||||||
|
Help: "Accumulated payload size read from FSTree",
|
||||||
|
}, []string{shardIDLabel, pathLabel}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *fstreeMetrics) SetMode(shardID, path string, readOnly bool) {
|
||||||
|
modeValue := readWriteMode
|
||||||
|
if readOnly {
|
||||||
|
modeValue = readOnlyMode
|
||||||
|
}
|
||||||
|
m.mode.SetMode(shardID, path, modeValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *fstreeMetrics) Close(shardID, path string) {
|
||||||
|
m.mode.SetMode(shardID, path, closedMode)
|
||||||
|
m.reqDuration.DeletePartialMatch(prometheus.Labels{
|
||||||
|
shardIDLabel: shardID,
|
||||||
|
pathLabel: path,
|
||||||
|
})
|
||||||
|
m.get.DeletePartialMatch(prometheus.Labels{
|
||||||
|
shardIDLabel: shardID,
|
||||||
|
pathLabel: path,
|
||||||
|
})
|
||||||
|
m.put.DeletePartialMatch(prometheus.Labels{
|
||||||
|
shardIDLabel: shardID,
|
||||||
|
pathLabel: path,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *fstreeMetrics) MethodDuration(shardID, path string, method string, d time.Duration, success bool) {
|
||||||
|
m.reqDuration.With(prometheus.Labels{
|
||||||
|
shardIDLabel: shardID,
|
||||||
|
pathLabel: path,
|
||||||
|
successLabel: strconv.FormatBool(success),
|
||||||
|
methodLabel: method,
|
||||||
|
}).Observe(d.Seconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *fstreeMetrics) AddGet(shardID, path string, size int) {
|
||||||
|
m.get.With(prometheus.Labels{
|
||||||
|
shardIDLabel: shardID,
|
||||||
|
pathLabel: path,
|
||||||
|
}).Add(float64(size))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *fstreeMetrics) AddPut(shardID, path string, size int) {
|
||||||
|
m.put.With(prometheus.Labels{
|
||||||
|
shardIDLabel: shardID,
|
||||||
|
pathLabel: path,
|
||||||
|
}).Add(float64(size))
|
||||||
|
}
|
|
@ -37,3 +37,39 @@ func (m *shardIDModeValue) Delete(shardID string) {
|
||||||
wcShardID: shardID,
|
wcShardID: shardID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type shardIDPathModeValue struct {
|
||||||
|
modeValue *prometheus.GaugeVec
|
||||||
|
}
|
||||||
|
|
||||||
|
func newShardIDPathMode(subsystem, name, help string) *shardIDPathModeValue {
|
||||||
|
return &shardIDPathModeValue{
|
||||||
|
modeValue: metrics.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Subsystem: subsystem,
|
||||||
|
Name: name,
|
||||||
|
Help: help,
|
||||||
|
}, []string{shardIDLabel, pathLabel, modeLabel}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *shardIDPathModeValue) SetMode(shardID, path string, mode string) {
|
||||||
|
m.modeValue.DeletePartialMatch(prometheus.Labels{
|
||||||
|
shardIDLabel: shardID,
|
||||||
|
pathLabel: path,
|
||||||
|
})
|
||||||
|
|
||||||
|
m.modeValue.With(prometheus.Labels{
|
||||||
|
shardIDLabel: shardID,
|
||||||
|
pathLabel: path,
|
||||||
|
modeLabel: mode,
|
||||||
|
}).Set(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *shardIDPathModeValue) Delete(shardID, path string) {
|
||||||
|
m.modeValue.DeletePartialMatch(prometheus.Labels{
|
||||||
|
shardIDLabel: shardID,
|
||||||
|
pathLabel: path,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ type NodeMetrics struct {
|
||||||
objectService *objectServiceMetrics
|
objectService *objectServiceMetrics
|
||||||
treeService *treeServiceMetrics
|
treeService *treeServiceMetrics
|
||||||
epoch prometheus.Gauge
|
epoch prometheus.Gauge
|
||||||
|
fstree *fstreeMetrics
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNodeMetrics() *NodeMetrics {
|
func NewNodeMetrics() *NodeMetrics {
|
||||||
|
@ -41,6 +42,7 @@ func NewNodeMetrics() *NodeMetrics {
|
||||||
replicator: replicator,
|
replicator: replicator,
|
||||||
treeService: treeService,
|
treeService: treeService,
|
||||||
epoch: epoch,
|
epoch: epoch,
|
||||||
|
fstree: newFSTreeMetrics(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,3 +70,7 @@ func (m *NodeMetrics) Engine() EngineMetrics {
|
||||||
func (m *NodeMetrics) State() StateMetrics {
|
func (m *NodeMetrics) State() StateMetrics {
|
||||||
return m.state
|
return m.state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *NodeMetrics) FSTree() FSTreeMetrics {
|
||||||
|
return m.fstree
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue