diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index 5eb1f26072..360020b77b 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -43,6 +43,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/swarm" bzzapi "github.com/ethereum/go-ethereum/swarm/api" + swarmmetrics "github.com/ethereum/go-ethereum/swarm/metrics" "gopkg.in/urfave/cli.v1" ) @@ -334,7 +335,6 @@ DEPRECATED: use 'swarm db clean'. utils.IPCDisabledFlag, utils.IPCPathFlag, utils.PasswordFileFlag, - utils.MetricsEnabledFlag, // bzzd-specific flags CorsStringFlag, EnsAPIFlag, @@ -360,9 +360,14 @@ DEPRECATED: use 'swarm db clean'. DeprecatedEnsAddrFlag, } app.Flags = append(app.Flags, debug.Flags...) + app.Flags = append(app.Flags, swarmmetrics.Flags...) app.Before = func(ctx *cli.Context) error { runtime.GOMAXPROCS(runtime.NumCPU()) - return debug.Setup(ctx) + if err := debug.Setup(ctx); err != nil { + return err + } + swarmmetrics.Setup(ctx) + return nil } app.After = func(ctx *cli.Context) error { debug.Exit() diff --git a/metrics/metrics.go b/metrics/metrics.go index a4318b6822..6143fe2875 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -38,6 +38,15 @@ func init() { //exp.Exp(DefaultRegistry) } +// NewResettingTimer create a new ResettingTimer, either a real one of a NOP stub depending +// on the metrics flag. +func NewResettingTimer(name string) metrics.ResettingTimer { + if !Enabled { + return new(metrics.NilResettingTimer) + } + return metrics.GetOrRegisterResettingTimer(name, metrics.DefaultRegistry) +} + // NewGauge creates a new metrics Gauge, either a real one of a NOP stub depending // on the metrics flag. func NewGauge(name string) metrics.Gauge { diff --git a/swarm/api/api.go b/swarm/api/api.go index 19667d7a7b..aca5ca7750 100644 --- a/swarm/api/api.go +++ b/swarm/api/api.go @@ -46,7 +46,7 @@ var ( apiPutFail = metrics.NewCounter("api.put.fail") apiGetCount = metrics.NewCounter("api.get.count") apiGetNotFound = metrics.NewCounter("api.get.notfound") - apiGetHttp300 = metrics.NewCounter("api.get.http300") + apiGetHttp300 = metrics.NewCounter("api.get.http.300") apiModifyCount = metrics.NewCounter("api.modify.count") apiModifyFail = metrics.NewCounter("api.modify.fail") apiAddFileCount = metrics.NewCounter("api.addfile.count") @@ -55,8 +55,8 @@ var ( apiRmFileFail = metrics.NewCounter("api.removefile.fail") apiAppendFileCount = metrics.NewCounter("api.appendfile.count") apiAppendFileFail = metrics.NewCounter("api.appendfile.fail") - apiBuildDirTreeCount = metrics.NewCounter("api.builddirtree.fail") - apiBuildDirTreeFail = metrics.NewCounter("api.builddirtree.count") + apiBuildDirTreeCount = metrics.NewCounter("api.builddirtree.count") + apiBuildDirTreeFail = metrics.NewCounter("api.builddirtree.fail") ) type Resolver interface { @@ -295,7 +295,6 @@ func (self *Api) Modify(key storage.Key, path, contentHash, contentType string) } func (self *Api) AddFile(mhash, path, fname string, content []byte, nameresolver bool) (storage.Key, string, error) { - apiAddFileCount.Inc(1) uri, err := Parse("bzz:/" + mhash) @@ -346,7 +345,6 @@ func (self *Api) AddFile(mhash, path, fname string, content []byte, nameresolver } func (self *Api) RemoveFile(mhash, path, fname string, nameresolver bool) (string, error) { - apiRmFileCount.Inc(1) uri, err := Parse("bzz:/" + mhash) @@ -388,7 +386,6 @@ func (self *Api) RemoveFile(mhash, path, fname string, nameresolver bool) (strin } func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, content []byte, oldKey storage.Key, offset int64, addSize int64, nameresolver bool) (storage.Key, string, error) { - apiAppendFileCount.Inc(1) buffSize := offset + addSize @@ -470,7 +467,6 @@ func (self *Api) AppendFile(mhash, path, fname string, existingSize int64, conte } func (self *Api) BuildDirectoryTree(mhash string, nameresolver bool) (key storage.Key, manifestEntryMap map[string]*manifestTrieEntry, err error) { - apiBuildDirTreeCount.Inc(1) uri, err := Parse("bzz:/" + mhash) diff --git a/swarm/api/http/server.go b/swarm/api/http/server.go index a83fc3cbd0..b9c2e4c24e 100644 --- a/swarm/api/http/server.go +++ b/swarm/api/http/server.go @@ -646,6 +646,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { requestCount.Inc(1) startTime := time.Now() defer requestTimer.UpdateSince(startTime) + defer metrics.NewResettingTimer("http.request.time_resetting").UpdateSince(startTime) s.logDebug("HTTP %s request URL: '%s', Host: '%s', Path: '%s', Referer: '%s', Accept: '%s'", r.Method, r.RequestURI, r.URL.Host, r.URL.Path, r.Referer(), r.Header.Get("Accept")) uri, err := api.Parse(strings.TrimLeft(r.URL.Path, "/")) diff --git a/swarm/fuse/swarmfs_util.go b/swarm/fuse/swarmfs_util.go index d39966c0e3..169b674876 100644 --- a/swarm/fuse/swarmfs_util.go +++ b/swarm/fuse/swarmfs_util.go @@ -47,7 +47,6 @@ func externalUnmount(mountPoint string) error { } func addFileToSwarm(sf *SwarmFile, content []byte, size int) error { - fkey, mhash, err := sf.mountInfo.swarmApi.AddFile(sf.mountInfo.LatestManifest, sf.path, sf.name, content, true) if err != nil { return err @@ -64,11 +63,9 @@ func addFileToSwarm(sf *SwarmFile, content []byte, size int) error { log.Info("Added new file:", "fname", sf.name, "New Manifest hash", mhash) return nil - } func removeFileFromSwarm(sf *SwarmFile) error { - mkey, err := sf.mountInfo.swarmApi.RemoveFile(sf.mountInfo.LatestManifest, sf.path, sf.name, true) if err != nil { return err @@ -83,7 +80,6 @@ func removeFileFromSwarm(sf *SwarmFile) error { } func removeDirectoryFromSwarm(sd *SwarmDir) error { - if len(sd.directories) == 0 && len(sd.files) == 0 { return nil } @@ -103,11 +99,9 @@ func removeDirectoryFromSwarm(sd *SwarmDir) error { } return nil - } func appendToExistingFileInSwarm(sf *SwarmFile, content []byte, offset int64, length int64) error { - fkey, mhash, err := sf.mountInfo.swarmApi.AppendFile(sf.mountInfo.LatestManifest, sf.path, sf.name, sf.fileSize, content, sf.key, offset, length, true) if err != nil { return err @@ -124,5 +118,4 @@ func appendToExistingFileInSwarm(sf *SwarmFile, content []byte, offset int64, le log.Info("Appended file:", "fname", sf.name, "New Manifest hash", mhash) return nil - } diff --git a/swarm/metrics/flags.go b/swarm/metrics/flags.go new file mode 100644 index 0000000000..ea2afd071f --- /dev/null +++ b/swarm/metrics/flags.go @@ -0,0 +1,79 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package metrics + +import ( + "time" + + "github.com/ethereum/go-ethereum/cmd/utils" + "github.com/ethereum/go-ethereum/log" + gethmetrics "github.com/ethereum/go-ethereum/metrics" + metrics "github.com/ethersphere/go-metrics" + influxdb "github.com/ethersphere/go-metrics-influxdb" + "gopkg.in/urfave/cli.v1" +) + +var ( + metricsEndpointFlag = cli.StringFlag{ + Name: "metricsendpoint", + Usage: "metrics backend endpoint", + Value: "http://127.0.0.1:8086", + } + metricsDatabaseFlag = cli.StringFlag{ + Name: "metricsdatabase", + Usage: "metrics backend database", + Value: "metrics", + } + metricsUsernameFlag = cli.StringFlag{ + Name: "metricsusername", + Usage: "metrics backend username", + Value: "admin", + } + metricsPasswordFlag = cli.StringFlag{ + Name: "metricspassword", + Usage: "metrics backend password", + Value: "admin", + } + metricsHostTagFlag = cli.StringFlag{ + Name: "metricshosttag", + Usage: "metrics host tag", + Value: "localhost", + } +) + +// Flags holds all command-line flags required for metrics collection. +var Flags = []cli.Flag{ + utils.MetricsEnabledFlag, + metricsEndpointFlag, metricsDatabaseFlag, metricsUsernameFlag, metricsPasswordFlag, metricsHostTagFlag, +} + +func Setup(ctx *cli.Context) { + if gethmetrics.Enabled { + var ( + endpoint = ctx.GlobalString(metricsEndpointFlag.Name) + database = ctx.GlobalString(metricsDatabaseFlag.Name) + username = ctx.GlobalString(metricsUsernameFlag.Name) + password = ctx.GlobalString(metricsPasswordFlag.Name) + hosttag = ctx.GlobalString(metricsHostTagFlag.Name) + ) + + log.Info("Enabling swarm metrics collection and export") + go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "swarm.", map[string]string{ + "host": hosttag, + }) + } +} diff --git a/swarm/swarm.go b/swarm/swarm.go index f7806aff01..9db386ee64 100644 --- a/swarm/swarm.go +++ b/swarm/swarm.go @@ -45,16 +45,14 @@ import ( "github.com/ethereum/go-ethereum/swarm/fuse" "github.com/ethereum/go-ethereum/swarm/network" "github.com/ethereum/go-ethereum/swarm/storage" - - gometrics "github.com/rcrowley/go-metrics" ) var ( - runTimer gometrics.Timer startTime time.Time metricsTimeout = 5 * time.Second startCounter = metrics.NewCounter("stack,start") stopCounter = metrics.NewCounter("stack,stop") + uptimeGauge = metrics.NewGauge("stack.uptime") dbSizeGauge = metrics.NewGauge("storage.db.chunks.size") cacheSizeGauge = metrics.NewGauge("storage.db.cache.size") ) @@ -275,7 +273,6 @@ Start is called when the stack is started */ // implements the node.Service interface func (self *Swarm) Start(srv *p2p.Server) error { - runTimer = metrics.NewTimer("stack,uptime") startTime = time.Now() connectPeer := func(url string) error { node, err := discover.ParseNode(url) @@ -342,7 +339,7 @@ func (self *Swarm) metricsLoop() { func (self *Swarm) sendMetrics() { dbSizeGauge.Update(int64(self.lstore.DbCounter())) cacheSizeGauge.Update(int64(self.lstore.CacheCounter())) - runTimer.UpdateSince(startTime) + uptimeGauge.Update(time.Since(startTime).Nanoseconds()) } // implements the node.Service interface @@ -360,7 +357,6 @@ func (self *Swarm) Stop() error { } self.sfs.Stop() stopCounter.Inc(1) - runTimer.UpdateSince(startTime) return err }