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 {
cfg
dataSize atomic.Uint64
dataSize atomic.Uint64
itemsCount atomic.Uint64
boltDB *bbolt.DB

View file

@ -14,7 +14,7 @@ import (
// 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 blobovnizca is already open, does nothing.
// If blobovnicza is already open, does nothing.
func (b *Blobovnicza) Open() error {
b.controlMtx.Lock()
defer b.controlMtx.Unlock()
@ -45,7 +45,7 @@ func (b *Blobovnicza) Open() error {
b.boltDB, err = bbolt.Open(b.path, b.perm, b.boltOptions)
if err == nil {
b.opened = true
b.metrics.IncOpenBlobovnizcaCount()
b.metrics.IncOpenBlobovniczaCount()
}
return err
@ -54,13 +54,13 @@ func (b *Blobovnicza) Open() error {
// Init initializes internal database structure.
//
// 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 {
b.controlMtx.Lock()
defer b.controlMtx.Unlock()
if !b.opened {
return errors.New("blobovnizca is not open")
return errors.New("blobovnicza is not open")
}
b.log.Debug(logs.BlobovniczaInitializing,
@ -68,8 +68,10 @@ func (b *Blobovnicza) Init() error {
zap.Uint64("storage size limit", b.fullSizeLimit),
)
if size := b.dataSize.Load(); size != 0 {
b.log.Debug(logs.BlobovniczaAlreadyInitialized, zap.Uint64("size", size))
size := b.dataSize.Load()
items := b.itemsCount.Load()
if size != 0 || items != 0 {
b.log.Debug(logs.BlobovniczaAlreadyInitialized, zap.Uint64("size", size), zap.Uint64("items", items))
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 items uint64
err := b.boltDB.View(func(tx *bbolt.Tx) 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
})
})
@ -111,13 +116,15 @@ func (b *Blobovnicza) initializeSize() error {
return fmt.Errorf("can't determine DB size: %w", err)
}
b.dataSize.Store(size)
b.metrics.AddOpenBlobovnizcaSize(size)
b.itemsCount.Store(items)
b.metrics.AddOpenBlobovniczaSize(size)
b.metrics.AddOpenBlobovniczaItems(items)
return nil
}
// 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 {
b.controlMtx.Lock()
defer b.controlMtx.Unlock()
@ -134,9 +141,11 @@ func (b *Blobovnicza) Close() error {
return err
}
b.metrics.DecOpenBlobovnizcaCount()
b.metrics.SubOpenBlobovnizcaSize(b.dataSize.Load())
b.metrics.DecOpenBlobovniczaCount()
b.metrics.SubOpenBlobovniczaSize(b.dataSize.Load())
b.metrics.SubOpenBlobovniczaItems(b.itemsCount.Load())
b.dataSize.Store(0)
b.itemsCount.Store(0)
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("range", stringifyBounds(sizeLowerBound, sizeUpperBound)),
)
b.decSize(sizeUpperBound)
b.itemDeleted(sizeUpperBound)
}
return DeleteRes{}, err

View file

@ -1,16 +1,21 @@
package blobovnicza
type Metrics interface {
IncOpenBlobovnizcaCount()
DecOpenBlobovnizcaCount()
IncOpenBlobovniczaCount()
DecOpenBlobovniczaCount()
AddOpenBlobovnizcaSize(size uint64)
SubOpenBlobovnizcaSize(size uint64)
AddOpenBlobovniczaSize(size uint64)
SubOpenBlobovniczaSize(size uint64)
AddOpenBlobovniczaItems(items uint64)
SubOpenBlobovniczaItems(items uint64)
}
type NoopMetrics struct{}
func (m *NoopMetrics) IncOpenBlobovnizcaCount() {}
func (m *NoopMetrics) DecOpenBlobovnizcaCount() {}
func (m *NoopMetrics) AddOpenBlobovnizcaSize(uint64) {}
func (m *NoopMetrics) SubOpenBlobovnizcaSize(uint64) {}
func (m *NoopMetrics) IncOpenBlobovniczaCount() {}
func (m *NoopMetrics) DecOpenBlobovniczaCount() {}
func (m *NoopMetrics) AddOpenBlobovniczaSize(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
})
if err == nil {
b.incSize(upperBound)
b.itemAdded(upperBound)
}
return PutRes{}, err

View file

@ -3,6 +3,7 @@ package blobovnicza
import (
"encoding/binary"
"fmt"
"math"
"math/bits"
"strconv"
)
@ -40,14 +41,18 @@ func upperPowerOfTwo(v uint64) uint64 {
return 1 << bits.Len64(v-1)
}
func (b *Blobovnicza) incSize(sz uint64) {
b.dataSize.Add(sz)
b.metrics.AddOpenBlobovnizcaSize(sz)
func (b *Blobovnicza) itemAdded(itemSize uint64) {
b.dataSize.Add(itemSize)
b.itemsCount.Add(1)
b.metrics.AddOpenBlobovniczaSize(itemSize)
b.metrics.AddOpenBlobovniczaItems(1)
}
func (b *Blobovnicza) decSize(sz uint64) {
b.dataSize.Add(^(sz - 1))
b.metrics.SubOpenBlobovnizcaSize(sz)
func (b *Blobovnicza) itemDeleted(itemSize uint64) {
b.dataSize.Add(^(itemSize - 1))
b.itemsCount.Add(math.MaxUint64)
b.metrics.SubOpenBlobovniczaSize(itemSize)
b.metrics.SubOpenBlobovniczaItems(1)
}
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")
// NewBlobovniczaTree returns new instance of blobovnizas tree.
// NewBlobovniczaTree returns new instance of blobovniczas tree.
func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) {
blz = new(Blobovniczas)
initConfig(&blz.cfg)

View file

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

View file

@ -7,7 +7,7 @@ import (
)
type Metrics interface {
Blobovnizca() blobovnicza.Metrics
Blobovnicza() blobovnicza.Metrics
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) Iterate(time.Duration, bool) {}
func (m *noopMetrics) Put(time.Duration, int, bool) {}
func (m *noopMetrics) Blobovnizca() blobovnicza.Metrics {
func (m *noopMetrics) Blobovnicza() blobovnicza.Metrics {
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)
raw1 := testutil.GenerateObject()

View file

@ -22,7 +22,7 @@ type blobovniczaTreeMetrics struct {
m metrics_impl.BlobobvnizcaMetrics
}
func (m *blobovniczaTreeMetrics) Blobovnizca() blobovnicza.Metrics {
func (m *blobovniczaTreeMetrics) Blobovnicza() blobovnicza.Metrics {
return &blobovniczaMetrics{
shardID: func() string { return m.shardID },
path: m.path,
@ -81,18 +81,26 @@ type blobovniczaMetrics struct {
path string
}
func (m *blobovniczaMetrics) AddOpenBlobovnizcaSize(size uint64) {
m.m.AddOpenBlobovnizcaSize(m.shardID(), m.path, size)
func (m *blobovniczaMetrics) AddOpenBlobovniczaSize(size uint64) {
m.m.AddOpenBlobovniczaSize(m.shardID(), m.path, size)
}
func (m *blobovniczaMetrics) SubOpenBlobovnizcaSize(size uint64) {
m.m.SubOpenBlobovnizcaSize(m.shardID(), m.path, size)
func (m *blobovniczaMetrics) SubOpenBlobovniczaSize(size uint64) {
m.m.SubOpenBlobovniczaSize(m.shardID(), m.path, size)
}
func (m *blobovniczaMetrics) IncOpenBlobovnizcaCount() {
m.m.IncOpenBlobovnizcaCount(m.shardID(), m.path)
func (m *blobovniczaMetrics) IncOpenBlobovniczaCount() {
m.m.IncOpenBlobovniczaCount(m.shardID(), m.path)
}
func (m *blobovniczaMetrics) DecOpenBlobovnizcaCount() {
m.m.DecOpenBlobovnizcaCount(m.shardID(), m.path)
func (m *blobovniczaMetrics) DecOpenBlobovniczaCount() {
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)
AddBlobobvnizcaTreeGet(shardID, path string, size int)
AddOpenBlobovnizcaSize(shardID, path string, size uint64)
SubOpenBlobovnizcaSize(shardID, path string, size uint64)
AddOpenBlobovniczaSize(shardID, path string, size uint64)
SubOpenBlobovniczaSize(shardID, path string, size uint64)
IncOpenBlobovnizcaCount(shardID, path string)
DecOpenBlobovnizcaCount(shardID, path string)
AddOpenBlobovniczaItems(shardID, path string, items uint64)
SubOpenBlobovniczaItems(shardID, path string, items uint64)
IncOpenBlobovniczaCount(shardID, path string)
DecOpenBlobovniczaCount(shardID, path string)
}
type blobovnizca struct {
type blobovnicza struct {
treeMode *shardIDPathModeValue
treeReqDuration *prometheus.HistogramVec
treePut *prometheus.CounterVec
treeGet *prometheus.CounterVec
treeOpenSize *prometheus.GaugeVec
treeOpenItems *prometheus.GaugeVec
treeOpenCounter *prometheus.GaugeVec
}
func newBlobovnizca() *blobovnizca {
return &blobovnizca{
treeMode: newShardIDPathMode(blobovniczaTreeSubSystem, "mode", "Blobovnizca tree mode"),
func newBlobovnicza() *blobovnicza {
return &blobovnicza{
treeMode: newShardIDPathMode(blobovniczaTreeSubSystem, "mode", "Blobovnicza tree mode"),
treeReqDuration: metrics.NewHistogramVec(prometheus.HistogramOpts{
Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem,
Name: "request_duration_seconds",
Help: "Accumulated Blobovnizca tree request process duration",
Help: "Accumulated Blobovnicza tree request process duration",
}, []string{shardIDLabel, pathLabel, successLabel, methodLabel, withStorageIDLabel}),
treePut: metrics.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem,
Name: "put_bytes",
Help: "Accumulated payload size written to Blobovnizca tree",
Help: "Accumulated payload size written to Blobovnicza tree",
}, []string{shardIDLabel, pathLabel}),
treeGet: metrics.NewCounterVec(prometheus.CounterOpts{
Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem,
Name: "get_bytes",
Help: "Accumulated payload size read from Blobovnizca tree",
Help: "Accumulated payload size read from Blobovnicza tree",
}, []string{shardIDLabel, pathLabel}),
treeOpenSize: metrics.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem,
Name: "open_blobovnizca_size_bytes",
Help: "Size of opened blobovnizcas of Blobovnizca tree",
Name: "open_blobovnicza_size_bytes",
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}),
treeOpenCounter: metrics.NewGaugeVec(prometheus.GaugeOpts{
Namespace: namespace,
Subsystem: blobovniczaTreeSubSystem,
Name: "open_blobovnizca_count",
Help: "Count of opened blobovnizcas of Blobovnizca tree",
Name: "open_blobovnicza_count",
Help: "Count of opened blobovniczas of Blobovnicza tree",
}, []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))
}
func (b *blobovnizca) CloseBlobobvnizcaTree(shardID, path string) {
func (b *blobovnicza) CloseBlobobvnizcaTree(shardID, path string) {
b.treeMode.SetMode(shardID, path, closedMode)
b.treeReqDuration.DeletePartialMatch(prometheus.Labels{
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{
shardIDLabel: shardID,
pathLabel: path,
@ -98,44 +108,58 @@ func (b *blobovnizca) BlobobvnizcaTreeMethodDuration(shardID, path string, metho
}).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{
shardIDLabel: shardID,
pathLabel: path,
}).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{
shardIDLabel: shardID,
pathLabel: path,
}).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{
shardIDLabel: shardID,
pathLabel: path,
}).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{
shardIDLabel: shardID,
pathLabel: path,
}).Sub(float64(size))
}
func (b *blobovnizca) IncOpenBlobovnizcaCount(shardID, path string) {
func (b *blobovnicza) IncOpenBlobovniczaCount(shardID, path string) {
b.treeOpenCounter.With(prometheus.Labels{
shardIDLabel: shardID,
pathLabel: path,
}).Inc()
}
func (b *blobovnizca) DecOpenBlobovnizcaCount(shardID, path string) {
func (b *blobovnicza) DecOpenBlobovniczaCount(shardID, path string) {
b.treeOpenCounter.With(prometheus.Labels{
shardIDLabel: shardID,
pathLabel: path,
}).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
fstree *fstreeMetrics
blobstore *blobstoreMetrics
blobobvnizca *blobovnizca
blobobvnizca *blobovnicza
metabase *metabaseMetrics
pilorama *piloramaMetrics
grpc *grpcServerMetrics
@ -35,7 +35,7 @@ func NewNodeMetrics() *NodeMetrics {
}),
fstree: newFSTreeMetrics(),
blobstore: newBlobstoreMetrics(),
blobobvnizca: newBlobovnizca(),
blobobvnizca: newBlobovnicza(),
metabase: newMetabaseMetrics(),
pilorama: newPiloramaMetrics(),
grpc: newGrpcServerMetrics(),