swarm: initialise metrics collection and add ResettingTimer to HTTP requests

This commit is contained in:
Anton Evangelatov 2018-01-24 12:57:50 +02:00
parent 89dfc96ec3
commit b7516e4540
7 changed files with 101 additions and 22 deletions

View file

@ -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()

View file

@ -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 {

View file

@ -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)

View file

@ -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, "/"))

View file

@ -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
}

79
swarm/metrics/flags.go Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
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,
})
}
}

View file

@ -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
}