Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions tests/reexecute/c/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package vm

import (
"fmt"
"testing"
"time"

"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
)

type metricKind uint

const (
counter metricKind = iota + 1
gauge
)

var (
gasMetric = topLevelMetric{
name: "gas",
query: "avalanche_evm_eth_chain_block_gas_used_processed",
kind: counter,
}
meterVMMetrics = []topLevelMetric{
{
name: "block_parse",
query: "avalanche_meterchainvm_parse_block_sum",
kind: gauge,
},
{
name: "block_verify",
query: "avalanche_meterchainvm_verify_sum",
kind: gauge,
},
{
name: "block_accept",
query: "avalanche_meterchainvm_accept_sum",
kind: gauge,
},
}
)

func getMetricValue(registry prometheus.Gatherer, metric topLevelMetric) (float64, error) {
metricFamilies, err := registry.Gather()
if err != nil {
return 0, fmt.Errorf("failed to gather metrics: %w", err)
}

query := metric.query
for _, mf := range metricFamilies {
switch metric.kind {
case counter:
if mf.GetName() == query {
return mf.GetMetric()[0].Counter.GetValue(), nil
}
case gauge:
if mf.GetName() == query {
return mf.GetMetric()[0].Gauge.GetValue(), nil
}
default:
return 0, fmt.Errorf("metric type unknown: %d", metric.kind)
}
}

return 0, fmt.Errorf("metric %s not found", query)
}

type topLevelMetric struct {
name string
query string
kind metricKind
}

func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time.Duration) {
r := require.New(b)

totalGas, err := getMetricValue(registry, gasMetric)
r.NoError(err)
r.NotZero(totalGas, "denominator metric %q has value 0", gasMetric.name)

var (
mgas float64 = 1_000_000
ggas float64 = 1_000_000_000
nsPerMs float64 = 1_000_000
)

mgasPerSecond := (totalGas / mgas) / elapsed.Seconds()
b.ReportMetric(mgasPerSecond, "mgas/s")

totalGGas := totalGas / ggas
msPerGGas := (float64(elapsed) / nsPerMs) / totalGGas
b.ReportMetric(msPerGGas, "ms/ggas")

for _, metric := range meterVMMetrics {
metricVal, err := getMetricValue(registry, metric)
r.NoError(err)

metricValMS := (metricVal / nsPerMs) / totalGGas
b.ReportMetric(metricValMS, metric.name+"_ms/ggas")
}
}
36 changes: 10 additions & 26 deletions tests/reexecute/c/vm_reexecute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import (
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/timer"
"github.com/ava-labs/avalanchego/utils/units"
"github.com/ava-labs/avalanchego/vms/metervm"
"github.com/ava-labs/avalanchego/vms/platformvm/warp"
)

Expand Down Expand Up @@ -171,6 +172,9 @@ func benchmarkReexecuteRange(
vmMultiGatherer := metrics.NewPrefixGatherer()
r.NoError(prefixGatherer.Register("avalanche_evm", vmMultiGatherer))

meterVMRegistry := prometheus.NewRegistry()
r.NoError(prefixGatherer.Register("avalanche_meterchainvm", meterVMRegistry))

// consensusRegistry includes the chain="C" label and the prefix "avalanche_snowman".
// The consensus registry is passed to the executor to mimic a subset of consensus metrics.
consensusRegistry := prometheus.NewRegistry()
Expand Down Expand Up @@ -214,6 +218,7 @@ func benchmarkReexecuteRange(
chainDataDir,
configBytes,
vmMultiGatherer,
meterVMRegistry,
)
r.NoError(err)
defer func() {
Expand Down Expand Up @@ -244,7 +249,8 @@ func newMainnetCChainVM(
vmAndSharedMemoryDB database.Database,
chainDataDir string,
configBytes []byte,
metricsGatherer metrics.MultiGatherer,
vmMultiGatherer metrics.MultiGatherer,
meterVMRegistry prometheus.Registerer,
) (block.ChainVM, error) {
factory := factory.Factory{}
vmIntf, err := factory.New(logging.NoLog{})
Expand Down Expand Up @@ -272,6 +278,8 @@ func newMainnetCChainVM(
ids.Empty: constants.PrimaryNetworkID,
}

vm = metervm.NewBlockVM(vm, meterVMRegistry)

if err := vm.Initialize(
ctx,
&snow.Context{
Expand All @@ -289,7 +297,7 @@ func newMainnetCChainVM(
Log: tests.NewDefaultLogger("mainnet-vm-reexecution"),
SharedMemory: atomicMemory.NewSharedMemory(mainnetCChainID),
BCLookup: ids.NewAliaser(),
Metrics: metricsGatherer,
Metrics: vmMultiGatherer,

WarpSigner: warpSigner,

Expand Down Expand Up @@ -600,27 +608,3 @@ func parseCustomLabels(labelsStr string) (map[string]string, error) {
}
return labels, nil
}

func getTopLevelMetrics(b *testing.B, registry prometheus.Gatherer, elapsed time.Duration) {
r := require.New(b)

gasUsed, err := getCounterMetricValue(registry, "avalanche_evm_eth_chain_block_gas_used_processed")
r.NoError(err)
mgasPerSecond := gasUsed / 1_000_000 / elapsed.Seconds()
b.ReportMetric(mgasPerSecond, "mgas/s")
}

func getCounterMetricValue(registry prometheus.Gatherer, query string) (float64, error) {
metricFamilies, err := registry.Gather()
if err != nil {
return 0, fmt.Errorf("failed to gather metrics: %w", err)
}

for _, mf := range metricFamilies {
if mf.GetName() == query {
return mf.GetMetric()[0].Counter.GetValue(), nil
}
}

return 0, fmt.Errorf("metric %s not found", query)
}