[#371] ir: Add morph cache metrics #400
11 changed files with 154 additions and 27 deletions
|
@ -469,11 +469,12 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<-
|
|||
}
|
||||
|
||||
morphChain := &chainParams{
|
||||
log: s.log,
|
||||
cfg: cfg,
|
||||
key: s.key,
|
||||
name: morphPrefix,
|
||||
from: fromSideChainBlock,
|
||||
log: s.log,
|
||||
cfg: cfg,
|
||||
key: s.key,
|
||||
name: morphPrefix,
|
||||
from: fromSideChainBlock,
|
||||
morphCacheMetric: s.metrics.MorphCacheMetrics(),
|
||||
}
|
||||
|
||||
// create morph client
|
||||
|
|
|
@ -102,12 +102,13 @@ type (
|
|||
}
|
||||
|
||||
chainParams struct {
|
||||
log *logger.Logger
|
||||
cfg *viper.Viper
|
||||
key *keys.PrivateKey
|
||||
name string
|
||||
sgn *transaction.Signer
|
||||
from uint32 // block height
|
||||
log *logger.Logger
|
||||
cfg *viper.Viper
|
||||
key *keys.PrivateKey
|
||||
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),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,10 @@ const (
|
|||
|
||||
// InnerRingServiceMetrics contains metrics collected by inner ring.
|
||||
type InnerRingServiceMetrics struct {
|
||||
epoch prometheus.Gauge
|
||||
health prometheus.Gauge
|
||||
eventDuration *prometheus.HistogramVec
|
||||
epoch prometheus.Gauge
|
||||
health prometheus.Gauge
|
||||
eventDuration *prometheus.HistogramVec
|
||||
morphCacheMetrics *morphCacheMetrics
|
||||
}
|
||||
|
||||
// NewInnerRingMetrics returns new instance of metrics collectors for inner ring.
|
||||
|
@ -45,9 +46,10 @@ func NewInnerRingMetrics() *InnerRingServiceMetrics {
|
|||
)
|
||||
|
||||
return &InnerRingServiceMetrics{
|
||||
epoch: epoch,
|
||||
health: health,
|
||||
eventDuration: eventDuration,
|
||||
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
77
pkg/metrics/morphcache.go
Normal 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})
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {}
|
||||
|
|
Loading…
Reference in a new issue