[#371] ir: Add morph cache metrics

Signed-off-by: Airat Arifullin a.arifullin@yadro.com
This commit is contained in:
Airat Arifullin 2023-05-26 12:15:50 +03:00 committed by Evgenii Stratonikov
parent 4f83ab0fb4
commit 90e9247b69
11 changed files with 154 additions and 27 deletions

View file

@ -469,11 +469,12 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<-
} }
morphChain := &chainParams{ morphChain := &chainParams{
log: s.log, log: s.log,
cfg: cfg, cfg: cfg,
key: s.key, key: s.key,
name: morphPrefix, name: morphPrefix,
from: fromSideChainBlock, from: fromSideChainBlock,
morphCacheMetric: s.metrics.MorphCacheMetrics(),
} }
// create morph client // create morph client

View file

@ -102,12 +102,13 @@ type (
} }
chainParams struct { chainParams struct {
log *logger.Logger log *logger.Logger
cfg *viper.Viper cfg *viper.Viper
key *keys.PrivateKey key *keys.PrivateKey
name string name string
sgn *transaction.Signer sgn *transaction.Signer
from uint32 // block height from uint32 // block height
morphCacheMetric metrics.MorphCacheMetrics
} }
) )
@ -465,6 +466,7 @@ func createClient(ctx context.Context, p *chainParams, errChan chan<- error) (*c
errChan <- fmt.Errorf("%s chain connection has been lost", p.name) errChan <- fmt.Errorf("%s chain connection has been lost", p.name)
}), }),
client.WithSwitchInterval(p.cfg.GetDuration(p.name+".switch_interval")), client.WithSwitchInterval(p.cfg.GetDuration(p.name+".switch_interval")),
client.WithMorphCacheMetrics(p.morphCacheMetric),
) )
} }

View file

@ -16,9 +16,10 @@ const (
// InnerRingServiceMetrics contains metrics collected by inner ring. // InnerRingServiceMetrics contains metrics collected by inner ring.
type InnerRingServiceMetrics struct { type InnerRingServiceMetrics struct {
epoch prometheus.Gauge epoch prometheus.Gauge
health prometheus.Gauge health prometheus.Gauge
eventDuration *prometheus.HistogramVec eventDuration *prometheus.HistogramVec
morphCacheMetrics *morphCacheMetrics
} }
// NewInnerRingMetrics returns new instance of metrics collectors for inner ring. // NewInnerRingMetrics returns new instance of metrics collectors for inner ring.
@ -45,9 +46,10 @@ func NewInnerRingMetrics() *InnerRingServiceMetrics {
) )
return &InnerRingServiceMetrics{ return &InnerRingServiceMetrics{
epoch: epoch, epoch: epoch,
health: health, health: health,
eventDuration: eventDuration, eventDuration: eventDuration,
morphCacheMetrics: newMorphCacheMetrics(),
} }
} }
@ -67,3 +69,7 @@ func (m InnerRingServiceMetrics) AddEvent(d time.Duration, typ string, success b
innerRingLabelSuccess: strconv.FormatBool(success), innerRingLabelSuccess: strconv.FormatBool(success),
}).Observe(d.Seconds()) }).Observe(d.Seconds())
} }
func (m InnerRingServiceMetrics) MorphCacheMetrics() MorphCacheMetrics {
return m.morphCacheMetrics
}

77
pkg/metrics/morphcache.go Normal file
View file

