Add blobovnicza items metric #623

Merged
fyrchik merged 2 commits from dstepanov-yadro/frostfs-node:feat/blobovnicza_items_count_metric into master 2024-09-04 19:51:02 +00:00
13 changed files with 122 additions and 70 deletions

View file

@ -16,7 +16,8 @@ import (
type Blobovnicza struct { type Blobovnicza struct {
cfg cfg
dataSize atomic.Uint64 dataSize atomic.Uint64
itemsCount atomic.Uint64
boltDB *bbolt.DB boltDB *bbolt.DB

View file

@ -14,7 +14,7 @@ import (
// Open opens an internal database at the configured path with the configured permissions. // Open opens an internal database at the configured path with the configured permissions.
// //
// If the database file does not exist, it will be created automatically. // If the database file does not exist, it will be created automatically.
// If blobovnizca is already open, does nothing. // If blobovnicza is already open, does nothing.
func (b *Blobovnicza) Open() error { func (b *Blobovnicza) Open() error {
b.controlMtx.Lock() b.controlMtx.Lock()
defer b.controlMtx.Unlock() defer b.controlMtx.Unlock()
@ -45,7 +45,7 @@ func (b *Blobovnicza) Open() error {
b.boltDB, err = bbolt.Open(b.path, b.perm, b.boltOptions) b.boltDB, err = bbolt.Open(b.path, b.perm, b.boltOptions)
if err == nil { if err == nil {
b.opened = true b.opened = true
b.metrics.IncOpenBlobovnizcaCount() b.metrics.IncOpenBlobovniczaCount()
} }
return err return err
@ -54,13 +54,13 @@ func (b *Blobovnicza) Open() error {
// Init initializes internal database structure. // Init initializes internal database structure.
// //
// If Blobovnicza is already initialized, no action is taken. // If Blobovnicza is already initialized, no action is taken.
// Blobovnizca must be open, otherwise an error will return. // Blobovnicza must be open, otherwise an error will return.
func (b *Blobovnicza) Init() error { func (b *Blobovnicza) Init() error {
b.controlMtx.Lock() b.controlMtx.Lock()
defer b.controlMtx.Unlock() defer b.controlMtx.Unlock()
if !b.opened { if !b.opened {
return errors.New("blobovnizca is not open") return errors.New("blobovnicza is not open")
} }
b.log.Debug(logs.BlobovniczaInitializing, b.log.Debug(logs.BlobovniczaInitializing,
@ -68,8 +68,10 @@ func (b *Blobovnicza) Init() error {
zap.Uint64("storage size limit", b.fullSizeLimit), zap.Uint64("storage size limit", b.fullSizeLimit),
) )
if size := b.dataSize.Load(); size != 0 { size := b.dataSize.Load()
b.log.Debug(logs.BlobovniczaAlreadyInitialized, zap.Uint64("size", size)) items := b.itemsCount.Load()
if size != 0 || items != 0 {
b.log.Debug(logs.BlobovniczaAlreadyInitialized, zap.Uint64("size", size), zap.Uint64("items", items))
return nil return nil
} }
@ -96,14 +98,17 @@ func (b *Blobovnicza) Init() error {
} }
} }
return b.initializeSize() return b.initializeCounters()
} }
func (b *Blobovnicza) initializeSize() error { func (b *Blobovnicza) initializeCounters() error {
var size uint64 var size uint64
var items uint64
err := b.boltDB.View(func(tx *bbolt.Tx) error { err := b.boltDB.View(func(tx *bbolt.Tx) error {
return b.iterateAllBuckets(tx, func(lower, upper uint64, b *bbolt.Bucket) (bool, error) { return b.iterateAllBuckets(tx, func(lower, upper uint64, b *bbolt.Bucket) (bool, error) {
size += uint64(b.Stats().KeyN) * upper keysN := uint64(b.Stats().KeyN)
size += keysN * upper
items += keysN
return false, nil return false, nil
}) })
}) })
@ -111,13 +116,15 @@ func (b *Blobovnicza) initializeSize() error {
return fmt.Errorf("can't determine DB size: %w", err) return fmt.Errorf("can't determine DB size: %w", err)
} }
b.dataSize.Store(size) b.dataSize.Store(size)
b.metrics.AddOpenBlobovnizcaSize(size) b.itemsCount.Store(items)
b.metrics.AddOpenBlobovniczaSize(size)
b.metrics.AddOpenBlobovniczaItems(items)
return nil return nil
} }
// Close releases all internal database resources. // Close releases all internal database resources.
// //
// If blobovnizca is already closed, does nothing. // If blobovnicza is already closed, does nothing.
func (b *Blobovnicza) Close() error { func (b *Blobovnicza) Close() error {
b.controlMtx.Lock() b.controlMtx.Lock()
defer b.controlMtx.Unlock() defer b.controlMtx.Unlock()
@ -134,9 +141,11 @@ func (b *Blobovnicza) Close() error {
return err return err
} }
b.metrics.DecOpenBlobovnizcaCount() b.metrics.DecOpenBlobovniczaCount()
b.metrics.SubOpenBlobovnizcaSize(b.dataSize.Load()) b.metrics.SubOpenBlobovniczaSize(b.dataSize.Load())
b.metrics.SubOpenBlobovniczaItems(b.itemsCount.Load())
b.dataSize.Store(0) b.dataSize.Store(0)
b.itemsCount.Store(0)
b.opened = false b.opened = false

View file

@ -74,7 +74,7 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err
zap.String("binary size", stringifyByteSize(dataSize)), zap.String("binary size", stringifyByteSize(dataSize)),
zap.String("range", stringifyBounds(sizeLowerBound, sizeUpperBound)), zap.String("range", stringifyBounds(sizeLowerBound, sizeUpperBound)),
) )
b.decSize(sizeUpperBound) b.itemDeleted(sizeUpperBound)
} }
return DeleteRes{}, err return DeleteRes{}, err

View file

@ -1,16 +1,21 @@
package blobovnicza package blobovnicza
type Metrics interface { type Metrics interface {
IncOpenBlobovnizcaCount() IncOpenBlobovniczaCount()
DecOpenBlobovnizcaCount() DecOpenBlobovniczaCount()
AddOpenBlobovnizcaSize(size uint64) AddOpenBlobovniczaSize(size uint64)
SubOpenBlobovnizcaSize(size uint64) SubOpenBlobovniczaSize(size uint64)
AddOpenBlobovniczaItems(items uint64)
SubOpenBlobovniczaItems(items uint64)
} }
type NoopMetrics struct{} type NoopMetrics struct{}
func (m *NoopMetrics) IncOpenBlobovnizcaCount() {} func (m *NoopMetrics) IncOpenBlobovniczaCount() {}
func (m *NoopMetrics) DecOpenBlobovnizcaCount() {} func (m *NoopMetrics) DecOpenBlobovniczaCount() {}
func (m *NoopMetrics) AddOpenBlobovnizcaSize(uint64) {} func (m *NoopMetrics) AddOpenBlobovniczaSize(uint64) {}
func (m *NoopMetrics) SubOpenBlobovnizcaSize(uint64) {} func (m *NoopMetrics) SubOpenBlobovniczaSize(uint64) {}
func (m *NoopMetrics) AddOpenBlobovniczaItems(uint64) {}
func (m *NoopMetrics) SubOpenBlobovniczaItems(uint64) {}

View file

@ -85,7 +85,7 @@ func (b *Blobovnicza) Put(ctx context.Context, prm PutPrm) (PutRes, error) {
return nil return nil
}) })
if err == nil { if err == nil {
b.incSize(upperBound) b.itemAdded(upperBound)
} }
return PutRes{}, err return PutRes{}, err

