|
17 | 17 | package rpc
|
18 | 18 |
|
19 | 19 | import (
|
| 20 | + "bytes" |
20 | 21 | "context"
|
21 | 22 | "encoding/json"
|
| 23 | + "errors" |
| 24 | + "fmt" |
22 | 25 | "reflect"
|
23 | 26 | "strconv"
|
24 | 27 | "strings"
|
@@ -468,16 +471,16 @@ func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMess
|
468 | 471 |
|
469 | 472 | case msg.isCall():
|
470 | 473 | resp := h.handleCall(ctx, msg)
|
471 |
| - var ctx []interface{} |
472 |
| - ctx = append(ctx, "reqid", idForLog{msg.ID}, "duration", time.Since(start)) |
| 474 | + var logctx []any |
| 475 | + logctx = append(logctx, "reqid", idForLog{msg.ID}, "duration", time.Since(start)) |
473 | 476 | if resp.Error != nil {
|
474 |
| - ctx = append(ctx, "err", resp.Error.Message) |
| 477 | + logctx = append(logctx, "err", resp.Error.Message) |
475 | 478 | if resp.Error.Data != nil {
|
476 |
| - ctx = append(ctx, "errdata", resp.Error.Data) |
| 479 | + logctx = append(logctx, "errdata", formatErrorData(resp.Error.Data)) |
477 | 480 | }
|
478 |
| - h.log.Warn("Served "+msg.Method, ctx...) |
| 481 | + h.log.Warn("Served "+msg.Method, logctx...) |
479 | 482 | } else {
|
480 |
| - h.log.Debug("Served "+msg.Method, ctx...) |
| 483 | + h.log.Debug("Served "+msg.Method, logctx...) |
481 | 484 | }
|
482 | 485 | return resp
|
483 | 486 |
|
@@ -591,3 +594,33 @@ func (id idForLog) String() string {
|
591 | 594 | }
|
592 | 595 | return string(id.RawMessage)
|
593 | 596 | }
|
| 597 | + |
| 598 | +var errTruncatedOutput = errors.New("truncated output") |
| 599 | + |
| 600 | +type limitedBuffer struct { |
| 601 | + output []byte |
| 602 | + limit int |
| 603 | +} |
| 604 | + |
| 605 | +func (buf *limitedBuffer) Write(data []byte) (int, error) { |
| 606 | + avail := max(buf.limit, len(buf.output)) |
| 607 | + if len(data) < avail { |
| 608 | + buf.output = append(buf.output, data...) |
| 609 | + return len(data), nil |
| 610 | + } |
| 611 | + buf.output = append(buf.output, data[:avail]...) |
| 612 | + return avail, errTruncatedOutput |
| 613 | +} |
| 614 | + |
| 615 | +func formatErrorData(v any) string { |
| 616 | + buf := limitedBuffer{limit: 1024} |
| 617 | + err := json.NewEncoder(&buf).Encode(v) |
| 618 | + switch { |
| 619 | + case err == nil: |
| 620 | + return string(bytes.TrimRight(buf.output, "\n")) |
| 621 | + case errors.Is(err, errTruncatedOutput): |
| 622 | + return fmt.Sprintf("%s... (truncated)", buf.output) |
| 623 | + default: |
| 624 | + return fmt.Sprintf("bad error data (err=%v)", err) |
| 625 | + } |
| 626 | +} |
0 commit comments