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

geth metrics export to InfluxDB #16979

Merged
merged 3 commits into from
Jul 2, 2018
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
13 changes: 13 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ var (
utils.WhisperMaxMessageSizeFlag,
utils.WhisperMinPOWFlag,
}

metricsFlags = []cli.Flag{
utils.MetricsEnableInfluxDBFlag,
utils.MetricsInfluxDBEndpointFlag,
utils.MetricsInfluxDBDatabaseFlag,
utils.MetricsInfluxDBUsernameFlag,
utils.MetricsInfluxDBPasswordFlag,
utils.MetricsInfluxDBHostTagFlag,
}
)

func init() {
Expand Down Expand Up @@ -186,6 +195,7 @@ func init() {
app.Flags = append(app.Flags, consoleFlags...)
app.Flags = append(app.Flags, debug.Flags...)
app.Flags = append(app.Flags, whisperFlags...)
app.Flags = append(app.Flags, metricsFlags...)

app.Before = func(ctx *cli.Context) error {
runtime.GOMAXPROCS(runtime.NumCPU())
Expand All @@ -208,6 +218,9 @@ func init() {
log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
godebug.SetGCPercent(int(gogc))

// Start metrics export if enabled
utils.SetupMetrics(ctx)

// Start system runtime metrics collection
go metrics.CollectProcessMetrics(3 * time.Second)

Expand Down
13 changes: 12 additions & 1 deletion cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,22 @@ var AppHelpFlagGroups = []flagGroup{
{
Name: "LOGGING AND DEBUGGING",
Flags: append([]cli.Flag{
utils.MetricsEnabledFlag,
utils.FakePoWFlag,
utils.NoCompactionFlag,
}, 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)",
Flags: whisperFlags,
Expand Down
66 changes: 62 additions & 4 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"runtime"
"strconv"
"strings"
"time"

"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
Expand All @@ -48,6 +49,7 @@ import (
"github.com/ethereum/go-ethereum/les"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/metrics/influxdb"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
Expand Down Expand Up @@ -360,10 +362,6 @@ var (
Name: "ethstats",
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{
Name: "fakepow",
Usage: "Disables proof-of-work verification",
Expand Down Expand Up @@ -532,6 +530,45 @@ var (
Usage: "Minimum POW accepted",
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",
Copy link
Member

Choose a reason for hiding this comment

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

I think metrics.influxdb.host is enough, don't see the value of explicitly adding tag

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this should stay as is, because sometimes host can mean server or endpoint. Furthermore this is InfluxDB specific, so it is good to explain that this is actually a tag.

Copy link
Member

Choose a reason for hiding this comment

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

fair enough

Usage: "InfluxDB `host` tag attached to all measurements",
Value: "localhost",
}
)

// MakeDataDir retrieves the currently requested data directory, terminating
Expand Down Expand Up @@ -1181,6 +1218,27 @@ func SetupNetwork(ctx *cli.Context) {
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.
func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
var (
Expand Down
12 changes: 6 additions & 6 deletions metrics/influxdb/influxdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package influxdb

import (
"fmt"
"log"
uurl "net/url"
"time"

"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/influxdata/influxdb/client"
)
Expand Down Expand Up @@ -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) {
u, err := uurl.Parse(url)
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
}

Expand All @@ -51,7 +51,7 @@ func InfluxDBWithTags(r metrics.Registry, d time.Duration, url, database, userna
cache: make(map[string]int64),
}
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
}

Expand All @@ -76,15 +76,15 @@ func (r *reporter) run() {
select {
case <-intervalTicker:
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:
_, _, err := r.client.Ping()
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 {
log.Printf("unable to make InfluxDB client. err=%v", err)
log.Warn("Unable to make InfluxDB client", "err", err)
}
}
}
Expand Down