From 8054d16b269b477e550edfd1fa8f105a29dd2b29 Mon Sep 17 00:00:00 2001 From: Rafael Sampaio <5679073+r4f4ss@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:27:16 -0300 Subject: [PATCH] implementation of metrics influx, influxV2 and local web server --- cmd/shisui/main.go | 24 +++++- cmd/utils/flags.go | 148 +++++++++++++++++++++++++++++++++++ internal/flags/categories.go | 39 ++++----- metrics/config.go | 20 +++++ 4 files changed, 211 insertions(+), 20 deletions(-) diff --git a/cmd/shisui/main.go b/cmd/shisui/main.go index c4eb34670773..54c52c14314e 100644 --- a/cmd/shisui/main.go +++ b/cmd/shisui/main.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/p2p/discover/portalwire" "github.com/ethereum/go-ethereum/p2p/enode" @@ -79,11 +80,26 @@ var ( utils.PortalDataCapacityFlag, utils.PortalLogLevelFlag, } + metricsFlags = []cli.Flag{ + utils.PortalMetricsEnabledFlag, + utils.PortalMetricsHTTPFlag, + utils.PortalMetricsPortFlag, + utils.PortalMetricsEnableInfluxDBFlag, + utils.PortalMetricsInfluxDBEndpointFlag, + utils.PortalMetricsInfluxDBDatabaseFlag, + utils.PortalMetricsInfluxDBUsernameFlag, + utils.PortalMetricsInfluxDBPasswordFlag, + utils.PortalMetricsInfluxDBTagsFlag, + utils.PortalMetricsEnableInfluxDBV2Flag, + utils.PortalMetricsInfluxDBTokenFlag, + utils.PortalMetricsInfluxDBBucketFlag, + utils.PortalMetricsInfluxDBOrganizationFlag, + } ) func init() { app.Action = shisui - app.Flags = flags.Merge(portalProtocolFlags, historyRpcFlags) + app.Flags = flags.Merge(portalProtocolFlags, historyRpcFlags, metricsFlags) flags.AutoEnvVars(app.Flags, "SHISUI") } @@ -97,6 +113,12 @@ func main() { func shisui(ctx *cli.Context) error { setDefaultLogger(ctx.Int(utils.PortalLogLevelFlag.Name)) + // Start metrics export if enabled + utils.PortalSetupMetrics(ctx) + + // Start system runtime metrics collection + go metrics.CollectProcessMetrics(3 * time.Second) + config, err := getPortalConfig(ctx) if err != nil { return nil diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index ff7c1356bc4f..2bb0fc7f3e17 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1026,6 +1026,93 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server. Category: flags.PortalNetworkCategory, Value: cli.NewStringSlice(portalwire.History.Name()), } + // Metrics flags for shisui + PortalMetricsEnabledFlag = &cli.BoolFlag{ + Name: "metrics", + Usage: "Enable metrics collection and reporting", + Category: flags.PortalNetworkMetricsCategory, + } + // MetricsHTTPFlag defines the endpoint for a stand-alone metrics HTTP endpoint. + // Since the pprof service enables sensitive/vulnerable behavior, this allows a user + // to enable a public-OK metrics endpoint without having to worry about ALSO exposing + // other profiling behavior or information. + PortalMetricsHTTPFlag = &cli.StringFlag{ + Name: "metrics.addr", + Usage: `Enable stand-alone metrics HTTP server listening interface.`, + Category: flags.PortalNetworkMetricsCategory, + } + PortalMetricsPortFlag = &cli.IntFlag{ + Name: "metrics.port", + Usage: `Metrics HTTP server listening port. +Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.`, + Value: metrics.ShisuiDefaultConfig.Port, + Category: flags.PortalNetworkMetricsCategory, + } + PortalMetricsEnableInfluxDBFlag = &cli.BoolFlag{ + Name: "metrics.influxdb", + Usage: "Enable metrics export/push to an external InfluxDB database", + Category: flags.PortalNetworkMetricsCategory, + } + PortalMetricsInfluxDBEndpointFlag = &cli.StringFlag{ + Name: "metrics.influxdb.endpoint", + Usage: "InfluxDB API endpoint to report metrics to", + Value: metrics.ShisuiDefaultConfig.InfluxDBEndpoint, + Category: flags.PortalNetworkMetricsCategory, + } + PortalMetricsInfluxDBDatabaseFlag = &cli.StringFlag{ + Name: "metrics.influxdb.database", + Usage: "InfluxDB database name to push reported metrics to", + Value: metrics.ShisuiDefaultConfig.InfluxDBDatabase, + Category: flags.PortalNetworkMetricsCategory, + } + PortalMetricsInfluxDBUsernameFlag = &cli.StringFlag{ + Name: "metrics.influxdb.username", + Usage: "Username to authorize access to the database", + Value: metrics.ShisuiDefaultConfig.InfluxDBUsername, + Category: flags.PortalNetworkMetricsCategory, + } + PortalMetricsInfluxDBPasswordFlag = &cli.StringFlag{ + Name: "metrics.influxdb.password", + Usage: "Password to authorize access to the database", + Value: metrics.ShisuiDefaultConfig.InfluxDBPassword, + Category: flags.PortalNetworkMetricsCategory, + } + // Tags are part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB. + // For example `host` tag could be used so that we can group all nodes and average a measurement + // across all of them, but also so that we can select a specific node and inspect its measurements. + // https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key + PortalMetricsInfluxDBTagsFlag = &cli.StringFlag{ + Name: "metrics.influxdb.tags", + Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", + Value: metrics.ShisuiDefaultConfig.InfluxDBTags, + Category: flags.PortalNetworkMetricsCategory, + } + + PortalMetricsEnableInfluxDBV2Flag = &cli.BoolFlag{ + Name: "metrics.influxdbv2", + Usage: "Enable metrics export/push to an external InfluxDB v2 database", + Category: flags.PortalNetworkMetricsCategory, + } + PortalMetricsInfluxDBTokenFlag = &cli.StringFlag{ + Name: "metrics.influxdb.token", + Usage: "Token to authorize access to the database (v2 only)", + Value: metrics.ShisuiDefaultConfig.InfluxDBToken, + Category: flags.PortalNetworkMetricsCategory, + } + + PortalMetricsInfluxDBBucketFlag = &cli.StringFlag{ + Name: "metrics.influxdb.bucket", + Usage: "InfluxDB bucket name to push reported metrics to (v2 only)", + Value: metrics.ShisuiDefaultConfig.InfluxDBBucket, + Category: flags.PortalNetworkMetricsCategory, + } + + PortalMetricsInfluxDBOrganizationFlag = &cli.StringFlag{ + Name: "metrics.influxdb.organization", + Usage: "InfluxDB organization name (v2 only)", + Value: metrics.ShisuiDefaultConfig.InfluxDBOrganization, + Category: flags.PortalNetworkMetricsCategory, + } ) var ( @@ -2042,6 +2129,67 @@ func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, target common.H log.Info("Registered full-sync tester", "hash", target) } +func PortalSetupMetrics(ctx *cli.Context) { + if metrics.Enabled { + log.Info("Enabling metrics collection") + + var ( + enableExport = ctx.Bool(PortalMetricsEnableInfluxDBFlag.Name) + enableExportV2 = ctx.Bool(PortalMetricsEnableInfluxDBV2Flag.Name) + ) + + if enableExport || enableExportV2 { + CheckExclusive(ctx, PortalMetricsEnableInfluxDBFlag, PortalMetricsEnableInfluxDBV2Flag) + + v1FlagIsSet := ctx.IsSet(PortalMetricsInfluxDBUsernameFlag.Name) || + ctx.IsSet(PortalMetricsInfluxDBPasswordFlag.Name) + + v2FlagIsSet := ctx.IsSet(PortalMetricsInfluxDBTokenFlag.Name) || + ctx.IsSet(PortalMetricsInfluxDBOrganizationFlag.Name) || + ctx.IsSet(PortalMetricsInfluxDBBucketFlag.Name) + + if enableExport && v2FlagIsSet { + Fatalf("Flags --influxdb.metrics.organization, --influxdb.metrics.token, --influxdb.metrics.bucket are only available for influxdb-v2") + } else if enableExportV2 && v1FlagIsSet { + Fatalf("Flags --influxdb.metrics.username, --influxdb.metrics.password are only available for influxdb-v1") + } + } + + var ( + endpoint = ctx.String(PortalMetricsInfluxDBEndpointFlag.Name) + database = ctx.String(PortalMetricsInfluxDBDatabaseFlag.Name) + username = ctx.String(PortalMetricsInfluxDBUsernameFlag.Name) + password = ctx.String(PortalMetricsInfluxDBPasswordFlag.Name) + + token = ctx.String(PortalMetricsInfluxDBTokenFlag.Name) + bucket = ctx.String(PortalMetricsInfluxDBBucketFlag.Name) + organization = ctx.String(PortalMetricsInfluxDBOrganizationFlag.Name) + ) + + if enableExport { + tagsMap := SplitTagsFlag(ctx.String(PortalMetricsInfluxDBTagsFlag.Name)) + + log.Info("Enabling metrics export to InfluxDB") + + go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap) + } else if enableExportV2 { + tagsMap := SplitTagsFlag(ctx.String(PortalMetricsInfluxDBTagsFlag.Name)) + + log.Info("Enabling metrics export to InfluxDB (v2)") + + go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap) + } + + if ctx.IsSet(PortalMetricsHTTPFlag.Name) { + address := net.JoinHostPort(ctx.String(PortalMetricsHTTPFlag.Name), fmt.Sprintf("%d", ctx.Int(PortalMetricsPortFlag.Name))) + log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address) + exp.Setup(address) + } else if ctx.IsSet(PortalMetricsPortFlag.Name) { + log.Warn(fmt.Sprintf("--%s specified without --%s, metrics server will not start.", PortalMetricsPortFlag.Name, PortalMetricsHTTPFlag.Name)) + } + } +} + func SetupMetrics(ctx *cli.Context) { if metrics.Enabled { log.Info("Enabling metrics collection") diff --git a/internal/flags/categories.go b/internal/flags/categories.go index 8fa23dbc45f4..cfe90d3b0dbe 100644 --- a/internal/flags/categories.go +++ b/internal/flags/categories.go @@ -19,25 +19,26 @@ package flags import "github.com/urfave/cli/v2" const ( - EthCategory = "ETHEREUM" - BeaconCategory = "BEACON CHAIN" - DevCategory = "DEVELOPER CHAIN" - StateCategory = "STATE HISTORY MANAGEMENT" - TxPoolCategory = "TRANSACTION POOL (EVM)" - BlobPoolCategory = "TRANSACTION POOL (BLOB)" - PerfCategory = "PERFORMANCE TUNING" - AccountCategory = "ACCOUNT" - APICategory = "API AND CONSOLE" - NetworkingCategory = "NETWORKING" - MinerCategory = "MINER" - GasPriceCategory = "GAS PRICE ORACLE" - VMCategory = "VIRTUAL MACHINE" - LoggingCategory = "LOGGING AND DEBUGGING" - MetricsCategory = "METRICS AND STATS" - MiscCategory = "MISC" - TestingCategory = "TESTING" - DeprecatedCategory = "ALIASED (deprecated)" - PortalNetworkCategory = "PORTAL NETWORK" + EthCategory = "ETHEREUM" + BeaconCategory = "BEACON CHAIN" + DevCategory = "DEVELOPER CHAIN" + StateCategory = "STATE HISTORY MANAGEMENT" + TxPoolCategory = "TRANSACTION POOL (EVM)" + BlobPoolCategory = "TRANSACTION POOL (BLOB)" + PerfCategory = "PERFORMANCE TUNING" + AccountCategory = "ACCOUNT" + APICategory = "API AND CONSOLE" + NetworkingCategory = "NETWORKING" + MinerCategory = "MINER" + GasPriceCategory = "GAS PRICE ORACLE" + VMCategory = "VIRTUAL MACHINE" + LoggingCategory = "LOGGING AND DEBUGGING" + MetricsCategory = "METRICS AND STATS" + MiscCategory = "MISC" + TestingCategory = "TESTING" + DeprecatedCategory = "ALIASED (deprecated)" + PortalNetworkCategory = "PORTAL NETWORK" + PortalNetworkMetricsCategory = "PORTAL NETWORK METRICS" ) func init() { diff --git a/metrics/config.go b/metrics/config.go index 72f94dd194c9..435f84e85575 100644 --- a/metrics/config.go +++ b/metrics/config.go @@ -54,3 +54,23 @@ var DefaultConfig = Config{ InfluxDBBucket: "geth", InfluxDBOrganization: "geth", } + +// ShisuiDefaultConfig is the default config for metrics used in shisui. +var ShisuiDefaultConfig = Config{ + Enabled: false, + EnabledExpensive: false, + HTTP: "127.0.0.1", + Port: 6060, + EnableInfluxDB: false, + InfluxDBEndpoint: "http://localhost:8086", + InfluxDBDatabase: "shisui", + InfluxDBUsername: "test", + InfluxDBPassword: "test", + InfluxDBTags: "host=localhost", + + // influxdbv2-specific flags + EnableInfluxDBV2: false, + InfluxDBToken: "test", + InfluxDBBucket: "shisui", + InfluxDBOrganization: "shisui", +}