|
|
|
@ -17,8 +17,11 @@ |
|
|
|
|
package rpc |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"bytes" |
|
|
|
|
"context" |
|
|
|
|
"encoding/json" |
|
|
|
|
"errors" |
|
|
|
|
"fmt" |
|
|
|
|
"reflect" |
|
|
|
|
"strconv" |
|
|
|
|
"strings" |
|
|
|
@ -468,16 +471,16 @@ func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMess |
|
|
|
|
|
|
|
|
|
case msg.isCall(): |
|
|
|
|
resp := h.handleCall(ctx, msg) |
|
|
|
|
var ctx []interface{} |
|
|
|
|
ctx = append(ctx, "reqid", idForLog{msg.ID}, "duration", time.Since(start)) |
|
|
|
|
var logctx []any |
|
|
|
|
logctx = append(logctx, "reqid", idForLog{msg.ID}, "duration", time.Since(start)) |
|
|
|
|
if resp.Error != nil { |
|
|
|
|
ctx = append(ctx, "err", resp.Error.Message) |
|
|
|
|
logctx = append(logctx, "err", resp.Error.Message) |
|
|
|
|
if resp.Error.Data != nil { |
|
|
|
|
ctx = append(ctx, "errdata", resp.Error.Data) |
|
|
|
|
logctx = append(logctx, "errdata", formatErrorData(resp.Error.Data)) |
|
|
|
|
} |
|
|
|
|
h.log.Warn("Served "+msg.Method, ctx...) |
|
|
|
|
h.log.Warn("Served "+msg.Method, logctx...) |
|
|
|
|
} else { |
|
|
|
|
h.log.Debug("Served "+msg.Method, ctx...) |
|
|
|
|
h.log.Debug("Served "+msg.Method, logctx...) |
|
|
|
|
} |
|
|
|
|
return resp |
|
|
|
|
|
|
|
|
@ -591,3 +594,33 @@ func (id idForLog) String() string { |
|
|
|
|
} |
|
|
|
|
return string(id.RawMessage) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var errTruncatedOutput = errors.New("truncated output") |
|
|
|
|
|
|
|
|
|
type limitedBuffer struct { |
|
|
|
|
output []byte |
|
|
|
|
limit int |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (buf *limitedBuffer) Write(data []byte) (int, error) { |
|
|
|
|
avail := max(buf.limit, len(buf.output)) |
|
|
|
|
if len(data) < avail { |
|
|
|
|
buf.output = append(buf.output, data...) |
|
|
|
|
return len(data), nil |
|
|
|
|
} |
|
|
|
|
buf.output = append(buf.output, data[:avail]...) |
|
|
|
|
return avail, errTruncatedOutput |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func formatErrorData(v any) string { |
|
|
|
|
buf := limitedBuffer{limit: 1024} |
|
|
|
|
err := json.NewEncoder(&buf).Encode(v) |
|
|
|
|
switch { |
|
|
|
|
case err == nil: |
|
|
|
|
return string(bytes.TrimRight(buf.output, "\n")) |
|
|
|
|
case errors.Is(err, errTruncatedOutput): |
|
|
|
|
return fmt.Sprintf("%s... (truncated)", buf.output) |
|
|
|
|
default: |
|
|
|
|
return fmt.Sprintf("bad error data (err=%v)", err) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|