Skip to content

Commit

Permalink
initialize x/metrics with metrics collection
Browse files Browse the repository at this point in the history
  • Loading branch information
pirtleshell committed Aug 24, 2023
1 parent b01062a commit 9368851
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 2 deletions.
8 changes: 8 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ import (
"github.com/kava-labs/kava/x/liquid"
liquidkeeper "github.com/kava-labs/kava/x/liquid/keeper"
liquidtypes "github.com/kava-labs/kava/x/liquid/types"
metrics "github.com/kava-labs/kava/x/metrics"
metricstypes "github.com/kava-labs/kava/x/metrics/types"
pricefeed "github.com/kava-labs/kava/x/pricefeed"
pricefeedkeeper "github.com/kava-labs/kava/x/pricefeed/keeper"
pricefeedtypes "github.com/kava-labs/kava/x/pricefeed/types"
Expand Down Expand Up @@ -216,6 +218,7 @@ var (
router.AppModuleBasic{},
mint.AppModuleBasic{},
community.AppModuleBasic{},
metrics.AppModuleBasic{},
)

// module account permissions
Expand Down Expand Up @@ -261,6 +264,7 @@ type Options struct {
MempoolAuthAddresses []sdk.AccAddress
EVMTrace string
EVMMaxGasWanted uint64
TelemetryOptions metricstypes.TelemetryOptions
}

// DefaultOptions is a sensible default Options value.
Expand Down Expand Up @@ -790,10 +794,12 @@ func NewApp(
// nil InflationCalculationFn, use SDK's default inflation function
mint.NewAppModule(appCodec, app.mintKeeper, app.accountKeeper, nil),
community.NewAppModule(app.communityKeeper, app.accountKeeper),
metrics.NewAppModule(options.TelemetryOptions),
)

// Warning: Some begin blockers must run before others. Ensure the dependencies are understood before modifying this list.
app.mm.SetOrderBeginBlockers(
metricstypes.ModuleName,
// Upgrade begin blocker runs migrations on the first block after an upgrade. It should run before any other module.
upgradetypes.ModuleName,
// Capability begin blocker runs non state changing initialization.
Expand Down Expand Up @@ -882,6 +888,7 @@ func NewApp(
routertypes.ModuleName,
minttypes.ModuleName,
communitytypes.ModuleName,
metricstypes.ModuleName,
)

// Warning: Some init genesis methods must run before others. Ensure the dependencies are understood before modifying this list
Expand Down Expand Up @@ -923,6 +930,7 @@ func NewApp(
validatorvestingtypes.ModuleName,
liquidtypes.ModuleName,
routertypes.ModuleName,
metricstypes.ModuleName,
)

app.mm.RegisterInvariants(&app.crisisKeeper)
Expand Down
2 changes: 2 additions & 0 deletions cmd/kava/cmd/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/app/params"
metricstypes "github.com/kava-labs/kava/x/metrics/types"
)

const (
Expand Down Expand Up @@ -99,6 +100,7 @@ func (ac appCreator) newApp(
MempoolAuthAddresses: mempoolAuthAddresses,
EVMTrace: cast.ToString(appOpts.Get(ethermintflags.EVMTracer)),
EVMMaxGasWanted: cast.ToUint64(appOpts.Get(ethermintflags.EVMMaxTxGasWanted)),
TelemetryOptions: metricstypes.TelemetryOptionsFromAppOpts(appOpts),
},
baseapp.SetPruning(pruningOpts),
baseapp.SetMinGasPrices(strings.Replace(cast.ToString(appOpts.Get(server.FlagMinGasPrices)), ";", ",", -1)),
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ require (
github.com/cosmos/ibc-go/v6 v6.1.1
github.com/ethereum/go-ethereum v1.10.26
github.com/evmos/ethermint v0.21.0
github.com/go-kit/kit v0.12.0
github.com/gogo/protobuf v1.3.3
github.com/golang/protobuf v1.5.3
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/linxGnu/grocksdb v1.8.0
github.com/pelletier/go-toml/v2 v2.0.6
github.com/prometheus/client_golang v1.14.0
github.com/spf13/cast v1.5.0
github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.15.0
Expand Down Expand Up @@ -85,7 +87,6 @@ require (
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
github.com/gin-gonic/gin v1.8.1 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
Expand Down Expand Up @@ -148,7 +149,6 @@ require (
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.40.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
Expand Down
11 changes: 11 additions & 0 deletions x/metrics/abci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package metrics

import (
"github.com/kava-labs/kava/x/metrics/types"

sdk "github.com/cosmos/cosmos-sdk/types"
)

func BeginBlocker(ctx sdk.Context, metrics *types.Metrics) {
metrics.LatestBlockHeight.Set(float64(ctx.BlockHeight()))
}
125 changes: 125 additions & 0 deletions x/metrics/module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package metrics

import (
"encoding/json"

"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"

abci "github.com/tendermint/tendermint/abci/types"

"github.com/kava-labs/kava/x/metrics/types"
)

var (
_ module.AppModule = AppModule{}
_ module.AppModuleBasic = AppModuleBasic{}
)

// AppModuleBasic app module basics object
type AppModuleBasic struct{}

// Name returns the module name
func (AppModuleBasic) Name() string {
return types.ModuleName
}

// RegisterLegacyAminoCodec register module codec
// Deprecated: unused but necessary to fulfill AppModuleBasic interface
func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {}

// DefaultGenesis default genesis state
func (AppModuleBasic) DefaultGenesis(_ codec.JSONCodec) json.RawMessage {
return []byte("{}")
}

// ValidateGenesis module validate genesis
func (AppModuleBasic) ValidateGenesis(_ codec.JSONCodec, _ client.TxEncodingConfig, _ json.RawMessage) error {
return nil
}

// RegisterInterfaces implements InterfaceModule.RegisterInterfaces
func (a AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {}

// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the module.
func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {}

// GetTxCmd returns the root tx command for the module.
func (AppModuleBasic) GetTxCmd() *cobra.Command {
return nil
}

// GetQueryCmd returns no root query command for the module.
func (AppModuleBasic) GetQueryCmd() *cobra.Command {
return nil
}

//____________________________________________________________________________

// AppModule app module type
type AppModule struct {
AppModuleBasic
metrics *types.Metrics
}

// NewAppModule creates a new AppModule object
func NewAppModule(telemetryOpts types.TelemetryOptions) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
metrics: types.NewMetrics(telemetryOpts),
}
}

// Name module name
func (am AppModule) Name() string {
return am.AppModuleBasic.Name()
}

// RegisterInvariants register module invariants
func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}

// Route module message route name
// Deprecated: unused but necessary to fulfill AppModule interface
func (am AppModule) Route() sdk.Route { return sdk.Route{} }

// QuerierRoute module querier route name
// Deprecated: unused but necessary to fulfill AppModule interface
func (AppModule) QuerierRoute() string { return types.ModuleName }

// LegacyQuerierHandler returns no sdk.Querier.
// Deprecated: unused but necessary to fulfill AppModule interface
func (am AppModule) LegacyQuerierHandler(_ *codec.LegacyAmino) sdk.Querier {
return nil
}

// ConsensusVersion implements AppModule/ConsensusVersion.
func (AppModule) ConsensusVersion() uint64 { return 1 }

// RegisterServices registers module services.
func (am AppModule) RegisterServices(cfg module.Configurator) {}

// InitGenesis module init-genesis
func (am AppModule) InitGenesis(ctx sdk.Context, _ codec.JSONCodec, _ json.RawMessage) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

// ExportGenesis module export genesis
func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONCodec) json.RawMessage {
return nil
}

// BeginBlock module begin-block
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
BeginBlocker(ctx, am.metrics)
}

// EndBlock module end-block
func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}
9 changes: 9 additions & 0 deletions x/metrics/types/keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package types

const (
// Name of the module
ModuleName = "metrics"

// Name of the CometBFT metrics namespace. Used to emulate future cometBFT metrics.
CometBFTMetricNamespace = "cometbft"
)
81 changes: 81 additions & 0 deletions x/metrics/types/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package types

import (
"github.com/go-kit/kit/metrics"
"github.com/go-kit/kit/metrics/discard"
prometheus "github.com/go-kit/kit/metrics/prometheus"
stdprometheus "github.com/prometheus/client_golang/prometheus"
"github.com/spf13/cast"

servertypes "github.com/cosmos/cosmos-sdk/server/types"
)

// TelemetryOptions defines the app configurations for the x/metrics module
type TelemetryOptions struct {
// CometBFT config value for instrumentation.prometheus (config.toml)
PrometheusEnabled bool
// Namespace for CometBFT metrics. Used to emulate CometBFT metrics.
CometBFTMetricsNamespace string
// A list of keys and values used as labels on all metrics
GlobalLabelsAndValues []string
}

// TelemetryOptionsFromAppOpts creates the TelemetryOptions from server AppOptions
func TelemetryOptionsFromAppOpts(appOpts servertypes.AppOptions) TelemetryOptions {
prometheusEnabled := cast.ToBool(appOpts.Get("instrumentation.prometheus"))
if !prometheusEnabled {
return TelemetryOptions{
GlobalLabelsAndValues: []string{},
}
}
return TelemetryOptions{
PrometheusEnabled: true,
CometBFTMetricsNamespace: cast.ToString(appOpts.Get("instrumentation.namespace")),
GlobalLabelsAndValues: []string{
// TODO: can i get the chain id in this context?
},
}
}

// Metrics contains metrics exposed by this module.
// They use go-kit metrics like CometBFT as opposed to using cosmos-sdk telemetry
// because the sdk's telemetry only supports float32s, whereas go-kit prometheus
// metrics correctly handle float64s (and thus a larger number of int64s)
type Metrics struct {
// The height of the latest block.
// This gauges exactly emulates the default blocksync metric in CometBFT v0.38+
// It should be removed when
// see https://github.com/cometbft/cometbft/blob/v0.38.0-rc3/blocksync/metrics.gen.go
LatestBlockHeight metrics.Gauge
}

// NewMetrics creates a new Metrics object based on whether or not prometheus instrumentation is enabled.
func NewMetrics(opts TelemetryOptions) *Metrics {
if opts.PrometheusEnabled {
return PrometheusMetrics(opts)
}
return NoopMetrics()
}

// PrometheusMetrics returns the gauges for when prometheus instrumentation is enabled.
func PrometheusMetrics(opts TelemetryOptions) *Metrics {
labels := []string{}
for i := 0; i < len(opts.GlobalLabelsAndValues); i += 2 {
labels = append(labels, opts.GlobalLabelsAndValues[i])
}
return &Metrics{
LatestBlockHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: opts.CometBFTMetricsNamespace,
Subsystem: "blocksync",
Name: "latest_block_height",
Help: "The height of the latest block.",
}, labels).With(opts.GlobalLabelsAndValues...),
}
}

// NoopMetrics are a do-nothing placeholder used when prometheus instrumentation is not enabled.
func NoopMetrics() *Metrics {
return &Metrics{
LatestBlockHeight: discard.NewGauge(),
}
}

0 comments on commit 9368851

Please sign in to comment.