Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new flag + readme for starting p2p prometheus dashboards #5707

Merged
merged 3 commits into from
Nov 22, 2023
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
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,36 @@ sudo cp protoc-gen-gogoslick /usr/bin/

Done

## Running p2p Prometheus dashboards
1. Start the node with `--p2p-prometheus-metrics` flag. This exposes a metrics collection at http://localhost:8080/debug/metrics/prometheus (port defined by -rest-api-interface flag, default 8080)
2. Clone libp2p repository: `git clone https://github.com/libp2p/go-libp2p`
3. `cd go-libp2p/dasboards/swarm` and under the
```
"templating": {
"list": [
```
section, add the following lines:
```
{
"hide": 0,
"label": "datasource",
"name": "DS_PROMETHEUS",
"options": [],
"query": "prometheus",
"refresh": 1,
"regex": "",
"type": "datasource"
},
```
(this step will be removed once it will be fixed on libp2p)
4. `cd ..` to dashboards directory and update the port of `host.docker.internal` from `prometheus.yml` to node's Rest API port(default `8080`)
5. From this directory, run the following docker compose command:
```
sudo docker compose -f docker-compose.base.yml -f docker-compose-linux.yml up --force-recreate
```
**Note:** If you choose to install the new Docker version manually, please make sure that installation is done for all users of the system. Otherwise, the docker command will fail because it needs the super-user privileges.
6. The preconfigured dashboards should be now available on Grafana at http://localhost:3000/dashboards

## Progress

