1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-05-21 17:08:13 +08:00
Files
kubo/core/coreapi/swarm.go
Gus Eggert f855bfe6ef feat: add basic gateway tracing (#8595)
* add deprecation warning when tracer plugins are loaded
* add response format attribute to span in gateway handler
* add note about tracing's experimental status in godoc
* add nil check for TTL when adding name span attrs
* add basic sharness test for integration with otel collector
* add nil check in UnixFSAPI.processLink
* test: sharness check all json objs for swarm span
* add env var docs to docs/environment-variables.md
* chore: pin the otel collector version
* add tracing spans per response type (#8841)
* docs: tracing with jaeger-ui

Co-authored-by: Marcin Rataj <lidel@lidel.org>
2022-04-04 19:24:05 +02:00

194 lines
4.4 KiB
Go

package coreapi
import (
"context"
"sort"
"time"
"github.com/ipfs/go-ipfs/tracing"
coreiface "github.com/ipfs/interface-go-ipfs-core"
inet "github.com/libp2p/go-libp2p-core/network"
peer "github.com/libp2p/go-libp2p-core/peer"
pstore "github.com/libp2p/go-libp2p-core/peerstore"
protocol "github.com/libp2p/go-libp2p-core/protocol"
swarm "github.com/libp2p/go-libp2p-swarm"
ma "github.com/multiformats/go-multiaddr"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)
type SwarmAPI CoreAPI
type connInfo struct {
peerstore pstore.Peerstore
conn inet.Conn
dir inet.Direction
addr ma.Multiaddr
peer peer.ID
}
// tag used in the connection manager when explicitly connecting to a peer.
const connectionManagerTag = "user-connect"
const connectionManagerWeight = 100
func (api *SwarmAPI) Connect(ctx context.Context, pi peer.AddrInfo) error {
ctx, span := tracing.Span(ctx, "CoreAPI.SwarmAPI", "Connect", trace.WithAttributes(attribute.String("peerid", pi.ID.String())))
defer span.End()
if api.peerHost == nil {
return coreiface.ErrOffline
}
if swrm, ok := api.peerHost.Network().(*swarm.Swarm); ok {
swrm.Backoff().Clear(pi.ID)
}
if err := api.peerHost.Connect(ctx, pi); err != nil {
return err
}
api.peerHost.ConnManager().TagPeer(pi.ID, connectionManagerTag, connectionManagerWeight)
return nil
}
func (api *SwarmAPI) Disconnect(ctx context.Context, addr ma.Multiaddr) error {
_, span := tracing.Span(ctx, "CoreAPI.SwarmAPI", "Disconnect", trace.WithAttributes(attribute.String("addr", addr.String())))
defer span.End()
if api.peerHost == nil {
return coreiface.ErrOffline
}
taddr, id := peer.SplitAddr(addr)
if id == "" {
return peer.ErrInvalidAddr
}
span.SetAttributes(attribute.String("peerid", id.String()))
net := api.peerHost.Network()
if taddr == nil {
if net.Connectedness(id) != inet.Connected {
return coreiface.ErrNotConnected
}
if err := net.ClosePeer(id); err != nil {
return err
}
return nil
}
for _, conn := range net.ConnsToPeer(id) {
if !conn.RemoteMultiaddr().Equal(taddr) {
continue
}
return conn.Close()
}
return coreiface.ErrConnNotFound
}
func (api *SwarmAPI) KnownAddrs(ctx context.Context) (map[peer.ID][]ma.Multiaddr, error) {
_, span := tracing.Span(ctx, "CoreAPI.SwarmAPI", "KnownAddrs")
defer span.End()
if api.peerHost == nil {
return nil, coreiface.ErrOffline
}
addrs := make(map[peer.ID][]ma.Multiaddr)
ps := api.peerHost.Network().Peerstore()
for _, p := range ps.Peers() {
addrs[p] = append(addrs[p], ps.Addrs(p)...)
sort.Slice(addrs[p], func(i, j int) bool {
return addrs[p][i].String() < addrs[p][j].String()
})
}
return addrs, nil
}
func (api *SwarmAPI) LocalAddrs(ctx context.Context) ([]ma.Multiaddr, error) {
_, span := tracing.Span(ctx, "CoreAPI.SwarmAPI", "LocalAddrs")
defer span.End()
if api.peerHost == nil {
return nil, coreiface.ErrOffline
}
return api.peerHost.Addrs(), nil
}
func (api *SwarmAPI) ListenAddrs(ctx context.Context) ([]ma.Multiaddr, error) {
_, span := tracing.Span(ctx, "CoreAPI.SwarmAPI", "ListenAddrs")
defer span.End()
if api.peerHost == nil {
return nil, coreiface.ErrOffline
}
return api.peerHost.Network().InterfaceListenAddresses()
}
func (api *SwarmAPI) Peers(ctx context.Context) ([]coreiface.ConnectionInfo, error) {
_, span := tracing.Span(ctx, "CoreAPI.SwarmAPI", "Peers")
defer span.End()
if api.peerHost == nil {
return nil, coreiface.ErrOffline
}
conns := api.peerHost.Network().Conns()
out := make([]coreiface.ConnectionInfo, 0, len(conns))
for _, c := range conns {
ci := &connInfo{
peerstore: api.peerstore,
conn: c,
dir: c.Stat().Direction,
addr: c.RemoteMultiaddr(),
peer: c.RemotePeer(),
}
/*
// FIXME(steb):
swcon, ok := c.(*swarm.Conn)
if ok {
ci.muxer = fmt.Sprintf("%T", swcon.StreamConn().Conn())
}
*/
out = append(out, ci)
}
return out, nil
}
func (ci *connInfo) ID() peer.ID {
return ci.peer
}
func (ci *connInfo) Address() ma.Multiaddr {
return ci.addr
}
func (ci *connInfo) Direction() inet.Direction {
return ci.dir
}
func (ci *connInfo) Latency() (time.Duration, error) {
return ci.peerstore.LatencyEWMA(peer.ID(ci.ID())), nil
}
func (ci *connInfo) Streams() ([]protocol.ID, error) {
streams := ci.conn.GetStreams()
out := make([]protocol.ID, len(streams))
for i, s := range streams {
out[i] = s.Protocol()
}
return out, nil
}