@ -0,0 +1,77 @@
package metrics
import (
"fmt"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-observability/metrics"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/prometheus/client_golang/prometheus"
)
const (
mcSubsystem = "morphcache"
mcSuccess = "success"
)
type MorphCacheMetrics interface {
AddNNSContractHashDuration(success bool, d time.Duration)
AddGroupKeyDuration(success bool, d time.Duration)
AddTxHeightDuration(hash util.Uint256, success bool, d time.Duration)
}
type morphCacheMetrics struct {
// Duration of processing get nns contract hash request
nnsContractHashDuration *prometheus.HistogramVec
// Duration of processing get group key request
groupKeyDuration *prometheus.HistogramVec
// Duration of processing get tx height request
txHeightDuration *prometheus.HistogramVec
}
var _ MorphCacheMetrics = (*morphCacheMetrics)(nil)
func newMorphCacheMetrics() *morphCacheMetrics {
return &morphCacheMetrics{
nnsContractHashDuration: newMCMethodDurationCounter("nns_contract_hash"),
groupKeyDuration: newMCMethodDurationCounter("group_key"),
txHeightDuration: newMCMethodDurationCounter("tx_height"),
}
}
func (m *morphCacheMetrics) AddNNSContractHashDuration(success bool, d time.Duration) {
m.nnsContractHashDuration.With(
prometheus.Labels{
mcSuccess: fmt.Sprintf("%v", success),
},
).Observe(float64(d))
}
func (m *morphCacheMetrics) AddGroupKeyDuration(success bool, d time.Duration) {
m.groupKeyDuration.With(
prometheus.Labels{
mcSuccess: fmt.Sprintf("%v", success),
},
).Observe(float64(d))
}
func (m *morphCacheMetrics) AddTxHeightDuration(hash util.Uint256, success bool, d time.Duration) {
m.txHeightDuration.With(
prometheus.Labels{
mcSuccess: fmt.Sprintf("%v", success),
},
).Observe(float64(d))
}
func newMCMethodDurationCounter(method string) *prometheus.HistogramVec {
return metrics.NewHistogramVec(prometheus.HistogramOpts{
Namespace: namespace,
Subsystem: mcSubsystem,
Name: fmt.Sprintf("%s_req_duration_seconds", method),
Help: fmt.Sprintf("Accumulated %s request process duration", method),
}, []string{mcSuccess})
}

View file

@ -1,7 +1,6 @@
package metrics package metrics
import ( import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree"
"git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
@ -67,7 +66,7 @@ func (m *NodeMetrics) WriteCache() WriteCacheMetrics {
return m.writeCacheMetrics return m.writeCacheMetrics
} }
func (m *NodeMetrics) TreeService() tree.MetricsRegister { func (m *NodeMetrics) TreeService() TreeMetricsRegister {
return m.treeService return m.treeService
} }

View file

@ -10,12 +10,20 @@ import (
const treeServiceLabelSuccess = "success" const treeServiceLabelSuccess = "success"
type TreeMetricsRegister interface {
AddReplicateTaskDuration(time.Duration, bool)
AddReplicateWaitDuration(time.Duration, bool)
AddSyncDuration(time.Duration, bool)
}
type treeServiceMetrics struct { type treeServiceMetrics struct {
replicateTaskDuration *prometheus.HistogramVec replicateTaskDuration *prometheus.HistogramVec
replicateWaitDuration *prometheus.HistogramVec replicateWaitDuration *prometheus.HistogramVec
syncOpDuration *prometheus.HistogramVec syncOpDuration *prometheus.HistogramVec
} }
var _ TreeMetricsRegister = (*treeServiceMetrics)(nil)
func newTreeServiceMetrics() *treeServiceMetrics { func newTreeServiceMetrics() *treeServiceMetrics {
const treeServiceSubsystem = "treeservice" const treeServiceSubsystem = "treeservice"
return &treeServiceMetrics{ return &treeServiceMetrics{

View file

@ -10,6 +10,7 @@ import (
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
lru "github.com/hashicorp/golang-lru/v2" lru "github.com/hashicorp/golang-lru/v2"
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
@ -88,6 +89,8 @@ type cache struct {
nnsHash *util.Uint160 nnsHash *util.Uint160
gKey *keys.PublicKey gKey *keys.PublicKey
txHeights *lru.Cache[util.Uint256, uint32] txHeights *lru.Cache[util.Uint256, uint32]
metrics metrics.MorphCacheMetrics
} }
func (c *cache) nns() *util.Uint160 { func (c *cache) nns() *util.Uint160 {

View file

@ -7,6 +7,7 @@ import (
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
lru "github.com/hashicorp/golang-lru/v2" lru "github.com/hashicorp/golang-lru/v2"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -42,6 +43,8 @@ type cfg struct {
inactiveModeCb Callback inactiveModeCb Callback
switchInterval time.Duration switchInterval time.Duration
morphCacheMetrics metrics.MorphCacheMetrics
} }
const ( const (
@ -104,7 +107,7 @@ func New(ctx context.Context, key *keys.PrivateKey, opts ...Option) (*Client, er
} }
cli := &Client{ cli := &Client{
cache: newClientCache(), cache: newClientCache(cfg.morphCacheMetrics),
logger: cfg.logger, logger: cfg.logger,
acc: acc, acc: acc,
accAddr: accAddr, accAddr: accAddr,
@ -195,10 +198,11 @@ func newActor(ws *rpcclient.WSClient, acc *wallet.Account, cfg cfg) (*actor.Acto
}}) }})
} }
func newClientCache() cache { func newClientCache(morphCacheMetrics metrics.MorphCacheMetrics) cache {
c, _ := lru.New[util.Uint256, uint32](100) // returns error only if size is negative c, _ := lru.New[util.Uint256, uint32](100) // returns error only if size is negative
return cache{ return cache{
txHeights: c, txHeights: c,
metrics: morphCacheMetrics,
} }
} }
@ -282,3 +286,9 @@ func WithSwitchInterval(i time.Duration) Option {
c.switchInterval = i c.switchInterval = i
} }
} }
func WithMorphCacheMetrics(morphCacheMetrics metrics.MorphCacheMetrics) Option {
return func(c *cfg) {
c.morphCacheMetrics = morphCacheMetrics
}
}

View file

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"strconv" "strconv"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -81,6 +82,13 @@ func (c *Client) NNSHash() (util.Uint160, error) {
return util.Uint160{}, ErrConnectionLost return util.Uint160{}, ErrConnectionLost
} }
success := false
startedAt := time.Now()
defer func() {
c.cache.metrics.AddNNSContractHashDuration(success, time.Since(startedAt))
}()
nnsHash := c.cache.nns() nnsHash := c.cache.nns()
if nnsHash == nil { if nnsHash == nil {
@ -92,6 +100,7 @@ func (c *Client) NNSHash() (util.Uint160, error) {
c.cache.setNNSHash(cs.Hash) c.cache.setNNSHash(cs.Hash)
nnsHash = &cs.Hash nnsHash = &cs.Hash
} }
success = true
return *nnsHash, nil return *nnsHash, nil
} }
@ -221,7 +230,14 @@ func (c *Client) SetGroupSignerScope() error {
// contractGroupKey returns public key designating FrostFS contract group. // contractGroupKey returns public key designating FrostFS contract group.
func (c *Client) contractGroupKey() (*keys.PublicKey, error) { func (c *Client) contractGroupKey() (*keys.PublicKey, error) {
success := false
startedAt := time.Now()
defer func() {
c.cache.metrics.AddGroupKeyDuration(success, time.Since(startedAt))
}()
if gKey := c.cache.groupKey(); gKey != nil { if gKey := c.cache.groupKey(); gKey != nil {
success = true
return gKey, nil return gKey, nil
} }
@ -251,5 +267,7 @@ func (c *Client) contractGroupKey() (*keys.PublicKey, error) {
} }
c.cache.setGroupKey(pub) c.cache.setGroupKey(pub)
success = true
return pub, nil return pub, nil
} }

View file

@ -8,6 +8,7 @@ import (
"math" "math"
"math/big" "math/big"
"strings" "strings"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand"
@ -789,7 +790,14 @@ func (c *Client) calculateNonceAndVUB(hash util.Uint256, roundBlockHeight bool)
} }
func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) { func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) {
success := false
startedAt := time.Now()
defer func() {
c.cache.metrics.AddTxHeightDuration(h, success, time.Since(startedAt))
}()
if rh, ok := c.cache.txHeights.Get(h); ok { if rh, ok := c.cache.txHeights.Get(h); ok {
success = true
return rh, nil return rh, nil
} }
height, err := c.client.GetTransactionHeight(h) height, err := c.client.GetTransactionHeight(h)
@ -797,5 +805,6 @@ func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) {
return 0, err return 0, err
} }
c.cache.txHeights.Add(h, height) c.cache.txHeights.Add(h, height)
success = true
return height, nil return height, nil
} }

View file

@ -2,12 +2,6 @@ package tree
import "time" import "time"
type MetricsRegister interface {
AddReplicateTaskDuration(time.Duration, bool)
AddReplicateWaitDuration(time.Duration, bool)
AddSyncDuration(time.Duration, bool)
}
type defaultMetricsRegister struct{} type defaultMetricsRegister struct{}
func (defaultMetricsRegister) AddReplicateTaskDuration(time.Duration, bool) {} func (defaultMetricsRegister) AddReplicateTaskDuration(time.Duration, bool) {}