mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 18:37:45 +08:00
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.
155 lines
3.6 KiB
Go
155 lines
3.6 KiB
Go
package peerlog
|
|
|
|
import (
|
|
"fmt"
|
|
"sync/atomic"
|
|
|
|
core "github.com/ipfs/go-ipfs/core"
|
|
plugin "github.com/ipfs/go-ipfs/plugin"
|
|
logging "github.com/ipfs/go-log"
|
|
event "github.com/libp2p/go-libp2p-core/event"
|
|
network "github.com/libp2p/go-libp2p-core/network"
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
"github.com/libp2p/go-libp2p-core/peerstore"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
var log = logging.Logger("plugin/peerlog")
|
|
|
|
type eventType int
|
|
|
|
const (
|
|
eventConnect eventType = iota
|
|
eventIdentify
|
|
)
|
|
|
|
type plEvent struct {
|
|
kind eventType
|
|
peer peer.ID
|
|
}
|
|
|
|
// Log all the PeerIDs we see
|
|
//
|
|
// Usage:
|
|
// GOLOG_FILE=~/peer.log IPFS_LOGGING_FMT=json ipfs daemon
|
|
// Output:
|
|
// {"level":"info","ts":"2020-02-10T13:54:26.639Z","logger":"plugin/peerlog","caller":"peerlog/peerlog.go:51","msg":"connected","peer":"QmS2H72gdrekXJggGdE9SunXPntBqdkJdkXQJjuxcH8Cbt"}
|
|
// {"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/"}
|
|
//
|
|
type peerLogPlugin struct {
|
|
droppedCount uint64
|
|
events chan plEvent
|
|
}
|
|
|
|
var _ plugin.PluginDaemonInternal = (*peerLogPlugin)(nil)
|
|
|
|
// Plugins is exported list of plugins that will be loaded
|
|
var Plugins = []plugin.Plugin{
|
|
&peerLogPlugin{},
|
|
}
|
|
|
|
// Name returns the plugin's name, satisfying the plugin.Plugin interface.
|
|
func (*peerLogPlugin) Name() string {
|
|
return "peerlog"
|
|
}
|
|
|
|
// Version returns the plugin's version, satisfying the plugin.Plugin interface.
|
|
func (*peerLogPlugin) Version() string {
|
|
return "0.1.0"
|
|
}
|
|
|
|
// Init initializes plugin
|
|
func (pl *peerLogPlugin) Init(*plugin.Environment) error {
|
|
pl.events = make(chan plEvent, 64*1024)
|
|
return nil
|
|
}
|
|
|
|
func (pl *peerLogPlugin) collectEvents(node *core.IpfsNode) {
|
|
go func() {
|
|
ctx := node.Context()
|
|
|
|
dlog := log.Desugar()
|
|
for {
|
|
dropped := atomic.SwapUint64(&pl.droppedCount, 0)
|
|
if dropped > 0 {
|
|
dlog.Error("dropped events", zap.Uint64("count", dropped))
|
|
}
|
|
|
|
var e plEvent
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case e = <-pl.events:
|
|
}
|
|
|
|
peerID := zap.String("peer", e.peer.Pretty())
|
|
|
|
switch e.kind {
|
|
case eventConnect:
|
|
dlog.Info("connected", peerID)
|
|
case eventIdentify:
|
|
agent, err := node.Peerstore.Get(e.peer, "AgentVersion")
|
|
switch err {
|
|
case nil:
|
|
case peerstore.ErrNotFound:
|
|
continue
|
|
default:
|
|
dlog.Error("failed to get agent version", zap.Error(err))
|
|
continue
|
|
}
|
|
|
|
agentS, ok := agent.(string)
|
|
if !ok {
|
|
continue
|
|
}
|
|
dlog.Info("identified", peerID, zap.String("agent", agentS))
|
|
}
|
|
}
|
|
}()
|
|
|
|
}
|
|
|
|
func (pl *peerLogPlugin) emit(evt eventType, p peer.ID) {
|
|
select {
|
|
case pl.events <- plEvent{kind: evt, peer: p}:
|
|
default:
|
|
atomic.AddUint64(&pl.droppedCount, 1)
|
|
}
|
|
}
|
|
|
|
func (pl *peerLogPlugin) Start(node *core.IpfsNode) error {
|
|
// Ensure logs from this plugin get printed regardless of global IPFS_LOGGING value
|
|
if err := logging.SetLogLevel("plugin/peerlog", "info"); err != nil {
|
|
return fmt.Errorf("failed to set log level: %w", err)
|
|
}
|
|
|
|
sub, err := node.PeerHost.EventBus().Subscribe(new(event.EvtPeerIdentificationCompleted))
|
|
if err != nil {
|
|
return fmt.Errorf("failed to subscribe to identify notifications")
|
|
}
|
|
|
|
var notifee network.NotifyBundle
|
|
notifee.ConnectedF = func(net network.Network, conn network.Conn) {
|
|
pl.emit(eventConnect, conn.RemotePeer())
|
|
}
|
|
node.PeerHost.Network().Notify(¬ifee)
|
|
|
|
go func() {
|
|
defer sub.Close()
|
|
for e := range sub.Out() {
|
|
switch e := e.(type) {
|
|
case event.EvtPeerIdentificationCompleted:
|
|
pl.emit(eventIdentify, e.Peer)
|
|
}
|
|
}
|
|
}()
|
|
|
|
go pl.collectEvents(node)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (*peerLogPlugin) Close() error {
|
|
return nil
|
|
}
|