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(¬ifee)
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