mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-30 18:49:08 +02:00
client: add gRPC logging interceptor for request and response tracking
This commit is contained in:
@@ -21,6 +21,8 @@ import (
|
|||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
|
|
||||||
|
grpcLogger "github.com/netbirdio/netbird/client/grpc/logger"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/internal"
|
"github.com/netbirdio/netbird/client/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -241,6 +243,7 @@ func DialClientGRPCServer(ctx context.Context, addr string) (*grpc.ClientConn, e
|
|||||||
strings.TrimPrefix(addr, "tcp://"),
|
strings.TrimPrefix(addr, "tcp://"),
|
||||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
grpc.WithBlock(),
|
grpc.WithBlock(),
|
||||||
|
grpc.WithUnaryInterceptor(grpcLogger.UnaryClientInterceptor()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnaryClientInterceptor logs gRPC requests using the global logrus logger
|
||||||
|
func UnaryClientInterceptor() grpc.UnaryClientInterceptor {
|
||||||
|
return func(
|
||||||
|
ctx context.Context,
|
||||||
|
method string,
|
||||||
|
req, reply interface{},
|
||||||
|
cc *grpc.ClientConn,
|
||||||
|
invoker grpc.UnaryInvoker,
|
||||||
|
opts ...grpc.CallOption,
|
||||||
|
) error {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
// og the request
|
||||||
|
if msg, ok := req.(proto.Message); ok {
|
||||||
|
if jsonReq, err := protojson.Marshal(msg); err == nil {
|
||||||
|
logrus.Debugf("gRPC request initiated: method=%s, request=%s", method, jsonReq)
|
||||||
|
} else {
|
||||||
|
logrus.Warnf("Could not marshal gRPC request: method=%s, error=%v", method, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logrus.Debugf("gRPC request initiated: method=%s, requestType=%T", method, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := invoker(ctx, method, req, reply, cc, opts...)
|
||||||
|
|
||||||
|
duration := time.Since(start)
|
||||||
|
|
||||||
|
// log the response
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("gRPC request failed: method=%s, duration=%v, error=%v", method, duration, err)
|
||||||
|
} else {
|
||||||
|
if msg, ok := reply.(proto.Message); ok {
|
||||||
|
if jsonReply, err := protojson.Marshal(msg); err == nil {
|
||||||
|
logrus.Debugf("gRPC request succeeded: method=%s, duration=%v, response=%s", method, duration, jsonReply)
|
||||||
|
} else {
|
||||||
|
logrus.Warnf("Could not marshal gRPC response: method=%s, error=%v", method, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logrus.Debugf("gRPC request succeeded: method=%s, duration=%v, responseType=%T", method, duration, reply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pion/ice/v3"
|
"github.com/pion/ice/v3"
|
||||||
"github.com/pion/logging"
|
|
||||||
"github.com/pion/stun/v2"
|
"github.com/pion/stun/v2"
|
||||||
"github.com/pion/transport/v3"
|
"github.com/pion/transport/v3"
|
||||||
"github.com/pion/transport/v3/stdnet"
|
"github.com/pion/transport/v3/stdnet"
|
||||||
@@ -48,7 +47,6 @@ const maxAddrSize = 512
|
|||||||
|
|
||||||
// UDPMuxParams are parameters for UDPMux.
|
// UDPMuxParams are parameters for UDPMux.
|
||||||
type UDPMuxParams struct {
|
type UDPMuxParams struct {
|
||||||
Logger logging.LeveledLogger
|
|
||||||
UDPConn net.PacketConn
|
UDPConn net.PacketConn
|
||||||
|
|
||||||
// Required for gathering local addresses
|
// Required for gathering local addresses
|
||||||
@@ -149,9 +147,6 @@ func isZeros(ip net.IP) bool {
|
|||||||
|
|
||||||
// NewUDPMuxDefault creates an implementation of UDPMux
|
// NewUDPMuxDefault creates an implementation of UDPMux
|
||||||
func NewUDPMuxDefault(params UDPMuxParams) *UDPMuxDefault {
|
func NewUDPMuxDefault(params UDPMuxParams) *UDPMuxDefault {
|
||||||
if params.Logger == nil {
|
|
||||||
params.Logger = logging.NewDefaultLoggerFactory().NewLogger("ice")
|
|
||||||
}
|
|
||||||
|
|
||||||
mux := &UDPMuxDefault{
|
mux := &UDPMuxDefault{
|
||||||
addressMap: map[string][]*udpMuxedConn{},
|
addressMap: map[string][]*udpMuxedConn{},
|
||||||
@@ -174,12 +169,12 @@ func NewUDPMuxDefault(params UDPMuxParams) *UDPMuxDefault {
|
|||||||
func (m *UDPMuxDefault) updateLocalAddresses() {
|
func (m *UDPMuxDefault) updateLocalAddresses() {
|
||||||
var localAddrsForUnspecified []net.Addr
|
var localAddrsForUnspecified []net.Addr
|
||||||
if addr, ok := m.params.UDPConn.LocalAddr().(*net.UDPAddr); !ok {
|
if addr, ok := m.params.UDPConn.LocalAddr().(*net.UDPAddr); !ok {
|
||||||
m.params.Logger.Errorf("LocalAddr is not a net.UDPAddr, got %T", m.params.UDPConn.LocalAddr())
|
log.Errorf("LocalAddr is not a net.UDPAddr, got %T", m.params.UDPConn.LocalAddr())
|
||||||
} else if ok && addr.IP.IsUnspecified() {
|
} else if ok && addr.IP.IsUnspecified() {
|
||||||
// For unspecified addresses, the correct behavior is to return errListenUnspecified, but
|
// For unspecified addresses, the correct behavior is to return errListenUnspecified, but
|
||||||
// it will break the applications that are already using unspecified UDP connection
|
// it will break the applications that are already using unspecified UDP connection
|
||||||
// with UDPMuxDefault, so print a warn log and create a local address list for mux.
|
// with UDPMuxDefault, so print a warn log and create a local address list for mux.
|
||||||
m.params.Logger.Warn("UDPMuxDefault should not listening on unspecified address, use NewMultiUDPMuxFromPort instead")
|
log.Warn("UDPMuxDefault should not listening on unspecified address, use NewMultiUDPMuxFromPort instead")
|
||||||
var networks []ice.NetworkType
|
var networks []ice.NetworkType
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
@@ -190,13 +185,13 @@ func (m *UDPMuxDefault) updateLocalAddresses() {
|
|||||||
networks = []ice.NetworkType{ice.NetworkTypeUDP4}
|
networks = []ice.NetworkType{ice.NetworkTypeUDP4}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
m.params.Logger.Errorf("LocalAddr expected IPV4 or IPV6, got %T", m.params.UDPConn.LocalAddr())
|
log.Errorf("LocalAddr expected IPV4 or IPV6, got %T", m.params.UDPConn.LocalAddr())
|
||||||
}
|
}
|
||||||
if len(networks) > 0 {
|
if len(networks) > 0 {
|
||||||
if m.params.Net == nil {
|
if m.params.Net == nil {
|
||||||
var err error
|
var err error
|
||||||
if m.params.Net, err = stdnet.NewNet(); err != nil {
|
if m.params.Net, err = stdnet.NewNet(); err != nil {
|
||||||
m.params.Logger.Errorf("failed to get create network: %v", err)
|
log.Errorf("failed to get create network: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +201,7 @@ func (m *UDPMuxDefault) updateLocalAddresses() {
|
|||||||
localAddrsForUnspecified = append(localAddrsForUnspecified, &net.UDPAddr{IP: ip, Port: addr.Port})
|
localAddrsForUnspecified = append(localAddrsForUnspecified, &net.UDPAddr{IP: ip, Port: addr.Port})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m.params.Logger.Errorf("failed to get local interfaces for unspecified addr: %v", err)
|
log.Errorf("failed to get local interfaces for unspecified addr: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -369,7 +364,6 @@ func (m *UDPMuxDefault) createMuxedConn(key string) *udpMuxedConn {
|
|||||||
Key: key,
|
Key: key,
|
||||||
AddrPool: m.pool,
|
AddrPool: m.pool,
|
||||||
LocalAddr: m.LocalAddr(),
|
LocalAddr: m.LocalAddr(),
|
||||||
Logger: m.params.Logger,
|
|
||||||
})
|
})
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/pion/logging"
|
|
||||||
"github.com/pion/stun/v2"
|
"github.com/pion/stun/v2"
|
||||||
"github.com/pion/transport/v3"
|
"github.com/pion/transport/v3"
|
||||||
|
|
||||||
@@ -38,7 +37,6 @@ type UniversalUDPMuxDefault struct {
|
|||||||
|
|
||||||
// UniversalUDPMuxParams are parameters for UniversalUDPMux server reflexive.
|
// UniversalUDPMuxParams are parameters for UniversalUDPMux server reflexive.
|
||||||
type UniversalUDPMuxParams struct {
|
type UniversalUDPMuxParams struct {
|
||||||
Logger logging.LeveledLogger
|
|
||||||
UDPConn net.PacketConn
|
UDPConn net.PacketConn
|
||||||
XORMappedAddrCacheTTL time.Duration
|
XORMappedAddrCacheTTL time.Duration
|
||||||
Net transport.Net
|
Net transport.Net
|
||||||
@@ -48,9 +46,6 @@ type UniversalUDPMuxParams struct {
|
|||||||
|
|
||||||
// NewUniversalUDPMuxDefault creates an implementation of UniversalUDPMux embedding UDPMux
|
// NewUniversalUDPMuxDefault creates an implementation of UniversalUDPMux embedding UDPMux
|
||||||
func NewUniversalUDPMuxDefault(params UniversalUDPMuxParams) *UniversalUDPMuxDefault {
|
func NewUniversalUDPMuxDefault(params UniversalUDPMuxParams) *UniversalUDPMuxDefault {
|
||||||
if params.Logger == nil {
|
|
||||||
params.Logger = logging.NewDefaultLoggerFactory().NewLogger("ice")
|
|
||||||
}
|
|
||||||
if params.XORMappedAddrCacheTTL == 0 {
|
if params.XORMappedAddrCacheTTL == 0 {
|
||||||
params.XORMappedAddrCacheTTL = time.Second * 25
|
params.XORMappedAddrCacheTTL = time.Second * 25
|
||||||
}
|
}
|
||||||
@@ -65,14 +60,12 @@ func NewUniversalUDPMuxDefault(params UniversalUDPMuxParams) *UniversalUDPMuxDef
|
|||||||
m.params.UDPConn = &udpConn{
|
m.params.UDPConn = &udpConn{
|
||||||
PacketConn: params.UDPConn,
|
PacketConn: params.UDPConn,
|
||||||
mux: m,
|
mux: m,
|
||||||
logger: params.Logger,
|
|
||||||
filterFn: params.FilterFn,
|
filterFn: params.FilterFn,
|
||||||
address: params.WGAddress,
|
address: params.WGAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
// embed UDPMux
|
// embed UDPMux
|
||||||
udpMuxParams := UDPMuxParams{
|
udpMuxParams := UDPMuxParams{
|
||||||
Logger: params.Logger,
|
|
||||||
UDPConn: m.params.UDPConn,
|
UDPConn: m.params.UDPConn,
|
||||||
Net: m.params.Net,
|
Net: m.params.Net,
|
||||||
}
|
}
|
||||||
@@ -118,7 +111,6 @@ func (m *UniversalUDPMuxDefault) ReadFromConn(ctx context.Context) {
|
|||||||
type udpConn struct {
|
type udpConn struct {
|
||||||
net.PacketConn
|
net.PacketConn
|
||||||
mux *UniversalUDPMuxDefault
|
mux *UniversalUDPMuxDefault
|
||||||
logger logging.LeveledLogger
|
|
||||||
filterFn FilterFn
|
filterFn FilterFn
|
||||||
// TODO: reset cache on route changes
|
// TODO: reset cache on route changes
|
||||||
addrCache sync.Map
|
addrCache sync.Map
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pion/logging"
|
|
||||||
"github.com/pion/transport/v3/packetio"
|
"github.com/pion/transport/v3/packetio"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,7 +19,6 @@ type udpMuxedConnParams struct {
|
|||||||
AddrPool *sync.Pool
|
AddrPool *sync.Pool
|
||||||
Key string
|
Key string
|
||||||
LocalAddr net.Addr
|
LocalAddr net.Addr
|
||||||
Logger logging.LeveledLogger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// udpMuxedConn represents a logical packet conn for a single remote as identified by ufrag
|
// udpMuxedConn represents a logical packet conn for a single remote as identified by ufrag
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/ui/process"
|
"github.com/netbirdio/netbird/client/ui/process"
|
||||||
"github.com/netbirdio/netbird/util"
|
"github.com/netbirdio/netbird/util"
|
||||||
|
|
||||||
|
grpcLogger "github.com/netbirdio/netbird/client/grpc/logger"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/version"
|
"github.com/netbirdio/netbird/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -822,6 +824,7 @@ func (s *serviceClient) getSrvClient(timeout time.Duration) (proto.DaemonService
|
|||||||
strings.TrimPrefix(s.addr, "tcp://"),
|
strings.TrimPrefix(s.addr, "tcp://"),
|
||||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||||
grpc.WithBlock(),
|
grpc.WithBlock(),
|
||||||
|
grpc.WithUnaryInterceptor(grpcLogger.UnaryClientInterceptor()),
|
||||||
grpc.WithUserAgent(desktop.GetUIUserAgent()),
|
grpc.WithUserAgent(desktop.GetUIUserAgent()),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
"google.golang.org/grpc/keepalive"
|
"google.golang.org/grpc/keepalive"
|
||||||
|
|
||||||
|
grpcLogger "github.com/netbirdio/netbird/client/grpc/logger"
|
||||||
"github.com/netbirdio/netbird/util/embeddedroots"
|
"github.com/netbirdio/netbird/util/embeddedroots"
|
||||||
nbnet "github.com/netbirdio/netbird/util/net"
|
nbnet "github.com/netbirdio/netbird/util/net"
|
||||||
)
|
)
|
||||||
@@ -84,6 +85,7 @@ func CreateConnection(addr string, tlsEnabled bool) (*grpc.ClientConn, error) {
|
|||||||
Time: 30 * time.Second,
|
Time: 30 * time.Second,
|
||||||
Timeout: 10 * time.Second,
|
Timeout: 10 * time.Second,
|
||||||
}),
|
}),
|
||||||
|
grpc.WithUnaryInterceptor(grpcLogger.UnaryClientInterceptor()),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("DialContext error: %v", err)
|
log.Printf("DialContext error: %v", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user