### Done
Expand Down
7 changes: 6 additions & 1 deletion api/gin/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ func TestCommon_checkArgs(t *testing.T) {
err := checkArgs(args)
require.True(t, errors.Is(err, apiErrors.ErrCannotCreateGinWebServer))

args.Facade, err = initial.NewInitialNodeFacade("api interface", false, &testscommon.StatusMetricsStub{})
args.Facade, err = initial.NewInitialNodeFacade(initial.ArgInitialNodeFacade{
ApiInterface: "api interface",
PprofEnabled: false,
P2PPrometheusMetricsEnabled: false,
StatusMetricsHandler: &testscommon.StatusMetricsStub{},
})
require.NoError(t, err)
err = checkArgs(args)
require.NoError(t, err)
Expand Down
7 changes: 7 additions & 0 deletions api/gin/webServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ import (
"github.com/multiversx/mx-chain-go/config"
"github.com/multiversx/mx-chain-go/facade"
logger "github.com/multiversx/mx-chain-logger-go"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

var log = logger.GetOrCreate("api/gin")

const prometheusMetricsRoute = "/debug/metrics/prometheus"

// ArgsNewWebServer holds the arguments needed to create a new instance of webServer
type ArgsNewWebServer struct {
Facade shared.FacadeHandler
Expand Down Expand Up @@ -227,6 +230,10 @@ func (ws *webServer) registerRoutes(ginRouter *gin.Engine) {
if ws.facade.PprofEnabled() {
pprof.Register(ginRouter)
}

if ws.facade.P2PPrometheusMetricsEnabled() {
ginRouter.GET(prometheusMetricsRoute, gin.WrapH(promhttp.Handler()))
}
}

func (ws *webServer) createMiddlewareLimiters() ([]shared.MiddlewareProcessor, error) {
Expand Down
9 changes: 9 additions & 0 deletions api/mock/facadeStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ type FacadeStub struct {
GetManagedKeysCalled func() []string
GetEligibleManagedKeysCalled func() ([]string, error)
GetWaitingManagedKeysCalled func() ([]string, error)
P2PPrometheusMetricsEnabledCalled func() bool
}

// GetTokenSupply -
Expand Down Expand Up @@ -610,6 +611,14 @@ func (f *FacadeStub) GetWaitingManagedKeys() ([]string, error) {
return make([]string, 0), nil
}

// P2PPrometheusMetricsEnabled -
func (f *FacadeStub) P2PPrometheusMetricsEnabled() bool {
if f.P2PPrometheusMetricsEnabledCalled != nil {
return f.P2PPrometheusMetricsEnabledCalled()
}
return false
}

// Close -
func (f *FacadeStub) Close() error {
return nil
Expand Down
1 change: 1 addition & 0 deletions api/shared/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,6 @@ type FacadeHandler interface {
GetManagedKeys() []string
GetEligibleManagedKeys() ([]string, error)
GetWaitingManagedKeys() ([]string, error)
P2PPrometheusMetricsEnabled() bool
IsInterfaceNil() bool
}
1 change: 1 addition & 0 deletions cmd/node/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ GLOBAL OPTIONS:
--logs-path directory This flag specifies the directory where the node will store logs.
--operation-mode operation mode String flag for specifying the desired operation mode(s) of the node, resulting in altering some configuration values accordingly. Possible values are: snapshotless-observer, full-archive, db-lookup-extension, historical-balances or `""` (empty). Multiple values can be separated via ,
--repopulate-tokens-supplies Boolean flag for repopulating the tokens supplies database. It will delete the current data, iterate over the entire trie and add he new obtained supplies
--p2p-prometheus-metrics Boolean option for enabling the /debug/metrics/prometheus route for p2p prometheus metrics
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

--help, -h show help
--version, -v print the version

Expand Down
9 changes: 9 additions & 0 deletions cmd/node/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,13 @@ var (
Name: "repopulate-tokens-supplies",
Usage: "Boolean flag for repopulating the tokens supplies database. It will delete the current data, iterate over the entire trie and add he new obtained supplies",
}

// p2pPrometheusMetrics defines a flag for p2p prometheus metrics
// If enabled, it will open a new route, /debug/metrics/prometheus, where p2p prometheus metrics will be available
p2pPrometheusMetrics = cli.BoolFlag{
Name: "p2p-prometheus-metrics",
Usage: "Boolean option for enabling the /debug/metrics/prometheus route for p2p prometheus metrics",
}
)

func getFlags() []cli.Flag {
Expand Down Expand Up @@ -469,6 +476,7 @@ func getFlags() []cli.Flag {
logsDirectory,
operationMode,
repopulateTokensSupplies,
p2pPrometheusMetrics,
}
}

Expand Down Expand Up @@ -497,6 +505,7 @@ func getFlagsConfig(ctx *cli.Context, log logger.Logger) *config.ContextFlagsCon
flagsConfig.SerializeSnapshots = ctx.GlobalBool(serializeSnapshots.Name)
flagsConfig.OperationMode = ctx.GlobalString(operationMode.Name)
flagsConfig.RepopulateTokensSupplies = ctx.GlobalBool(repopulateTokensSupplies.Name)
flagsConfig.P2PPrometheusMetricsEnabled = ctx.GlobalBool(p2pPrometheusMetrics.Name)

if ctx.GlobalBool(noKey.Name) {
log.Warn("the provided -no-key option is deprecated and will soon be removed. To start a node without " +
Expand Down
1 change: 1 addition & 0 deletions cmd/seednode/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ GLOBAL OPTIONS:
--log-save Boolean option for enabling log saving. If set, it will automatically save all the logs into a file.
--config [path] The [path] for the main configuration file. This TOML file contain the main configurations such as the marshalizer type (default: "./config/config.toml")
--p2p-key-pem-file filepath The filepath for the PEM file which contains the secret keys for the p2p key. If this is not specified a new key will be generated (internally) by default. (default: "./config/p2pKey.pem")
--p2p-prometheus-metrics Boolean option for enabling the /debug/metrics/prometheus route for p2p prometheus metrics
--help, -h show help
--version, -v print the version

Expand Down
15 changes: 10 additions & 5 deletions cmd/seednode/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,26 @@ import (
"github.com/multiversx/mx-chain-core-go/marshal"
"github.com/multiversx/mx-chain-go/api/logs"
logger "github.com/multiversx/mx-chain-logger-go"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

var log = logger.GetOrCreate("seednode/api")

// Start will boot up the api and appropriate routes, handlers and validators
func Start(restApiInterface string, marshalizer marshal.Marshalizer) error {
func Start(restApiInterface string, marshalizer marshal.Marshalizer, p2pPrometheusMetricsEnabled bool) error {
ws := gin.Default()
ws.Use(cors.Default())

registerRoutes(ws, marshalizer)
registerRoutes(ws, marshalizer, p2pPrometheusMetricsEnabled)

return ws.Run(restApiInterface)
}

func registerRoutes(ws *gin.Engine, marshalizer marshal.Marshalizer) {
registerLoggerWsRoute(ws, marshalizer)
func registerRoutes(ws *gin.Engine, marshalizer marshal.Marshalizer, p2pPrometheusMetricsEnabled bool) {
registerLoggerWsRoute(ws, marshalizer, p2pPrometheusMetricsEnabled)
}

func registerLoggerWsRoute(ws *gin.Engine, marshalizer marshal.Marshalizer) {
func registerLoggerWsRoute(ws *gin.Engine, marshalizer marshal.Marshalizer, p2pPrometheusMetricsEnabled bool) {
upgrader := websocket.Upgrader{}

ws.GET("/log", func(c *gin.Context) {
Expand All @@ -49,4 +50,8 @@ func registerLoggerWsRoute(ws *gin.Engine, marshalizer marshal.Marshalizer) {

ls.StartSendingBlocking()
})

if p2pPrometheusMetricsEnabled {
ws.GET("/debug/metrics/prometheus", gin.WrapH(promhttp.Handler()))
}
}
15 changes: 12 additions & 3 deletions cmd/seednode/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ VERSION:
}

p2pConfigurationFile = "./config/p2p.toml"

// p2pPrometheusMetrics defines a flag for p2p prometheus metrics
// If enabled, it will open a new route, /debug/metrics/prometheus, where p2p prometheus metrics will be available
p2pPrometheusMetrics = cli.BoolFlag{
Name: "p2p-prometheus-metrics",
Usage: "Boolean option for enabling the /debug/metrics/prometheus route for p2p prometheus metrics",
}
)

var log = logger.GetOrCreate("main")
Expand All @@ -114,6 +121,7 @@ func main() {
logSaveFile,
configurationFile,
p2pKeyPemFile,
p2pPrometheusMetrics,
}
app.Version = "v0.0.1"
app.Authors = []cli.Author{
Expand Down Expand Up @@ -350,14 +358,15 @@ func checkExpectedPeerCount(p2pConfig p2pConfig.P2PConfig) error {
func startRestServices(ctx *cli.Context, marshalizer marshal.Marshalizer) {
restApiInterface := ctx.GlobalString(restApiInterfaceFlag.Name)
if restApiInterface != facade.DefaultRestPortOff {
go startGinServer(restApiInterface, marshalizer)
p2pPrometheusMetricsEnabled := ctx.GlobalBool(p2pPrometheusMetrics.Name)
go startGinServer(restApiInterface, marshalizer, p2pPrometheusMetricsEnabled)
} else {
log.Info("rest api is disabled")
}
}

func startGinServer(restApiInterface string, marshalizer marshal.Marshalizer) {
err := api.Start(restApiInterface, marshalizer)
func startGinServer(restApiInterface string, marshalizer marshal.Marshalizer, p2pPrometheusMetricsEnabled bool) {
err := api.Start(restApiInterface, marshalizer, p2pPrometheusMetricsEnabled)
if err != nil {
log.LogIfError(err)
}
Expand Down
5 changes: 3 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,9 @@ type GeneralSettingsConfig struct {

// FacadeConfig will hold different configuration option that will be passed to the node facade
type FacadeConfig struct {
RestApiInterface string
PprofEnabled bool
RestApiInterface string
PprofEnabled bool
P2PPrometheusMetricsEnabled bool
}

// StateTriesConfig will hold information about state tries
Expand Down
1 change: 1 addition & 0 deletions config/contextFlagsConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type ContextFlagsConfig struct {
SerializeSnapshots bool
OperationMode string
RepopulateTokensSupplies bool
P2PPrometheusMetricsEnabled bool
}

// ImportDbConfig will hold the import-db parameters
Expand Down
35 changes: 25 additions & 10 deletions facade/initial/initialNodeFacade.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,38 @@ import (
var errNodeStarting = errors.New("node is starting")
var emptyString = ""

// ArgInitialNodeFacade is the DTO used to create a new instance of initialNodeFacade
type ArgInitialNodeFacade struct {
ApiInterface string
PprofEnabled bool
P2PPrometheusMetricsEnabled bool
StatusMetricsHandler external.StatusMetricsHandler
}

// initialNodeFacade represents a facade with no functionality
type initialNodeFacade struct {
apiInterface string
statusMetricsHandler external.StatusMetricsHandler
pprofEnabled bool
apiInterface string
statusMetricsHandler external.StatusMetricsHandler
pprofEnabled bool
p2pPrometheusMetricsEnabled bool
}

// NewInitialNodeFacade is the initial implementation of the facade interface
func NewInitialNodeFacade(apiInterface string, pprofEnabled bool, statusMetricsHandler external.StatusMetricsHandler) (*initialNodeFacade, error) {
if check.IfNil(statusMetricsHandler) {
func NewInitialNodeFacade(args ArgInitialNodeFacade) (*initialNodeFacade, error) {
if check.IfNil(args.StatusMetricsHandler) {
return nil, facade.ErrNilStatusMetrics
}

initialStatusMetrics, err := NewInitialStatusMetricsProvider(statusMetricsHandler)
initialStatusMetrics, err := NewInitialStatusMetricsProvider(args.StatusMetricsHandler)
if err != nil {
return nil, err
}

return &initialNodeFacade{
apiInterface: apiInterface,
statusMetricsHandler: initialStatusMetrics,
pprofEnabled: pprofEnabled,
apiInterface: args.ApiInterface,
statusMetricsHandler: initialStatusMetrics,
pprofEnabled: args.PprofEnabled,
p2pPrometheusMetricsEnabled: args.P2PPrometheusMetricsEnabled,
}, nil
}

Expand Down Expand Up @@ -76,7 +86,7 @@ func (inf *initialNodeFacade) SetSyncer(_ ntp.SyncTimer) {
}

// RestAPIServerDebugMode returns false
//TODO: remove in the future
// TODO: remove in the future
func (inf *initialNodeFacade) RestAPIServerDebugMode() bool {
return false
}
Expand Down Expand Up @@ -426,6 +436,11 @@ func (inf *initialNodeFacade) GetWaitingManagedKeys() ([]string, error) {
return nil, errNodeStarting
}

// P2PPrometheusMetricsEnabled returns either the p2p prometheus metrics are enabled or not
func (inf *initialNodeFacade) P2PPrometheusMetricsEnabled() bool {
return inf.p2pPrometheusMetricsEnabled
}

// IsInterfaceNil returns true if there is no value under the interface
func (inf *initialNodeFacade) IsInterfaceNil() bool {
return inf == nil
Expand Down
21 changes: 17 additions & 4 deletions facade/initial/initialNodeFacade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,31 @@ import (
"github.com/stretchr/testify/assert"
)

func createInitialNodeFacadeArgs() ArgInitialNodeFacade {
return ArgInitialNodeFacade{
ApiInterface: "127.0.0.1:8080",
PprofEnabled: true,
P2PPrometheusMetricsEnabled: false,
StatusMetricsHandler: &testscommon.StatusMetricsStub{},
}
}

func TestInitialNodeFacade(t *testing.T) {
t.Parallel()

t.Run("nil status metrics should error", func(t *testing.T) {
t.Parallel()

inf, err := NewInitialNodeFacade("127.0.0.1:8080", true, nil)
args := createInitialNodeFacadeArgs()
args.StatusMetricsHandler = nil
inf, err := NewInitialNodeFacade(args)
assert.Equal(t, facade.ErrNilStatusMetrics, err)
assert.Nil(t, inf)
})
t.Run("should work", func(t *testing.T) {
t.Parallel()

inf, err := NewInitialNodeFacade("127.0.0.1:8080", true, &testscommon.StatusMetricsStub{})
inf, err := NewInitialNodeFacade(createInitialNodeFacadeArgs())
assert.Nil(t, err)
assert.NotNil(t, inf)
})
Expand All @@ -40,7 +51,9 @@ func TestInitialNodeFacade_AllMethodsShouldNotPanic(t *testing.T) {
}()

apiInterface := "127.0.0.1:7799"
inf, err := NewInitialNodeFacade(apiInterface, true, &testscommon.StatusMetricsStub{})
args := createInitialNodeFacadeArgs()
args.ApiInterface = apiInterface
inf, err := NewInitialNodeFacade(args)
assert.Nil(t, err)

inf.SetSyncer(nil)
Expand Down Expand Up @@ -325,6 +338,6 @@ func TestInitialNodeFacade_IsInterfaceNil(t *testing.T) {
var inf *initialNodeFacade
assert.True(t, inf.IsInterfaceNil())

inf, _ = NewInitialNodeFacade("127.0.0.1:7799", true, &testscommon.StatusMetricsStub{})
inf, _ = NewInitialNodeFacade(createInitialNodeFacadeArgs())
assert.False(t, inf.IsInterfaceNil())
}
Loading