Commit 8a2644dd authored by Svetomir Smiljkovic's avatar Svetomir Smiljkovic

Merge branch 'master' of https://github.com/janos/bee

parents a51aaf38 f9c58e64
Copyright (c) 2020 The Swarm Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
......@@ -18,13 +18,13 @@ Docker image `janos/bee`.
Execute the command terminals to start `node 1`:
```sh
bee start --api-addr :8501 --p2p-addr :30401
bee start --api-addr :8501 --p2p-addr :30401 --debug-api-addr :6061
```
Use one of the multiaddresses as bootnode for `node 2` in order to connect them:
```sh
bee start --api-addr :8502 --p2p-addr :30402 --bootnode /ip4/127.0.0.1/tcp/30401/p2p/QmT4TNB4cKYanUjdYodw1Cns8cuVaRVo24hHNYcT7JjkTB
bee start --api-addr :8502 --p2p-addr :30402 --debug-api-addr :6062 --bootnode /ip4/127.0.0.1/tcp/30401/p2p/QmT4TNB4cKYanUjdYodw1Cns8cuVaRVo24hHNYcT7JjkTB
```
Use the last part of `node 1` multiaddress to ping it using `node 2` by making an HTTP request to `localhost:{PORT2}/pingpong/{ID1}` like:
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cmd
import (
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cmd_test
import (
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cmd
import "io"
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cmd
import (
......@@ -22,12 +26,15 @@ import (
func (c *command) initStartCmd() (err error) {
const (
optionNameAPIAddr = "api-addr"
optionNameP2PAddr = "p2p-addr"
optionNameP2PDisableWS = "p2p-disable-ws"
optionNameP2PDisableQUIC = "p2p-disable-quic"
optionNameDebugAPIAddr = "debug-api-addr"
optionNameBootnodes = "bootnode"
optionNameAPIAddr = "api-addr"
optionNameP2PAddr = "p2p-addr"
optionNameP2PDisableWS = "p2p-disable-ws"
optionNameP2PDisableQUIC = "p2p-disable-quic"
optionNameDebugAPIAddr = "debug-api-addr"
optionNameBootnodes = "bootnode"
optionNameConnectionsLow = "connections-low"
optionNameConnectionsHigh = "connections-high"
optionNameConnectionsGrace = "connections-grace"
)
cmd := &cobra.Command{
......@@ -41,18 +48,15 @@ func (c *command) initStartCmd() (err error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
//var idht *dht.IpfsDHT
// Construct P2P service.
p2ps, err := libp2p.New(ctx, libp2p.Options{
Addr: c.config.GetString(optionNameP2PAddr),
DisableWS: c.config.GetBool(optionNameP2PDisableWS),
DisableQUIC: c.config.GetBool(optionNameP2PDisableQUIC),
Bootnodes: c.config.GetStringSlice(optionNameBootnodes),
// Routing: func(h host.Host) (r routing.PeerRouting, err error) {
// idht, err = dht.New(ctx, h)
// return idht, err
// },
Addr: c.config.GetString(optionNameP2PAddr),
DisableWS: c.config.GetBool(optionNameP2PDisableWS),
DisableQUIC: c.config.GetBool(optionNameP2PDisableQUIC),
Bootnodes: c.config.GetStringSlice(optionNameBootnodes),
ConnectionsLow: c.config.GetInt(optionNameConnectionsLow),
ConnectionsHigh: c.config.GetInt(optionNameConnectionsHigh),
ConnectionsGrace: c.config.GetDuration(optionNameConnectionsGrace),
})
if err != nil {
return fmt.Errorf("p2p service: %w", err)
......@@ -76,14 +80,15 @@ func (c *command) initStartCmd() (err error) {
}
// API server
apiService := api.New(api.Options{
P2P: p2ps,
Pingpong: pingPong,
})
apiListener, err := net.Listen("tcp", c.config.GetString(optionNameAPIAddr))
if err != nil {
return fmt.Errorf("api listener: %w", err)
}
apiServer := &http.Server{Handler: api.New(api.Options{
P2P: p2ps,
Pingpong: pingPong,
})}
apiServer := &http.Server{Handler: apiService}
go func() {
cmd.Println("api address:", apiListener.Addr())
......@@ -93,20 +98,30 @@ func (c *command) initStartCmd() (err error) {
}
}()
// Debug API server
debugAPIListener, err := net.Listen("tcp", c.config.GetString(optionNameDebugAPIAddr))
if err != nil {
return fmt.Errorf("debug api listener: %w", err)
}
debugAPIServer := &http.Server{Handler: debugapi.New(debugapi.Options{})}
var debugAPIServer *http.Server
if addr := c.config.GetString(optionNameDebugAPIAddr); addr != "" {
// Debug API server
debugAPIService := debugapi.New(debugapi.Options{})
// register metrics from components
debugAPIService.MustRegisterMetrics(p2ps.Metrics()...)
debugAPIService.MustRegisterMetrics(pingPong.Metrics()...)
debugAPIService.MustRegisterMetrics(apiService.Metrics()...)
debugAPIListener, err := net.Listen("tcp", addr)
if err != nil {
return fmt.Errorf("debug api listener: %w", err)
}
go func() {
cmd.Println("debug api address:", debugAPIListener.Addr())
debugAPIServer := &http.Server{Handler: debugAPIService}
if err := debugAPIServer.Serve(debugAPIListener); err != nil && err != http.ErrServerClosed {
log.Println("debug api server:", err)
}
}()
go func() {
cmd.Println("debug api address:", debugAPIListener.Addr())
if err := debugAPIServer.Serve(debugAPIListener); err != nil && err != http.ErrServerClosed {
log.Println("debug api server:", err)
}
}()
}
// Wait for termination or interrupt signals.
// We want to clean up things at the end.
......@@ -135,8 +150,10 @@ func (c *command) initStartCmd() (err error) {
log.Println("api server shutdown:", err)
}
if err := debugAPIServer.Shutdown(ctx); err != nil {
log.Println("debug api server shutdown:", err)
if debugAPIServer != nil {
if err := debugAPIServer.Shutdown(ctx); err != nil {
log.Println("debug api server shutdown:", err)
}
}
if err := p2ps.Close(); err != nil {
......@@ -162,6 +179,9 @@ func (c *command) initStartCmd() (err error) {
cmd.Flags().Bool(optionNameP2PDisableQUIC, false, "disable P2P QUIC protocol")
cmd.Flags().StringSlice(optionNameBootnodes, nil, "initial nodes to connect to")
cmd.Flags().String(optionNameDebugAPIAddr, ":6060", "Debug HTTP API listen address")
cmd.Flags().Int(optionNameConnectionsLow, 200, "low watermark governing the number of connections that'll be maintained")
cmd.Flags().Int(optionNameConnectionsHigh, 400, "high watermark governing the number of connections that'll be maintained")
cmd.Flags().Duration(optionNameConnectionsGrace, time.Minute, "the amount of time a newly opened connection is given before it becomes subject to pruning")
if err := c.config.BindPFlags(cmd.Flags()); err != nil {
return err
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cmd
import (
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cmd_test
import (
......
package main
// import (
// "context"
// "flag"
// "fmt"
// "log"
// "net"
// "net/http"
// "github.com/janos/bee/pkg/api"
// "github.com/janos/bee/pkg/p2p/libp2p"
// "github.com/janos/bee/pkg/pingpong"
// )
// var addr = flag.String("addr", ":0", "http api listen address")
// func main() {
// flag.Parse()
// ctx, cancel := context.WithCancel(context.Background())
// defer cancel()
// //var idht *dht.IpfsDHT
// // Construct P2P service.
// p2ps, err := libp2p.New(ctx, libp2p.Options{
// // Routing: func(h host.Host) (r routing.PeerRouting, err error) {
// // idht, err = dht.New(ctx, h)
// // return idht, err
// // },
// })
// if err != nil {
// log.Fatal("p2p service: ", err)
// }
// // Construct protocols.
// pingPong := pingpong.New(p2ps)
// // Add protocols to the P2P service.
// if err = p2ps.AddProtocol(pingPong.Protocol()); err != nil {
// log.Fatal("pingpong service: ", err)
// }
// addrs, err := p2ps.Addresses()
// if err != nil {
// log.Fatal("get server addresses: ", err)
// }
// for _, addr := range addrs {
// fmt.Println(addr)
// }
// h := api.New(api.Options{
// P2P: p2ps,
// Pingpong: pingPong,
// })
// l, err := net.Listen("tcp", *addr)
// if err != nil {
// log.Fatal("tcp: ", err)
// }
// log.Println("listening: ", l.Addr())
// log.Fatal(http.Serve(l, h))
// }
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package bee is the root package of Ethereum Swarm node implementation.
package bee
......@@ -18,6 +18,7 @@ require (
github.com/mitchellh/go-homedir v1.1.0
github.com/multiformats/go-multiaddr v0.2.0
github.com/multiformats/go-multistream v0.1.0
github.com/prometheus/client_golang v1.3.0
github.com/spf13/cobra v0.0.5
github.com/spf13/viper v1.6.1
resenje.org/web v0.4.0
......
......@@ -13,6 +13,7 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
......@@ -28,7 +29,9 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
......@@ -292,6 +295,7 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
......@@ -369,20 +373,24 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0 h1:miYCvYqFXtl/J9FIy8eNpBfYthAEFg+Ys0XyUVEcDsc=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0 h1:ElTg5tNp4DqfV7UQjDqv2+RJlNzsDtvNAWccbItceIE=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package api
import (
......@@ -5,11 +9,18 @@ import (
"github.com/janos/bee/pkg/p2p"
"github.com/janos/bee/pkg/pingpong"
"github.com/prometheus/client_golang/prometheus"
)
type Service interface {
http.Handler
Metrics() (cs []prometheus.Collector)
}
type server struct {
Options
http.Handler
metrics metrics
}
type Options struct {
......@@ -17,9 +28,10 @@ type Options struct {
Pingpong *pingpong.Service
}
func New(o Options) http.Handler {
func New(o Options) Service {
s := &server{
Options: o,
metrics: newMetrics(),
}
s.setupRouting()
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package api
import (
"net/http"
"time"
m "github.com/janos/bee/pkg/metrics"
"github.com/prometheus/client_golang/prometheus"
)
type metrics struct {
// all metrics fields must be exported
// to be able to return them by Metrics()
// using reflection
RequestCount prometheus.Counter
ResponseDuration prometheus.Histogram
PingRequestCount prometheus.Counter
}
func newMetrics() (m metrics) {
return metrics{
RequestCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "api_request_count",
Help: "Number of API requests.",
}),
ResponseDuration: prometheus.NewHistogram(prometheus.HistogramOpts{
Name: "api_response_duration_seconds",
Help: "Histogram of API response durations.",
Buckets: []float64{0.01, 0.1, 0.25, 0.5, 1, 2.5, 5, 10},
}),
PingRequestCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "api_ping_request_count",
Help: "Number HTTP API ping requests.",
}),
}
}
func (s *server) Metrics() []prometheus.Collector {
return m.PrometheusCollectorsFromFields(s.metrics)
}
func (s *server) pageviewMetricsHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
s.metrics.RequestCount.Inc()
h.ServeHTTP(w, r)
s.metrics.ResponseDuration.Observe(time.Since(start).Seconds())
})
}
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package api
import (
......@@ -17,6 +21,7 @@ func (s *server) pingpongHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "ping error", peerID, err)
return
}
s.metrics.PingRequestCount.Inc()
fmt.Fprintln(w, "RTT", rtt)
}
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package api
import (
......@@ -20,6 +24,7 @@ func (s *server) setupRouting() {
s.Handler = web.ChainHandlers(
handlers.CompressHandler,
s.pageviewMetricsHandler,
web.FinalHandler(baseRouter),
)
}
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package debugapi
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
)
type Service interface {
http.Handler
MustRegisterMetrics(cs ...prometheus.Collector)
}
type server struct {
Options
http.Handler
metricsRegistry *prometheus.Registry
}
type Options struct{}
func New(o Options) http.Handler {
func New(o Options) Service {
s := &server{
Options: o,
Options: o,
metricsRegistry: newMetricsRegistry(),
}
s.setupRouting()
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package debugapi
import (
"github.com/janos/bee"
"github.com/prometheus/client_golang/prometheus"
)
func newMetricsRegistry() (r *prometheus.Registry) {
r = prometheus.NewRegistry()
// register standard metrics
r.MustRegister(
prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}),
prometheus.NewGoCollector(),
prometheus.NewGauge(prometheus.GaugeOpts{
Name: "bee_info",
Help: "Bee information.",
ConstLabels: prometheus.Labels{
"version": bee.Version,
},
}),
)
return r
}
func (s *server) MustRegisterMetrics(cs ...prometheus.Collector) {
s.metricsRegistry.MustRegister(cs...)
}
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package debugapi
import (
......@@ -6,12 +10,18 @@ import (
"net/http/pprof"
"github.com/gorilla/handlers"
"github.com/prometheus/client_golang/prometheus/promhttp"
"resenje.org/web"
)
func (s *server) setupRouting() {
internalBaseRouter := http.NewServeMux()
internalBaseRouter.Handle("/metrics", promhttp.InstrumentMetricHandler(
s.metricsRegistry,
promhttp.HandlerFor(s.metricsRegistry, promhttp.HandlerOpts{}),
))
internalRouter := http.NewServeMux()
internalBaseRouter.Handle("/", web.ChainHandlers(
handlers.CompressHandler,
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package debugapi
import (
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package metrics
import (
"reflect"
"github.com/prometheus/client_golang/prometheus"
)
func PrometheusCollectorsFromFields(i interface{}) (cs []prometheus.Collector) {
v := reflect.Indirect(reflect.ValueOf(i))
for i := 0; i < v.NumField(); i++ {
if !v.Field(i).CanInterface() {
continue
}
if u, ok := v.Field(i).Interface().(prometheus.Collector); ok {
cs = append(cs, u)
}
}
return cs
}
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package libp2p
import (
......@@ -26,16 +30,18 @@ import (
var _ p2p.Service = new(Service)
type Service struct {
host host.Host
host host.Host
metrics metrics
}
type Options struct {
Addr string
DisableWS bool
DisableQUIC bool
Bootnodes []string
// PrivKey []byte
// Routing func(host.Host) (routing.PeerRouting, error)
Addr string
DisableWS bool
DisableQUIC bool
Bootnodes []string
ConnectionsLow int
ConnectionsHigh int
ConnectionsGrace time.Duration
}
func New(ctx context.Context, o Options) (*Service, error) {
......@@ -89,25 +95,24 @@ func New(ctx context.Context, o Options) (*Service, error) {
libp2p.Security(libp2ptls.ID, libp2ptls.New),
// support secio connections
libp2p.Security(secio.ID, secio.New),
// support QUIC - experimental
libp2p.Transport(libp2pquic.NewTransport),
// support any other default transports (TCP)
libp2p.DefaultTransports,
// Let's prevent our peer from having too many
// connections by attaching a connection manager.
libp2p.ConnectionManager(connmgr.NewConnManager(
100, // Lowwater
400, // HighWater,
time.Minute, // GracePeriod
o.ConnectionsLow,
o.ConnectionsHigh,
o.ConnectionsGrace,
)),
// Attempt to open ports using uPNP for NATed hosts.
libp2p.NATPortMap(),
// Let this host use the DHT to find other hosts
//libp2p.Routing(o.Routing),
// Let this host use relays and advertise itself on relays if
// it finds it is behind NAT. Use libp2p.Relay(options...) to
// enable active relays and more.
//libp2p.EnableAutoRelay(),
}
if !o.DisableQUIC {
opts = append(opts,
// support QUIC - experimental
libp2p.Transport(libp2pquic.NewTransport),
)
}
h, err := libp2p.New(ctx, opts...)
......@@ -129,7 +134,10 @@ func New(ctx context.Context, o Options) (*Service, error) {
return nil, fmt.Errorf("autonat: %w", err)
}
s := &Service{host: h}
s := &Service{
host: h,
metrics: newMetrics(),
}
// TODO: be more resilient on connection errors and connect in parallel
for _, a := range o.Bootnodes {
......@@ -143,6 +151,10 @@ func New(ctx context.Context, o Options) (*Service, error) {
}
}
h.Network().SetConnHandler(func(_ network.Conn) {
s.metrics.HandledConnectionCount.Inc()
})
return s, nil
}
......@@ -153,10 +165,11 @@ func (s *Service) AddProtocol(p p2p.ProtocolSpec) (err error) {
if err != nil {
return fmt.Errorf("match semver %s: %w", id, err)
}
s.host.SetStreamHandlerMatch(id, matcher, func(s network.Stream) {
s.host.SetStreamHandlerMatch(id, matcher, func(stream network.Stream) {
s.metrics.HandledStreamCount.Inc()
ss.Handler(p2p.Peer{
Addr: s.Conn().RemoteMultiaddr(),
Stream: s,
Addr: stream.Conn().RemoteMultiaddr(),
Stream: stream,
})
})
}
......@@ -189,6 +202,8 @@ func (s *Service) Connect(ctx context.Context, addr ma.Multiaddr) (peerID string
return "", err
}
s.metrics.CreatedConnectionCount.Inc()
return info.ID.String(), nil
}
......@@ -205,6 +220,7 @@ func (s *Service) NewStream(ctx context.Context, peerID, protocolName, streamNam
}
return nil, fmt.Errorf("create stream %q to %q: %w", swarmStreamName, peerID, err)
}
s.metrics.CreatedStreamCount.Inc()
return st, nil
}
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package libp2p
import (
m "github.com/janos/bee/pkg/metrics"
"github.com/prometheus/client_golang/prometheus"
)
type metrics struct {
// all metrics fields must be exported
// to be able to return them by Metrics()
// using reflection
CreatedConnectionCount prometheus.Counter
HandledConnectionCount prometheus.Counter
CreatedStreamCount prometheus.Counter
HandledStreamCount prometheus.Counter
}
func newMetrics() (m metrics) {
return metrics{
CreatedConnectionCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "libp2p_created_connection_count",
Help: "Number of initiated outgoing libp2p connections.",
}),
HandledConnectionCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "libp2p_handled_connection_count",
Help: "Number of handled incoming libp2p connections.",
}),
CreatedStreamCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "libp2p_created_stream_count",
Help: "Number of initiated outgoing libp2p streams.",
}),
HandledStreamCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "libp2p_handled_stream_count",
Help: "Number of handled incoming libp2p streams.",
}),
}
}
func (s *Service) Metrics() []prometheus.Collector {
return m.PrometheusCollectorsFromFields(s.metrics)
}
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mock
import (
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p2p
import (
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package protobuf
import (
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package pingpong
import (
m "github.com/janos/bee/pkg/metrics"
"github.com/prometheus/client_golang/prometheus"
)
type metrics struct {
// all metrics fields must be exported
// to be able to return them by Metrics()
// using reflection
PingSentCount prometheus.Counter
PongSentCount prometheus.Counter
PingReceivedCount prometheus.Counter
PongReceivedCount prometheus.Counter
}
func newMetrics() (m metrics) {
return metrics{
PingSentCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "pingpong_ping_sent_count",
Help: "Number ping requests sent.",
}),
PongSentCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "pingpong_pong_sent_count",
Help: "Number of pong responses sent.",
}),
PingReceivedCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "pingpong_ping_received_count",
Help: "Number ping requests received.",
}),
PongReceivedCount: prometheus.NewCounter(prometheus.CounterOpts{
Name: "pingpong_pong_received_count",
Help: "Number of pong responses received.",
}),
}
}
func (s *Service) Metrics() []prometheus.Collector {
return m.PrometheusCollectorsFromFields(s.metrics)
}
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate sh -c "protoc -I . -I \"$(go list -f '{{ .Dir }}' -m github.com/gogo/protobuf)/protobuf\" --gogofaster_out=. pingpong.proto"
package pingpong
......@@ -21,10 +25,14 @@ const (
type Service struct {
streamer p2p.Streamer
metrics metrics
}
func New(streamer p2p.Streamer) *Service {
return &Service{streamer: streamer}
return &Service{
streamer: streamer,
metrics: newMetrics(),
}
}
func (s *Service) Protocol() p2p.ProtocolSpec {
......@@ -54,6 +62,7 @@ func (s *Service) Handler(p p2p.Peer) {
return
}
log.Printf("got ping: %q\n", ping.Greeting)
s.metrics.PingReceivedCount.Inc()
if err := w.WriteMsg(&Pong{
Response: "{" + ping.Greeting + "}",
......@@ -61,6 +70,7 @@ func (s *Service) Handler(p p2p.Peer) {
log.Printf("pingpong handler: write message: %v\n", err)
return
}
s.metrics.PongSentCount.Inc()
}
}
......@@ -81,6 +91,7 @@ func (s *Service) Ping(ctx context.Context, peerID string, msgs ...string) (rtt
}); err != nil {
return 0, fmt.Errorf("stream write: %w", err)
}
s.metrics.PingSentCount.Inc()
if err := r.ReadMsg(&pong); err != nil {
if err == io.EOF {
......@@ -90,6 +101,7 @@ func (s *Service) Ping(ctx context.Context, peerID string, msgs ...string) (rtt
}
log.Printf("got pong: %q\n", pong.Response)
s.metrics.PongReceivedCount.Inc()
}
return time.Since(start) / time.Duration(len(msgs)), nil
}
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
syntax = "proto3";
package pingpong;
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package pingpong_test
import (
......
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bee
var (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment