mirror of
https://github.com/ipfs/kubo.git
synced 2026-03-09 18:28:08 +08:00
metrics: add prometheus back
With a proper IpfsCollector object and tests, this time. The collector object makes it easy to add further metrics, like e.g. bitswap wants/provs. License: MIT Signed-off-by: Lars Gierth <larsg@systemli.org>
This commit is contained in:
parent
daaa69e276
commit
caec086c28
@ -27,6 +27,7 @@ import (
|
||||
util "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
|
||||
conn "gx/ipfs/QmccGfZs3rzku8Bv6sTPH3bMUKD1EVod8srgRjt5csdmva/go-libp2p/p2p/net/conn"
|
||||
peer "gx/ipfs/QmccGfZs3rzku8Bv6sTPH3bMUKD1EVod8srgRjt5csdmva/go-libp2p/p2p/peer"
|
||||
prometheus "gx/ipfs/QmdhsRK1EK2fvAz2i2SH5DEfkL6seDuyMYEsxKa9Braim3/client_golang/prometheus"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -314,6 +315,10 @@ func daemonFunc(req cmds.Request, res cmds.Response) {
|
||||
return
|
||||
}
|
||||
|
||||
// initialize metrics collector
|
||||
prometheus.MustRegisterOrGet(&corehttp.IpfsNodeCollector{Node: node})
|
||||
prometheus.EnableCollectChecks(true)
|
||||
|
||||
fmt.Printf("Daemon is ready\n")
|
||||
// collect long-running errors and block for shutdown
|
||||
// TODO(cryptix): our fuse currently doesnt follow this pattern for graceful shutdown
|
||||
@ -376,15 +381,15 @@ func serveHTTPApi(req cmds.Request) (error, <-chan error) {
|
||||
},
|
||||
})
|
||||
var opts = []corehttp.ServeOption{
|
||||
corehttp.PrometheusCollectorOption("api"),
|
||||
corehttp.MetricsCollectionOption("api"),
|
||||
corehttp.CommandsOption(*req.InvocContext()),
|
||||
corehttp.WebUIOption,
|
||||
apiGw.ServeOption(),
|
||||
corehttp.VersionOption(),
|
||||
defaultMux("/debug/vars"),
|
||||
defaultMux("/debug/pprof/"),
|
||||
corehttp.MetricsScrapingOption("/debug/metrics/prometheus"),
|
||||
corehttp.LogOption(),
|
||||
corehttp.PrometheusOption("/debug/metrics/prometheus"),
|
||||
}
|
||||
|
||||
if len(cfg.Gateway.RootRedirect) > 0 {
|
||||
@ -455,7 +460,7 @@ func serveHTTPGateway(req cmds.Request) (error, <-chan error) {
|
||||
}
|
||||
|
||||
var opts = []corehttp.ServeOption{
|
||||
corehttp.PrometheusCollectorOption("gateway"),
|
||||
corehttp.MetricsCollectionOption("gateway"),
|
||||
corehttp.CommandsROOption(*req.InvocContext()),
|
||||
corehttp.VersionOption(),
|
||||
corehttp.IPNSHostnameOption(),
|
||||
|
||||
53
core/corehttp/metrics.go
Normal file
53
core/corehttp/metrics.go
Normal file
@ -0,0 +1,53 @@
|
||||
package corehttp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
prometheus "gx/ipfs/QmdhsRK1EK2fvAz2i2SH5DEfkL6seDuyMYEsxKa9Braim3/client_golang/prometheus"
|
||||
|
||||
core "github.com/ipfs/go-ipfs/core"
|
||||
)
|
||||
|
||||
// This adds the scraping endpoint which Prometheus uses to fetch metrics.
|
||||
func MetricsScrapingOption(path string) ServeOption {
|
||||
return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
|
||||
mux.Handle(path, prometheus.UninstrumentedHandler())
|
||||
return mux, nil
|
||||
}
|
||||
}
|
||||
|
||||
// This adds collection of net/http-related metrics
|
||||
func MetricsCollectionOption(handlerName string) ServeOption {
|
||||
return func(_ *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
|
||||
childMux := http.NewServeMux()
|
||||
mux.HandleFunc("/", prometheus.InstrumentHandler(handlerName, childMux))
|
||||
return childMux, nil
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
peersTotalMetric = prometheus.NewDesc(
|
||||
prometheus.BuildFQName("ipfs", "p2p", "peers_total"),
|
||||
"Number of connected peers", nil, nil)
|
||||
)
|
||||
|
||||
type IpfsNodeCollector struct {
|
||||
Node *core.IpfsNode
|
||||
}
|
||||
|
||||
func (_ IpfsNodeCollector) Describe(ch chan<- *prometheus.Desc) {
|
||||
ch <- peersTotalMetric
|
||||
}
|
||||
|
||||
func (c IpfsNodeCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
peersTotalMetric,
|
||||
prometheus.GaugeValue,
|
||||
c.PeersTotalValue(),
|
||||
)
|
||||
}
|
||||
|
||||
func (c IpfsNodeCollector) PeersTotalValue() float64 {
|
||||
return float64(len(c.Node.PeerHost.Network().Conns()))
|
||||
}
|
||||
46
core/corehttp/metrics_test.go
Normal file
46
core/corehttp/metrics_test.go
Normal file
@ -0,0 +1,46 @@
|
||||
package corehttp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
core "github.com/ipfs/go-ipfs/core"
|
||||
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
|
||||
bhost "gx/ipfs/QmccGfZs3rzku8Bv6sTPH3bMUKD1EVod8srgRjt5csdmva/go-libp2p/p2p/host/basic"
|
||||
inet "gx/ipfs/QmccGfZs3rzku8Bv6sTPH3bMUKD1EVod8srgRjt5csdmva/go-libp2p/p2p/net"
|
||||
testutil "gx/ipfs/QmccGfZs3rzku8Bv6sTPH3bMUKD1EVod8srgRjt5csdmva/go-libp2p/p2p/test/util"
|
||||
)
|
||||
|
||||
// This test is based on go-libp2p/p2p/net/swarm.TestConnectednessCorrect
|
||||
// It builds 4 nodes and connects them, one being the sole center.
|
||||
// Then it checks that the center reports the correct number of peers.
|
||||
func TestPeersTotal(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
hosts := make([]*bhost.BasicHost, 4)
|
||||
for i := 0; i < 4; i++ {
|
||||
hosts[i] = testutil.GenHostSwarm(t, ctx)
|
||||
}
|
||||
|
||||
dial := func(a, b inet.Network) {
|
||||
testutil.DivulgeAddresses(b, a)
|
||||
if _, err := a.DialPeer(ctx, b.LocalPeer()); err != nil {
|
||||
t.Fatalf("Failed to dial: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
dial(hosts[0].Network(), hosts[1].Network())
|
||||
dial(hosts[0].Network(), hosts[2].Network())
|
||||
dial(hosts[0].Network(), hosts[3].Network())
|
||||
|
||||
// there's something wrong with dial, i think. it's not finishing
|
||||
// completely. there must be some async stuff.
|
||||
<-time.After(100 * time.Millisecond)
|
||||
|
||||
node := &core.IpfsNode{PeerHost: hosts[0]}
|
||||
collector := IpfsNodeCollector{Node: node}
|
||||
actual := collector.PeersTotalValue()
|
||||
if actual != 3 {
|
||||
t.Fatalf("expected 3 peers, got %d", int(actual))
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
package corehttp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
prom "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"github.com/ipfs/go-ipfs/core"
|
||||
)
|
||||
|
||||
func PrometheusOption(path string) ServeOption {
|
||||
return func(n *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
|
||||
mux.Handle(path, prom.UninstrumentedHandler())
|
||||
return mux, nil
|
||||
}
|
||||
}
|
||||
|
||||
func PrometheusCollectorOption(handlerName string) ServeOption {
|
||||
return func(_ *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
|
||||
childMux := http.NewServeMux()
|
||||
mux.HandleFunc("/", prom.InstrumentHandler(handlerName, childMux))
|
||||
return childMux, nil
|
||||
}
|
||||
}
|
||||
@ -30,6 +30,11 @@
|
||||
"hash": "QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV",
|
||||
"name": "gogo-protobuf",
|
||||
"version": "0.0.0"
|
||||
},
|
||||
{
|
||||
"hash": "QmdhsRK1EK2fvAz2i2SH5DEfkL6seDuyMYEsxKa9Braim3",
|
||||
"name": "client_golang",
|
||||
"version": "0.0.0"
|
||||
}
|
||||
],
|
||||
"gxVersion": "0.4.0",
|
||||
@ -39,4 +44,4 @@
|
||||
"license": "",
|
||||
"name": "go-ipfs",
|
||||
"version": "0.4.0"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user