Skip to content

Commit

Permalink
feat(x/metrics): add module for emiting custom chain metrics (backport
Browse files Browse the repository at this point in the history
…#1668) (#1674)

* feat(x/metrics): add module for emiting custom chain metrics (#1668)

* initialize x/metrics with metrics collection

* include global labels in x/metrics metrics

* add x/metrics spec

* add x/metrics test coverage

* update changelog

(cherry picked from commit 9a0aed7)

# Conflicts:
#	CHANGELOG.md
#	app/app.go
#	go.mod

* fix merge conflicts, add docker-build command

---------

Co-authored-by: Robert Pirtle <Astropirtle@gmail.com>
  • Loading branch information
mergify[bot] and pirtleshell committed Aug 25, 2023
1 parent 64964fc commit e4c2bf6
Show file tree
Hide file tree
Showing 13 changed files with 456 additions and 4 deletions.
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
golang 1.18.10
50 changes: 48 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,62 @@ Ref: https://keepachangelog.com/en/1.0.0/

## [Unreleased]

- (metrics) [#1668] Adds non-state breaking x/metrics module for custom telemetry.

## [v0.19.2](https://github.com/Kava-Labs/kava/releases/tag/v0.19.2)
- Adds ethermint patch for finalized json rpc support & historical eth_call queries

## [v0.19.1](https://github.com/Kava-Labs/kava/releases/tag/v0.19.1)

- [#1384] Adds total supply queries for earn, savings, liquid (#1384)

## [v0.19.0](https://github.com/Kava-Labs/kava/releases/tag/v0.19.0)

* Adds liquid module for converting staked kava to bkava staking derivative tokens
* Adds earn module to support automated yield strategies
* Implements the Kava Infrastructure Rewards proposal (https://www.mintscan.io/kava/proposals/97)
* Adds support for signing cosmos messages using Metamask via eip712


## [v0.18.2](https://github.com/Kava-Labs/kava/releases/tag/v0.18.2)

* Update to go 1.18, cosmos v0.45.9, and tendermint v0.34.21
* Update ci & docker to go 1.18
* Config updates for iavl changes and broadcast mode flag
* Ensure fast node is disable if config value is not set in order to
avoid fast node upgrade for nodes that do not update their app.toml
* Update to new circle ci image instead of using legacy image
* Remove previous ics23 package -- now used directly from cosmos-sdk repo

## [v0.18.1](https://github.com/Kava-Labs/kava/releases/tag/v0.18.1)

Patch for IBC Security Advisory Dragonberry: https://forum.cosmos.network/t/ibc-security-advisory-dragonberry/7702

## [v0.18.0](https://github.com/Kava-Labs/kava/releases/tag/v0.18.0)

Security upgrade patch release for kava 10.

## [v0.17.3](https://github.com/Kava-Labs/kava/releases/tag/v0.17.3)

Release of Kava EVM & the first binary with chain id `kava_2222-10`.

See Release for full details:
* [v0.17.3](https://github.com/Kava-Labs/kava/releases/tag/v0.17.3)
* [v0.17.1](https://github.com/Kava-Labs/kava/releases/tag/v0.17.1)

### State Machine Breaking
[\#1158](https://github.com/Kava-Labs/kava/pull/1158) Split existing auction `bid_duration` parameter into `forward_bid_duration` and `reverse_bid_duration`

## [v0.16.1](https://github.com/Kava-Labs/kava/releases/tag/v0.16.1)

### State Machine Breaking

[\#1152](https://github.com/Kava-Labs/kava/pull/1152) Fix MultiSpend Proposal With Async Upgrade Time
[\#1152](https://github.com/Kava-Labs/kava/pull/1152) Fix MultiSpend Proposal With Async Upgrade Time

## [v0.16.0](https://github.com/Kava-Labs/kava/releases/tag/v0.16.0)

### State Machine Breaking
[\#1106](https://github.com/Kava-Labs/kava/pull/1106) Upgrades app to cosmos-sdk v0.44.x and adds IBC and ICS-20 modules.
[\#1106](https://github.com/Kava-Labs/kava/pull/1106) Upgrades app to cosmos-sdk v0.44.x and adds IBC and ICS-20 modules.

## [v0.13.0]

Expand Down Expand Up @@ -154,3 +197,6 @@ Bump tendermint version to 0.32.10 to address [cosmos security advisory Lavender
### Improvements

[\#257](https://github.com/Kava-Labs/kava/pulls/257) Include scripts to run large-scale simulations remotely using aws-batch

[#1668]: https://github.com/Kava-Labs/kava/pull/1668
[#1384]: https://github.com/Kava-Labs/kava/pull/1384
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ format:
### Localnet ###
###############################################################################

docker-build:
DOCKER_BUILDKIT=1 $(DOCKER) build -t kava/kava:local .

build-docker-local-kava:
@$(MAKE) -C networks/local

Expand Down
8 changes: 8 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,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 @@ -202,6 +204,7 @@ var (
liquid.AppModuleBasic{},
earn.AppModuleBasic{},
router.AppModuleBasic{},
metrics.AppModuleBasic{},
)

// module account permissions
Expand Down Expand Up @@ -245,6 +248,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 @@ -739,10 +743,12 @@ func NewApp(
liquid.NewAppModule(app.liquidKeeper),
earn.NewAppModule(app.earnKeeper, app.accountKeeper, app.bankKeeper),
router.NewAppModule(app.routerKeeper),
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 @@ -829,6 +835,7 @@ func NewApp(
liquidtypes.ModuleName,
earntypes.ModuleName,
routertypes.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 @@ -869,6 +876,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 @@ -23,6 +23,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 @@ -93,6 +94,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 @@ -7,11 +7,13 @@ require (
github.com/cosmos/cosmos-sdk v0.45.10
github.com/cosmos/ibc-go/v3 v3.3.1
github.com/ethereum/go-ethereum v1.10.16
github.com/go-kit/kit v0.12.0
github.com/gogo/protobuf v1.3.3
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.2
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/prometheus/client_golang v1.12.2
github.com/spf13/cast v1.5.0
github.com/spf13/cobra v1.6.0
github.com/stretchr/testify v1.8.0
Expand Down Expand Up @@ -61,7 +63,6 @@ require (
github.com/felixge/httpsnoop v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // 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.5 // indirect
Expand Down Expand Up @@ -112,7 +113,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.12.2 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.34.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
Expand Down
12 changes: 12 additions & 0 deletions x/metrics/abci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package metrics

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

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

// BeginBlocker publishes metrics at the start of each block.
func BeginBlocker(ctx sdk.Context, metrics *types.Metrics) {
metrics.LatestBlockHeight.Set(float64(ctx.BlockHeight()))
}
45 changes: 45 additions & 0 deletions x/metrics/abci_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package metrics_test

import (
"testing"

kitmetrics "github.com/go-kit/kit/metrics"
"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

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

type MockGauge struct {
value float64
}

func (mg *MockGauge) With(labelValues ...string) kitmetrics.Gauge { return mg }
func (mg *MockGauge) Set(value float64) { mg.value = value }
func (*MockGauge) Add(_ float64) {}

func ctxWithHeight(height int64) sdk.Context {
tApp := app.NewTestApp()
tApp.InitializeFromGenesisStates()
return tApp.NewContext(false, tmproto.Header{Height: height})
}

func TestBeginBlockEmitsLatestHeight(t *testing.T) {
gauge := MockGauge{}
myMetrics := &types.Metrics{
LatestBlockHeight: &gauge,
}

metrics.BeginBlocker(ctxWithHeight(1), myMetrics)
require.EqualValues(t, 1, gauge.value)

metrics.BeginBlocker(ctxWithHeight(100), myMetrics)
require.EqualValues(t, 100, gauge.value)

metrics.BeginBlocker(ctxWithHeight(17e6), myMetrics)
require.EqualValues(t, 17e6, gauge.value)
}
132 changes: 132 additions & 0 deletions x/metrics/module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package metrics

import (
"encoding/json"

"github.com/gorilla/mux"
"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{}

// RegisterRESTRoutes implements module.AppModuleBasic.
func (AppModuleBasic) RegisterRESTRoutes(client.Context, *mux.Router) {}

// 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
}

// RegisterRESTRoutes implements module.AppModule.
func (AppModule) RegisterRESTRoutes(client.Context, *mux.Router) {}

// 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{}
}
Loading

0 comments on commit e4c2bf6

Please sign in to comment.