rpc: log remote address only if available

This commit is contained in:
Felix Lange 2019-01-18 14:16:30 +01:00
parent 962f4ed490
commit 5f7693efa6
4 changed files with 29 additions and 21 deletions

View file

@ -551,13 +551,13 @@ func (c *Client) dispatch(codec ServerCodec) {
} }
case err := <-c.readErr: case err := <-c.readErr:
log.Debug("RPC connection read error", "err", err) conn.handler.log.Debug("RPC connection read error", "err", err)
conn.close(err, lastOp) conn.close(err, lastOp)
reading = false reading = false
// Reconnect: // Reconnect:
case newcodec := <-c.reconnected: case newcodec := <-c.reconnected:
log.Debug("RPC client reconnected", "reading", reading, "remote", newcodec.RemoteAddr()) log.Debug("RPC client reconnected", "reading", reading, "conn", newcodec.RemoteAddr())
go c.read(newcodec) go c.read(newcodec)
if reading { if reading {
// Wait for the previous read loop to exit. This is a rare case which // Wait for the previous read loop to exit. This is a rare case which

View file

@ -59,6 +59,7 @@ type handler struct {
rootCtx context.Context // canceled by close() rootCtx context.Context // canceled by close()
cancelRoot func() // cancel function for rootCtx cancelRoot func() // cancel function for rootCtx
conn jsonWriter // where responses will be sent conn jsonWriter // where responses will be sent
log log.Logger
allowSubscribe bool allowSubscribe bool
subLock sync.Mutex subLock sync.Mutex
@ -82,6 +83,10 @@ func newHandler(connCtx context.Context, conn jsonWriter, idgen func() ID, reg *
cancelRoot: cancelRoot, cancelRoot: cancelRoot,
allowSubscribe: true, allowSubscribe: true,
serverSubs: make(map[ID]*Subscription), serverSubs: make(map[ID]*Subscription),
log: log.Root(),
}
if conn.RemoteAddr() != "" {
h.log = h.log.New("conn", conn.RemoteAddr())
} }
h.unsubscribeCb = newCallback(reflect.Value{}, reflect.ValueOf(h.unsubscribe)) h.unsubscribeCb = newCallback(reflect.Value{}, reflect.ValueOf(h.unsubscribe))
return h return h
@ -235,7 +240,7 @@ func (h *handler) handleImmediate(msg *jsonrpcMessage) bool {
return false return false
case msg.isResponse(): case msg.isResponse():
h.handleResponse(msg) h.handleResponse(msg)
log.Trace("Handled RPC response", "reqid", idForLog{msg.ID}, "conn", h.conn.RemoteAddr(), "t", time.Since(start)) h.log.Trace("Handled RPC response", "reqid", idForLog{msg.ID}, "t", time.Since(start))
return true return true
default: default:
return false return false
@ -246,7 +251,7 @@ func (h *handler) handleImmediate(msg *jsonrpcMessage) bool {
func (h *handler) handleSubscriptionResult(msg *jsonrpcMessage) { func (h *handler) handleSubscriptionResult(msg *jsonrpcMessage) {
var result subscriptionResult var result subscriptionResult
if err := json.Unmarshal(msg.Params, &result); err != nil { if err := json.Unmarshal(msg.Params, &result); err != nil {
log.Debug("Dropping invalid subscription message", "conn", h.conn.RemoteAddr()) h.log.Debug("Dropping invalid subscription message")
return return
} }
if h.clientSubs[result.ID] != nil { if h.clientSubs[result.ID] != nil {
@ -258,7 +263,7 @@ func (h *handler) handleSubscriptionResult(msg *jsonrpcMessage) {
func (h *handler) handleResponse(msg *jsonrpcMessage) { func (h *handler) handleResponse(msg *jsonrpcMessage) {
op := h.respWait[string(msg.ID)] op := h.respWait[string(msg.ID)]
if op == nil { if op == nil {
log.Debug("Unsolicited RPC response", "reqid", idForLog{msg.ID}, "conn", h.conn.RemoteAddr()) h.log.Debug("Unsolicited RPC response", "reqid", idForLog{msg.ID})
return return
} }
delete(h.respWait, string(msg.ID)) delete(h.respWait, string(msg.ID))
@ -287,11 +292,15 @@ func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMess
switch { switch {
case msg.isNotification(): case msg.isNotification():
h.handleCall(ctx, msg) h.handleCall(ctx, msg)
log.Debug("Served "+msg.Method, "conn", h.conn.RemoteAddr(), "t", time.Since(start)) h.log.Debug("Served "+msg.Method, "t", time.Since(start))
return nil return nil
case msg.isCall(): case msg.isCall():
resp := h.handleCall(ctx, msg) resp := h.handleCall(ctx, msg)
log.Debug("Served "+msg.Method, "reqid", idForLog{msg.ID}, "conn", h.conn.RemoteAddr(), "t", time.Since(start)) if resp.Error != nil {
h.log.Info("Served "+msg.Method, "reqid", idForLog{msg.ID}, "t", time.Since(start), "err", resp.Error.Message)
} else {
h.log.Debug("Served "+msg.Method, "reqid", idForLog{msg.ID}, "t", time.Since(start))
}
return resp return resp
case msg.hasValidID(): case msg.hasValidID():
return msg.errorResponse(&invalidRequestError{"invalid request"}) return msg.errorResponse(&invalidRequestError{"invalid request"})

View file

@ -34,7 +34,7 @@ func (s *Server) ServeListener(l net.Listener) error {
} else if err != nil { } else if err != nil {
return err return err
} }
log.Trace("Accepted RPC connection", "addr", conn.RemoteAddr()) log.Trace("Accepted RPC connection", "conn", conn.RemoteAddr())
go s.ServeCodec(NewJSONCodec(conn), OptionMethodInvocation|OptionSubscriptions) go s.ServeCodec(NewJSONCodec(conn), OptionMethodInvocation|OptionSubscriptions)
} }
} }

View file

@ -23,7 +23,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"net"
"reflect" "reflect"
"strings" "strings"
"sync" "sync"
@ -142,6 +141,13 @@ type Conn interface {
SetWriteDeadline(time.Time) error SetWriteDeadline(time.Time) error
} }
// ConnRemoteAddr wraps the RemoteAddr operation, which returns a description
// of the peer address of a connection. If a Conn also implements ConnRemoteAddr, this
// description is used in log messages.
type ConnRemoteAddr interface {
RemoteAddr() string
}
// connWithRemoteAddr overrides the remote address of a connection. // connWithRemoteAddr overrides the remote address of a connection.
type connWithRemoteAddr struct { type connWithRemoteAddr struct {
Conn Conn
@ -166,20 +172,13 @@ type jsonCodec struct {
// on explicitly given encoding and decoding methods. // on explicitly given encoding and decoding methods.
func NewCodec(conn Conn, encode, decode func(v interface{}) error) ServerCodec { func NewCodec(conn Conn, encode, decode func(v interface{}) error) ServerCodec {
codec := &jsonCodec{ codec := &jsonCodec{
remoteAddr: "unknown",
closed: make(chan interface{}), closed: make(chan interface{}),
encode: encode, encode: encode,
decode: decode, decode: decode,
conn: conn, conn: conn,
} }
if ra, ok := conn.(ConnRemoteAddr); ok {
// Try to figure out the remote address.
type remoteStringAddr interface{ RemoteAddr() string }
type remoteNetAddr interface{ RemoteAddr() net.Addr }
if ra, ok := conn.(remoteStringAddr); ok {
codec.remoteAddr = ra.RemoteAddr() codec.remoteAddr = ra.RemoteAddr()
} else if ra, ok := conn.(remoteNetAddr); ok {
codec.remoteAddr = ra.RemoteAddr().String()
} }
return codec return codec
} }