cmd/geth: export metrics to InfluxDB (#16979)
* cmd/geth: add flags for metrics export * cmd/geth: update usage fields for metrics flags * metrics/influxdb: update reporter logger to adhere to geth logging convention
This commit is contained in:
parent
223d943481
commit
1990c9e621
@ -144,6 +144,15 @@ var (
|
|||||||
utils.WhisperMaxMessageSizeFlag,
|
utils.WhisperMaxMessageSizeFlag,
|
||||||
utils.WhisperMinPOWFlag,
|
utils.WhisperMinPOWFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metricsFlags = []cli.Flag{
|
||||||
|
utils.MetricsEnableInfluxDBFlag,
|
||||||
|
utils.MetricsInfluxDBEndpointFlag,
|
||||||
|
utils.MetricsInfluxDBDatabaseFlag,
|
||||||
|
utils.MetricsInfluxDBUsernameFlag,
|
||||||
|
utils.MetricsInfluxDBPasswordFlag,
|
||||||
|
utils.MetricsInfluxDBHostTagFlag,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -186,6 +195,7 @@ func init() {
|
|||||||
app.Flags = append(app.Flags, consoleFlags...)
|
app.Flags = append(app.Flags, consoleFlags...)
|
||||||
app.Flags = append(app.Flags, debug.Flags...)
|
app.Flags = append(app.Flags, debug.Flags...)
|
||||||
app.Flags = append(app.Flags, whisperFlags...)
|
app.Flags = append(app.Flags, whisperFlags...)
|
||||||
|
app.Flags = append(app.Flags, metricsFlags...)
|
||||||
|
|
||||||
app.Before = func(ctx *cli.Context) error {
|
app.Before = func(ctx *cli.Context) error {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
@ -208,6 +218,9 @@ func init() {
|
|||||||
log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
|
log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
|
||||||
godebug.SetGCPercent(int(gogc))
|
godebug.SetGCPercent(int(gogc))
|
||||||
|
|
||||||
|
// Start metrics export if enabled
|
||||||
|
utils.SetupMetrics(ctx)
|
||||||
|
|
||||||
// Start system runtime metrics collection
|
// Start system runtime metrics collection
|
||||||
go metrics.CollectProcessMetrics(3 * time.Second)
|
go metrics.CollectProcessMetrics(3 * time.Second)
|
||||||
|
|
||||||
|
@ -206,11 +206,22 @@ var AppHelpFlagGroups = []flagGroup{
|
|||||||
{
|
{
|
||||||
Name: "LOGGING AND DEBUGGING",
|
Name: "LOGGING AND DEBUGGING",
|
||||||
Flags: append([]cli.Flag{
|
Flags: append([]cli.Flag{
|
||||||
utils.MetricsEnabledFlag,
|
|
||||||
utils.FakePoWFlag,
|
utils.FakePoWFlag,
|
||||||
utils.NoCompactionFlag,
|
utils.NoCompactionFlag,
|
||||||
}, debug.Flags...),
|
}, debug.Flags...),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "METRICS AND STATS",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
utils.MetricsEnabledFlag,
|
||||||
|
utils.MetricsEnableInfluxDBFlag,
|
||||||
|
utils.MetricsInfluxDBEndpointFlag,
|
||||||
|
utils.MetricsInfluxDBDatabaseFlag,
|
||||||
|
utils.MetricsInfluxDBUsernameFlag,
|
||||||
|
utils.MetricsInfluxDBPasswordFlag,
|
||||||
|
utils.MetricsInfluxDBHostTagFlag,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "WHISPER (EXPERIMENTAL)",
|
Name: "WHISPER (EXPERIMENTAL)",
|
||||||
Flags: whisperFlags,
|
Flags: whisperFlags,
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
@ -48,6 +49,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/les"
|
"github.com/ethereum/go-ethereum/les"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
|
"github.com/ethereum/go-ethereum/metrics/influxdb"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||||
@ -360,10 +362,6 @@ var (
|
|||||||
Name: "ethstats",
|
Name: "ethstats",
|
||||||
Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
|
Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
|
||||||
}
|
}
|
||||||
MetricsEnabledFlag = cli.BoolFlag{
|
|
||||||
Name: metrics.MetricsEnabledFlag,
|
|
||||||
Usage: "Enable metrics collection and reporting",
|
|
||||||
}
|
|
||||||
FakePoWFlag = cli.BoolFlag{
|
FakePoWFlag = cli.BoolFlag{
|
||||||
Name: "fakepow",
|
Name: "fakepow",
|
||||||
Usage: "Disables proof-of-work verification",
|
Usage: "Disables proof-of-work verification",
|
||||||
@ -532,6 +530,45 @@ var (
|
|||||||
Usage: "Minimum POW accepted",
|
Usage: "Minimum POW accepted",
|
||||||
Value: whisper.DefaultMinimumPoW,
|
Value: whisper.DefaultMinimumPoW,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Metrics flags
|
||||||
|
MetricsEnabledFlag = cli.BoolFlag{
|
||||||
|
Name: metrics.MetricsEnabledFlag,
|
||||||
|
Usage: "Enable metrics collection and reporting",
|
||||||
|
}
|
||||||
|
MetricsEnableInfluxDBFlag = cli.BoolFlag{
|
||||||
|
Name: "metrics.influxdb",
|
||||||
|
Usage: "Enable metrics export/push to an external InfluxDB database",
|
||||||
|
}
|
||||||
|
MetricsInfluxDBEndpointFlag = cli.StringFlag{
|
||||||
|
Name: "metrics.influxdb.endpoint",
|
||||||
|
Usage: "InfluxDB API endpoint to report metrics to",
|
||||||
|
Value: "http://localhost:8086",
|
||||||
|
}
|
||||||
|
MetricsInfluxDBDatabaseFlag = cli.StringFlag{
|
||||||
|
Name: "metrics.influxdb.database",
|
||||||
|
Usage: "InfluxDB database name to push reported metrics to",
|
||||||
|
Value: "geth",
|
||||||
|
}
|
||||||
|
MetricsInfluxDBUsernameFlag = cli.StringFlag{
|
||||||
|
Name: "metrics.influxdb.username",
|
||||||
|
Usage: "Username to authorize access to the database",
|
||||||
|
Value: "test",
|
||||||
|
}
|
||||||
|
MetricsInfluxDBPasswordFlag = cli.StringFlag{
|
||||||
|
Name: "metrics.influxdb.password",
|
||||||
|
Usage: "Password to authorize access to the database",
|
||||||
|
Value: "test",
|
||||||
|
}
|
||||||
|
// The `host` tag is part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB.
|
||||||
|
// It is 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
|
||||||
|
MetricsInfluxDBHostTagFlag = cli.StringFlag{
|
||||||
|
Name: "metrics.influxdb.host.tag",
|
||||||
|
Usage: "InfluxDB `host` tag attached to all measurements",
|
||||||
|
Value: "localhost",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeDataDir retrieves the currently requested data directory, terminating
|
// MakeDataDir retrieves the currently requested data directory, terminating
|
||||||
@ -1184,6 +1221,27 @@ func SetupNetwork(ctx *cli.Context) {
|
|||||||
params.TargetGasLimit = ctx.GlobalUint64(TargetGasLimitFlag.Name)
|
params.TargetGasLimit = ctx.GlobalUint64(TargetGasLimitFlag.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetupMetrics(ctx *cli.Context) {
|
||||||
|
if metrics.Enabled {
|
||||||
|
log.Info("Enabling metrics collection")
|
||||||
|
var (
|
||||||
|
enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name)
|
||||||
|
endpoint = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name)
|
||||||
|
database = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name)
|
||||||
|
username = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name)
|
||||||
|
password = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name)
|
||||||
|
hosttag = ctx.GlobalString(MetricsInfluxDBHostTagFlag.Name)
|
||||||
|
)
|
||||||
|
|
||||||
|
if enableExport {
|
||||||
|
log.Info("Enabling metrics export to InfluxDB")
|
||||||
|
go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", map[string]string{
|
||||||
|
"host": hosttag,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
|
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
|
||||||
func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
|
func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
|
||||||
var (
|
var (
|
||||||
|
@ -2,10 +2,10 @@ package influxdb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
uurl "net/url"
|
uurl "net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/influxdata/influxdb/client"
|
"github.com/influxdata/influxdb/client"
|
||||||
)
|
)
|
||||||
@ -35,7 +35,7 @@ func InfluxDB(r metrics.Registry, d time.Duration, url, database, username, pass
|
|||||||
func InfluxDBWithTags(r metrics.Registry, d time.Duration, url, database, username, password, namespace string, tags map[string]string) {
|
func InfluxDBWithTags(r metrics.Registry, d time.Duration, url, database, username, password, namespace string, tags map[string]string) {
|
||||||
u, err := uurl.Parse(url)
|
u, err := uurl.Parse(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("unable to parse InfluxDB url %s. err=%v", url, err)
|
log.Warn("Unable to parse InfluxDB", "url", url, "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ func InfluxDBWithTags(r metrics.Registry, d time.Duration, url, database, userna
|
|||||||
cache: make(map[string]int64),
|
cache: make(map[string]int64),
|
||||||
}
|
}
|
||||||
if err := rep.makeClient(); err != nil {
|
if err := rep.makeClient(); err != nil {
|
||||||
log.Printf("unable to make InfluxDB client. err=%v", err)
|
log.Warn("Unable to make InfluxDB client", "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,15 +76,15 @@ func (r *reporter) run() {
|
|||||||
select {
|
select {
|
||||||
case <-intervalTicker:
|
case <-intervalTicker:
|
||||||
if err := r.send(); err != nil {
|
if err := r.send(); err != nil {
|
||||||
log.Printf("unable to send to InfluxDB. err=%v", err)
|
log.Warn("Unable to send to InfluxDB", "err", err)
|
||||||
}
|
}
|
||||||
case <-pingTicker:
|
case <-pingTicker:
|
||||||
_, _, err := r.client.Ping()
|
_, _, err := r.client.Ping()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("got error while sending a ping to InfluxDB, trying to recreate client. err=%v", err)
|
log.Warn("Got error while sending a ping to InfluxDB, trying to recreate client", "err", err)
|
||||||
|
|
||||||
if err = r.makeClient(); err != nil {
|
if err = r.makeClient(); err != nil {
|
||||||
log.Printf("unable to make InfluxDB client. err=%v", err)
|
log.Warn("Unable to make InfluxDB client", "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user