View file

@ -3,6 +3,7 @@ package blobovnicza
import ( import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math"
"math/bits" "math/bits"
"strconv" "strconv"
) )
@ -40,14 +41,18 @@ func upperPowerOfTwo(v uint64) uint64 {
return 1 << bits.Len64(v-1) return 1 << bits.Len64(v-1)
} }
func (b *Blobovnicza) incSize(sz uint64) { func (b *Blobovnicza) itemAdded(itemSize uint64) {
b.dataSize.Add(sz) b.dataSize.Add(itemSize)
b.metrics.AddOpenBlobovnizcaSize(sz) b.itemsCount.Add(1)
b.metrics.AddOpenBlobovniczaSize(itemSize)
b.metrics.AddOpenBlobovniczaItems(1)
} }
func (b *Blobovnicza) decSize(sz uint64) { func (b *Blobovnicza) itemDeleted(itemSize uint64) {
b.dataSize.Add(^(sz - 1)) b.dataSize.Add(^(itemSize - 1))
b.metrics.SubOpenBlobovnizcaSize(sz) b.itemsCount.Add(math.MaxUint64)
b.metrics.SubOpenBlobovniczaSize(itemSize)
b.metrics.SubOpenBlobovniczaItems(1)
} }
func (b *Blobovnicza) full() bool { func (b *Blobovnicza) full() bool {

View file

@ -89,7 +89,7 @@ var _ common.Storage = (*Blobovniczas)(nil)
var errPutFailed = errors.New("could not save the object in any blobovnicza") var errPutFailed = errors.New("could not save the object in any blobovnicza")
// NewBlobovniczaTree returns new instance of blobovnizas tree. // NewBlobovniczaTree returns new instance of blobovniczas tree.
func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) {
blz = new(Blobovniczas) blz = new(Blobovniczas)
initConfig(&blz.cfg) initConfig(&blz.cfg)

View file

@ -130,7 +130,7 @@ func (b *Blobovniczas) openBlobovniczaNoCache(p string) (*blobovnicza.Blobovnicz
blz := blobovnicza.New(append(b.blzOpts, blz := blobovnicza.New(append(b.blzOpts,
blobovnicza.WithReadOnly(b.readOnly), blobovnicza.WithReadOnly(b.readOnly),
blobovnicza.WithPath(path), blobovnicza.WithPath(path),
blobovnicza.WithMetrics(b.metrics.Blobovnizca()), blobovnicza.WithMetrics(b.metrics.Blobovnicza()),
)...) )...)
if err := blz.Open(); err != nil { if err := blz.Open(); err != nil {

View file

@ -7,7 +7,7 @@ import (
) )
type Metrics interface { type Metrics interface {
Blobovnizca() blobovnicza.Metrics Blobovnicza() blobovnicza.Metrics
SetParentID(parentID string) SetParentID(parentID string)
@ -33,6 +33,6 @@ func (m *noopMetrics) GetRange(time.Duration, int, bool, bool) {}
func (m *noopMetrics) Get(time.Duration, int, bool, bool) {} func (m *noopMetrics) Get(time.Duration, int, bool, bool) {}
func (m *noopMetrics) Iterate(time.Duration, bool) {} func (m *noopMetrics) Iterate(time.Duration, bool) {}
func (m *noopMetrics) Put(time.Duration, int, bool) {} func (m *noopMetrics) Put(time.Duration, int, bool) {}
func (m *noopMetrics) Blobovnizca() blobovnicza.Metrics { func (m *noopMetrics) Blobovnicza() blobovnicza.Metrics {
return &blobovnicza.NoopMetrics{} return &blobovnicza.NoopMetrics{}
} }

View file

@ -80,7 +80,7 @@ func BenchmarkPut(b *testing.B) {
}) })
} }
func TestDB_PutBlobovnicaUpdate(t *testing.T) { func TestDB_PutBlobovniczaUpdate(t *testing.T) {
db := newDB(t) db := newDB(t)
raw1 := testutil.GenerateObject() raw1 := testutil.GenerateObject()

View file

@ -22,7 +22,7 @@ type blobovniczaTreeMetrics struct {
m metrics_impl.BlobobvnizcaMetrics m metrics_impl.BlobobvnizcaMetrics
} }
func (m *blobovniczaTreeMetrics) Blobovnizca() blobovnicza.Metrics { func (m *blobovniczaTreeMetrics) Blobovnicza() blobovnicza.Metrics {
return &blobovniczaMetrics{ return &blobovniczaMetrics{
shardID: func() string { return m.shardID }, shardID: func() string { return m.shardID },
path: m.path, path: m.path,
@ -81,18 +81,26 @@ type blobovniczaMetrics struct {
path string path string
} }
func (m *blobovniczaMetrics) AddOpenBlobovnizcaSize(size uint64) { func (m *blobovniczaMetrics) AddOpenBlobovniczaSize(size uint64) {
m.m.AddOpenBlobovnizcaSize(m.shardID(), m.path, size) m.m.AddOpenBlobovniczaSize(m.shardID(), m.path, size)
} }
func (m *blobovniczaMetrics) SubOpenBlobovnizcaSize(size uint64) { func (m *blobovniczaMetrics) SubOpenBlobovniczaSize(size uint64) {
m.m.SubOpenBlobovnizcaSize(m.shardID(), m.path, size) m.m.SubOpenBlobovniczaSize(m.shardID(), m.path, size)
} }
func (m *blobovniczaMetrics) IncOpenBlobovnizcaCount() { func (m *blobovniczaMetrics) IncOpenBlobovniczaCount() {
m.m.IncOpenBlobovnizcaCount(m.shardID(), m.path) m.m.IncOpenBlobovniczaCount(m.shardID(), m.path)
} }
func (m *blobovniczaMetrics) DecOpenBlobovnizcaCount() { func (m *blobovniczaMetrics) DecOpenBlobovniczaCount() {
m.m.DecOpenBlobovnizcaCount(m.shardID(), m.path) m.m.DecOpenBlobovniczaCount(m.shardID(), m.path)
}
func (m *blobovniczaMetrics) AddOpenBlobovniczaItems(items uint64) {
m.m.AddOpenBlobovniczaItems(m.shardID(), m.path, items)
}
func (m *blobovniczaMetrics) SubOpenBlobovniczaItems(items uint64) {
m.m.SubOpenBlobovniczaItems(m.shardID(), m.path, items)
} }

View file

@ -15,64 +15,74 @@ type BlobobvnizcaMetrics interface {
AddBlobobvnizcaTreePut(shardID, path string, size int) AddBlobobvnizcaTreePut(shardID, path string, size int)
AddBlobobvnizcaTreeGet(shardID, path string, size int) AddBlobobvnizcaTreeGet(shardID, path string, size int)
AddOpenBlobovnizcaSize(shardID, path string, size uint64) AddOpenBlobovniczaSize(shardID, path string, size uint64)
SubOpenBlobovnizcaSize(shardID, path string, size uint64) SubOpenBlobovniczaSize(shardID, path string, size uint64)
IncOpenBlobovnizcaCount(shardID, path string) AddOpenBlobovniczaItems(shardID, path string, items uint64)
DecOpenBlobovnizcaCount(shardID, path string) SubOpenBlobovniczaItems(shardID, path string, items uint64)
IncOpenBlobovniczaCount(shardID, path string)
DecOpenBlobovniczaCount(shardID, path string)
} }
type blobovnizca struct { type blobovnicza struct {
treeMode *shardIDPathModeValue treeMode *shardIDPathModeValue
treeReqDuration *prometheus.HistogramVec treeReqDuration *prometheus.HistogramVec
treePut *prometheus.CounterVec treePut *prometheus.CounterVec
treeGet *prometheus.CounterVec treeGet *prometheus.CounterVec
treeOpenSize *prometheus.GaugeVec treeOpenSize *prometheus.GaugeVec
treeOpenItems *prometheus.GaugeVec
treeOpenCounter *prometheus.GaugeVec treeOpenCounter *prometheus.GaugeVec
} }
func newBlobovnizca() *blobovnizca { func newBlobovnicza() *blobovnicza {
return &blobovnizca{ return &blobovnicza{
treeMode: newShardIDPathMode(blobovniczaTreeSubSystem, "mode", "Blobovnizca tree mode"), treeMode: newShardIDPathMode(blobovniczaTreeSubSystem, "mode", "Blobovnicza tree mode"),
treeReqDuration: metrics.NewHistogramVec(prometheus.HistogramOpts{ treeReqDuration: metrics.NewHistogramVec(prometheus.HistogramOpts{
Namespace: namespace, Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem, Subsystem: blobovniczaTreeSubSystem,
Name: "request_duration_seconds", Name: "request_duration_seconds",
Help: "Accumulated Blobovnizca tree request process duration", Help: "Accumulated Blobovnicza tree request process duration",
}, []string{shardIDLabel, pathLabel, successLabel, methodLabel, withStorageIDLabel}), }, []string{shardIDLabel, pathLabel, successLabel, methodLabel, withStorageIDLabel}),
treePut: metrics.NewCounterVec(prometheus.CounterOpts{ treePut: metrics.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace, Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem, Subsystem: blobovniczaTreeSubSystem,
Name: "put_bytes", Name: "put_bytes",
Help: "Accumulated payload size written to Blobovnizca tree", Help: "Accumulated payload size written to Blobovnicza tree",
}, []string{shardIDLabel, pathLabel}), }, []string{shardIDLabel, pathLabel}),
treeGet: metrics.NewCounterVec(prometheus.CounterOpts{ treeGet: metrics.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace, Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem, Subsystem: blobovniczaTreeSubSystem,
Name: "get_bytes", Name: "get_bytes",
Help: "Accumulated payload size read from Blobovnizca tree", Help: "Accumulated payload size read from Blobovnicza tree",
}, []string{shardIDLabel, pathLabel}), }, []string{shardIDLabel, pathLabel}),
treeOpenSize: metrics.NewGaugeVec(prometheus.GaugeOpts{ treeOpenSize: metrics.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace, Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem, Subsystem: blobovniczaTreeSubSystem,
Name: "open_blobovnizca_size_bytes", Name: "open_blobovnicza_size_bytes",
Help: "Size of opened blobovnizcas of Blobovnizca tree", Help: "Size of opened blobovniczas of Blobovnicza tree",
}, []string{shardIDLabel, pathLabel}),
treeOpenItems: metrics.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem,
Name: "open_blobovnicza_items_total",
Help: "Count of items in opened blobovniczas of Blobovnicza tree",
}, []string{shardIDLabel, pathLabel}), }, []string{shardIDLabel, pathLabel}),
treeOpenCounter: metrics.NewGaugeVec(prometheus.GaugeOpts{ treeOpenCounter: metrics.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace, Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem, Subsystem: blobovniczaTreeSubSystem,
Name: "open_blobovnizca_count", Name: "open_blobovnicza_count",
Help: "Count of opened blobovnizcas of Blobovnizca tree", Help: "Count of opened blobovniczas of Blobovnicza tree",
}, []string{shardIDLabel, pathLabel}), }, []string{shardIDLabel, pathLabel}),
} }
} }
func (b *blobovnizca) SetBlobobvnizcaTreeMode(shardID, path string, readOnly bool) { func (b *blobovnicza) SetBlobobvnizcaTreeMode(shardID, path string, readOnly bool) {
b.treeMode.SetMode(shardID, path, modeFromBool(readOnly)) b.treeMode.SetMode(shardID, path, modeFromBool(readOnly))
} }
func (b *blobovnizca) CloseBlobobvnizcaTree(shardID, path string) { func (b *blobovnicza) CloseBlobobvnizcaTree(shardID, path string) {
b.treeMode.SetMode(shardID, path, closedMode) b.treeMode.SetMode(shardID, path, closedMode)
b.treeReqDuration.DeletePartialMatch(prometheus.Labels{ b.treeReqDuration.DeletePartialMatch(prometheus.Labels{
shardIDLabel: shardID, shardIDLabel: shardID,
@ -88,7 +98,7 @@ func (b *blobovnizca) CloseBlobobvnizcaTree(shardID, path string) {
}) })
} }
func (b *blobovnizca) BlobobvnizcaTreeMethodDuration(shardID, path string, method string, d time.Duration, success bool, withStorageID NullBool) { func (b *blobovnicza) BlobobvnizcaTreeMethodDuration(shardID, path string, method string, d time.Duration, success bool, withStorageID NullBool) {
b.treeReqDuration.With(prometheus.Labels{ b.treeReqDuration.With(prometheus.Labels{
shardIDLabel: shardID, shardIDLabel: shardID,
pathLabel: path, pathLabel: path,
@ -98,44 +108,58 @@ func (b *blobovnizca) BlobobvnizcaTreeMethodDuration(shardID, path string, metho
}).Observe(d.Seconds()) }).Observe(d.Seconds())
} }
func (b *blobovnizca) AddBlobobvnizcaTreePut(shardID, path string, size int) { func (b *blobovnicza) AddBlobobvnizcaTreePut(shardID, path string, size int) {
b.treePut.With(prometheus.Labels{ b.treePut.With(prometheus.Labels{
shardIDLabel: shardID, shardIDLabel: shardID,
pathLabel: path, pathLabel: path,
}).Add(float64(size)) }).Add(float64(size))
} }
func (b *blobovnizca) AddBlobobvnizcaTreeGet(shardID, path string, size int) { func (b *blobovnicza) AddBlobobvnizcaTreeGet(shardID, path string, size int) {
b.treeGet.With(prometheus.Labels{ b.treeGet.With(prometheus.Labels{
shardIDLabel: shardID, shardIDLabel: shardID,
pathLabel: path, pathLabel: path,
}).Add(float64(size)) }).Add(float64(size))
} }
func (b *blobovnizca) AddOpenBlobovnizcaSize(shardID, path string, size uint64) { func (b *blobovnicza) AddOpenBlobovniczaSize(shardID, path string, size uint64) {
b.treeOpenSize.With(prometheus.Labels{ b.treeOpenSize.With(prometheus.Labels{
shardIDLabel: shardID, shardIDLabel: shardID,
pathLabel: path, pathLabel: path,
}).Add(float64(size)) }).Add(float64(size))
} }
func (b *blobovnizca) SubOpenBlobovnizcaSize(shardID, path string, size uint64) { func (b *blobovnicza) SubOpenBlobovniczaSize(shardID, path string, size uint64) {
b.treeOpenSize.With(prometheus.Labels{ b.treeOpenSize.With(prometheus.Labels{
shardIDLabel: shardID, shardIDLabel: shardID,
pathLabel: path, pathLabel: path,
}).Sub(float64(size)) }).Sub(float64(size))
} }
func (b *blobovnizca) IncOpenBlobovnizcaCount(shardID, path string) { func (b *blobovnicza) IncOpenBlobovniczaCount(shardID, path string) {
b.treeOpenCounter.With(prometheus.Labels{ b.treeOpenCounter.With(prometheus.Labels{
shardIDLabel: shardID, shardIDLabel: shardID,
pathLabel: path, pathLabel: path,
}).Inc() }).Inc()
} }
func (b *blobovnizca) DecOpenBlobovnizcaCount(shardID, path string) { func (b *blobovnicza) DecOpenBlobovniczaCount(shardID, path string) {
b.treeOpenCounter.With(prometheus.Labels{ b.treeOpenCounter.With(prometheus.Labels{
shardIDLabel: shardID, shardIDLabel: shardID,
pathLabel: path, pathLabel: path,
}).Dec() }).Dec()
} }
func (b *blobovnicza) AddOpenBlobovniczaItems(shardID, path string, items uint64) {
b.treeOpenItems.With(prometheus.Labels{
shardIDLabel: shardID,
pathLabel: path,
}).Add(float64(items))
}
func (b *blobovnicza) SubOpenBlobovniczaItems(shardID, path string, items uint64) {
b.treeOpenItems.With(prometheus.Labels{
shardIDLabel: shardID,
pathLabel: path,
}).Sub(float64(items))
}

View file

@ -14,7 +14,7 @@ type NodeMetrics struct {
epoch prometheus.Gauge epoch prometheus.Gauge
fstree *fstreeMetrics fstree *fstreeMetrics
blobstore *blobstoreMetrics blobstore *blobstoreMetrics
blobobvnizca *blobovnizca blobobvnizca *blobovnicza
metabase *metabaseMetrics metabase *metabaseMetrics
pilorama *piloramaMetrics pilorama *piloramaMetrics
grpc *grpcServerMetrics grpc *grpcServerMetrics
@ -35,7 +35,7 @@ func NewNodeMetrics() *NodeMetrics {
}), }),
fstree: newFSTreeMetrics(), fstree: newFSTreeMetrics(),
blobstore: newBlobstoreMetrics(), blobstore: newBlobstoreMetrics(),
blobobvnizca: newBlobovnizca(), blobobvnizca: newBlobovnicza(),
metabase: newMetabaseMetrics(), metabase: newMetabaseMetrics(),
pilorama: newPiloramaMetrics(), pilorama: newPiloramaMetrics(),
grpc: newGrpcServerMetrics(), grpc: newGrpcServerMetrics(),