@cryptotaxi247 / kubo / commits / bdbb79d30

fix: non-blocking peerlog logging

Avoid ever blocking new connections in the peer logger. Instead: 1. Send all new peers to a highly buffered channel. 2. Emit "dropped event" errors whenever we detect that we're dropping events and falling behind. 3. Don't log protocols, they're too large. 4. Don't log disconnects, we don't need them.

Steven Allen committed Apr 27, 2020 at 19:10 UTC bdbb79d30f6f65ab41780239653e0ea048e3a81e
2 files changed +89 -38
go.mod
+1 -1
@@ -59,7 +59,6 @@ require (
59 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c
60 github.com/jbenet/go-temp-err-catcher v0.1.0
61 github.com/jbenet/goprocess v0.1.4
62 - github.com/libp2p/go-eventbus v0.1.0
62 github.com/libp2p/go-libp2p v0.8.2
63 github.com/libp2p/go-libp2p-circuit v0.2.2
64 github.com/libp2p/go-libp2p-connmgr v0.2.1
@@ -101,6 +100,7 @@ require (
100 github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
101 github.com/whyrusleeping/tar-utils v0.0.0-20180509141711-8c6c8ba81d5c
102 go.uber.org/fx v1.12.0
103 + go.uber.org/zap v1.14.1
104 golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5
105 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
106 golang.org/x/sys v0.0.0-20200413165638-669c56c373c4
plugin/plugins/peerlog/peerlog.go
+88 -37
@@ -2,26 +2,44 @@ package peerlog
2
3 import (
4 "fmt"
5 + "sync/atomic"
6
7 core "github.com/ipfs/go-ipfs/core"
8 plugin "github.com/ipfs/go-ipfs/plugin"
9 logging "github.com/ipfs/go-log"
9 - eventbus "github.com/libp2p/go-eventbus"
10 event "github.com/libp2p/go-libp2p-core/event"
11 network "github.com/libp2p/go-libp2p-core/network"
12 + "github.com/libp2p/go-libp2p-core/peer"
13 + "github.com/libp2p/go-libp2p-core/peerstore"
14 + "go.uber.org/zap"
15 )
16
17 var log = logging.Logger("plugin/peerlog")
18
19 +type eventType int
20 +
21 +const (
22 + eventConnect eventType = iota
23 + eventIdentify
24 +)
25 +
26 +type plEvent struct {
27 + kind eventType
28 + peer peer.ID
29 +}
30 +
31 // Log all the PeerIDs we see
32 //
33 // Usage:
34 // GOLOG_FILE=~/peer.log IPFS_LOGGING_FMT=json ipfs daemon
35 // Output:
36 // {"level":"info","ts":"2020-02-10T13:54:26.639Z","logger":"plugin/peerlog","caller":"peerlog/peerlog.go:51","msg":"connected","peer":"QmS2H72gdrekXJggGdE9SunXPntBqdkJdkXQJjuxcH8Cbt"}
22 -// {"level":"info","ts":"2020-02-10T13:54:59.095Z","logger":"plugin/peerlog","caller":"peerlog/peerlog.go:56","msg":"disconnected","peer":"QmS2H72gdrekXJggGdE9SunXPntBqdkJdkXQJjuxcH8Cbt"}
37 +// {"level":"info","ts":"2020-02-10T13:54:59.095Z","logger":"plugin/peerlog","caller":"peerlog/peerlog.go:56","msg":"identified","peer":"QmS2H72gdrekXJggGdE9SunXPntBqdkJdkXQJjuxcH8Cbt","agent":"go-ipfs/0.5.0/"}
38 //
24 -type peerLogPlugin struct{}
39 +type peerLogPlugin struct {
40 + droppedCount uint64
41 + events chan plEvent
42 +}
43
44 var _ plugin.PluginDaemonInternal = (*peerLogPlugin)(nil)
45
@@ -41,60 +59,93 @@ func (*peerLogPlugin) Version() string {
59 }
60
61 // Init initializes plugin
44 -func (*peerLogPlugin) Init(*plugin.Environment) error {
62 +func (pl *peerLogPlugin) Init(*plugin.Environment) error {
63 + pl.events = make(chan plEvent, 64*1024)
64 return nil
65 }
66
48 -func (*peerLogPlugin) Start(node *core.IpfsNode) error {
67 +func (pl *peerLogPlugin) collectEvents(node *core.IpfsNode) {
68 + go func() {
69 + ctx := node.Context()
70 +
71 + dlog := log.Desugar()
72 + for {
73 + dropped := atomic.SwapUint64(&pl.droppedCount, 0)
74 + if dropped > 0 {
75 + dlog.Error("dropped events", zap.Uint64("count", dropped))
76 + }
77 +
78 + var e plEvent
79 + select {
80 + case <-ctx.Done():
81 + return
82 + case e = <-pl.events:
83 + }
84 +
85 + peerID := zap.String("peer", e.peer.Pretty())
86 +
87 + switch e.kind {
88 + case eventConnect:
89 + dlog.Info("connected", peerID)
90 + case eventIdentify:
91 + agent, err := node.Peerstore.Get(e.peer, "AgentVersion")
92 + switch err {
93 + case nil:
94 + case peerstore.ErrNotFound:
95 + continue
96 + default:
97 + dlog.Error("failed to get agent version", zap.Error(err))
98 + continue
99 + }
100 +
101 + agentS, ok := agent.(string)
102 + if !ok {
103 + continue
104 + }
105 + dlog.Info("identified", peerID, zap.String("agent", agentS))
106 + }
107 + }
108 + }()
109 +
110 +}
111 +
112 +func (pl *peerLogPlugin) emit(evt eventType, p peer.ID) {
113 + select {
114 + case pl.events <- plEvent{kind: evt, peer: p}:
115 + default:
116 + atomic.AddUint64(&pl.droppedCount, 1)
117 + }
118 +}
119 +
120 +func (pl *peerLogPlugin) Start(node *core.IpfsNode) error {
121 // Ensure logs from this plugin get printed regardless of global IPFS_LOGGING value
122 if err := logging.SetLogLevel("plugin/peerlog", "info"); err != nil {
123 return fmt.Errorf("failed to set log level: %w", err)
124 }
125 +
126 + sub, err := node.PeerHost.EventBus().Subscribe(new(event.EvtPeerIdentificationCompleted))
127 + if err != nil {
128 + return fmt.Errorf("failed to subscribe to identify notifications")
129 + }
130 +
131 var notifee network.NotifyBundle
132 notifee.ConnectedF = func(net network.Network, conn network.Conn) {
55 - // TODO: Log transport, country, etc?
56 - log.Infow("connected",
57 - "peer", conn.RemotePeer().Pretty(),
58 - )
59 - }
60 - notifee.DisconnectedF = func(net network.Network, conn network.Conn) {
61 - log.Infow("disconnected",
62 - "peer", conn.RemotePeer().Pretty(),
63 - )
133 + pl.emit(eventConnect, conn.RemotePeer())
134 }
135 node.PeerHost.Network().Notify(&notifee)
136
67 - sub, err := node.PeerHost.EventBus().Subscribe(
68 - new(event.EvtPeerIdentificationCompleted),
69 - eventbus.BufSize(1024),
70 - )
71 - if err != nil {
72 - return fmt.Errorf("failed to subscribe to identify notifications")
73 - }
137 go func() {
138 defer sub.Close()
139 for e := range sub.Out() {
140 switch e := e.(type) {
141 case event.EvtPeerIdentificationCompleted:
79 - protocols, err := node.Peerstore.GetProtocols(e.Peer)
80 - if err != nil {
81 - log.Errorw("failed to get protocols", "error", err)
82 - continue
83 - }
84 - agent, err := node.Peerstore.Get(e.Peer, "AgentVersion")
85 - if err != nil {
86 - log.Errorw("failed to get agent version", "error", err)
87 - continue
88 - }
89 - log.Infow(
90 - "identified",
91 - "peer", e.Peer.Pretty(),
92 - "agent", agent,
93 - "protocols", protocols,
94 - )
142 + pl.emit(eventIdentify, e.Peer)
143 }
144 }
145 }()
146 +
147 + go pl.collectEvents(node)
148 +
149 return nil
150 }
151