[#371] ir: Add morph cache metrics #400

Merged
fyrchik merged 1 commit from aarifullin/frostfs-node:feature/371-morph_cache_metr into master 2023-06-13 10:10:16 +00:00
11 changed files with 154 additions and 27 deletions

View file

@ -474,6 +474,7 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<-
key: s.key,
name: morphPrefix,
from: fromSideChainBlock,
morphCacheMetric: s.metrics.MorphCacheMetrics(),
}
// create morph client

View file

@ -108,6 +108,7 @@ type (
name string
sgn *transaction.Signer
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)
}),
client.WithSwitchInterval(p.cfg.GetDuration(p.name+".switch_interval")),
client.WithMorphCacheMetrics(p.morphCacheMetric),
)
}

View file

@ -19,6 +19,7 @@ type InnerRingServiceMetrics struct {
epoch prometheus.Gauge
health prometheus.Gauge
eventDuration *prometheus.HistogramVec
morphCacheMetrics *morphCacheMetrics
}
// NewInnerRingMetrics returns new instance of metrics collectors for inner ring.
@ -48,6 +49,7 @@ func NewInnerRingMetrics() *InnerRingServiceMetrics {
epoch: epoch,
health: health,
eventDuration: eventDuration,
morphCacheMetrics: newMorphCacheMetrics(),
}
}
@ -67,3 +69,7 @@ func (m InnerRingServiceMetrics) AddEvent(d time.Duration, typ string, success b
innerRingLabelSuccess: strconv.FormatBool(success),
}).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
import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree"
"git.frostfs.info/TrueCloudLab/frostfs-observability/metrics"
"github.com/prometheus/client_golang/prometheus"
)
@ -67,7 +66,7 @@ func (m *NodeMetrics) WriteCache() WriteCacheMetrics {
return m.writeCacheMetrics
}
func (m *NodeMetrics) TreeService() tree.MetricsRegister {
func (m *NodeMetrics) TreeService() TreeMetricsRegister {
return m.treeService
}

View file

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

View file

@ -10,6 +10,7 @@ import (
"time"
"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"
lru "github.com/hashicorp/golang-lru/v2"
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
@ -88,6 +89,8 @@ type cache struct {
nnsHash *util.Uint160
gKey *keys.PublicKey
txHeights *lru.Cache[util.Uint256, uint32]
metrics metrics.MorphCacheMetrics
}
func (c *cache) nns() *util.Uint160 {

View file

@ -7,6 +7,7 @@ import (
"time"
"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"
lru "github.com/hashicorp/golang-lru/v2"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
@ -42,6 +43,8 @@ type cfg struct {
inactiveModeCb Callback
switchInterval time.Duration
morphCacheMetrics metrics.MorphCacheMetrics
}
const (
@ -104,7 +107,7 @@ func New(ctx context.Context, key *keys.PrivateKey, opts ...Option) (*Client, er
}
cli := &Client{
cache: newClientCache(),
cache: newClientCache(cfg.morphCacheMetrics),
logger: cfg.logger,
acc: acc,
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
return cache{
txHeights: c,
metrics: morphCacheMetrics,
}
}
@ -282,3 +286,9 @@ func WithSwitchInterval(i time.Duration) Option {
c.switchInterval = i
}
}
func WithMorphCacheMetrics(morphCacheMetrics metrics.MorphCacheMetrics) Option {
return func(c *cfg) {
c.morphCacheMetrics = morphCacheMetrics
}
}

View file

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

View file

@ -8,6 +8,7 @@ import (
"math"
"math/big"
"strings"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"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) {
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 {
success = true
return rh, nil
}
height, err := c.client.GetTransactionHeight(h)
@ -797,5 +805,6 @@ func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) {
return 0, err
}
c.cache.txHeights.Add(h, height)
success = true
return height, nil
}

View file

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