|
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" |
@@ -418,16 +421,16 @@ func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMess |
418 | 421 | return nil |
419 | 422 | case msg.isCall(): |
420 | 423 | resp := h.handleCall(ctx, msg) |
421 | | - var ctx []any |
422 | | - ctx = append(ctx, "reqid", idForLog{msg.ID}, "t", time.Since(start)) |
| 424 | + var logctx []any |
| 425 | + logctx = append(logctx, "reqid", idForLog{msg.ID}, "duration", time.Since(start)) |
423 | 426 | if resp.Error != nil { |
424 | | - ctx = append(ctx, "err", resp.Error.Message) |
| 427 | + logctx = append(logctx, "err", resp.Error.Message) |
425 | 428 | if resp.Error.Data != nil { |
426 | | - ctx = append(ctx, "errdata", resp.Error.Data) |
| 429 | + logctx = append(logctx, "errdata", formatErrorData(resp.Error.Data)) |
427 | 430 | } |
428 | | - h.log.Warn("Served "+msg.Method, ctx...) |
| 431 | + h.log.Warn("Served "+msg.Method, logctx...) |
429 | 432 | } else { |
430 | | - h.log.Debug("Served "+msg.Method, ctx...) |
| 433 | + h.log.Debug("Served "+msg.Method, logctx...) |
431 | 434 | } |
432 | 435 | return resp |
433 | 436 | case msg.hasValidID(): |
@@ -537,3 +540,33 @@ func (id idForLog) String() string { |
537 | 540 | } |
538 | 541 | return string(id.RawMessage) |
539 | 542 | } |
| 543 | + |
| 544 | +var errTruncatedOutput = errors.New("truncated output") |
| 545 | + |
| 546 | +type limitedBuffer struct { |
| 547 | + output []byte |
| 548 | + limit int |
| 549 | +} |
| 550 | + |
| 551 | +func (buf *limitedBuffer) Write(data []byte) (int, error) { |
| 552 | + avail := max(buf.limit, len(buf.output)) |
| 553 | + if len(data) < avail { |
| 554 | + buf.output = append(buf.output, data...) |
| 555 | + return len(data), nil |
| 556 | + } |
| 557 | + buf.output = append(buf.output, data[:avail]...) |
| 558 | + return avail, errTruncatedOutput |
| 559 | +} |
| 560 | + |
| 561 | +func formatErrorData(v any) string { |
| 562 | + buf := limitedBuffer{limit: 1024} |
| 563 | + err := json.NewEncoder(&buf).Encode(v) |
| 564 | + switch { |
| 565 | + case err == nil: |
| 566 | + return string(bytes.TrimRight(buf.output, "\n")) |
| 567 | + case errors.Is(err, errTruncatedOutput): |
| 568 | + return fmt.Sprintf("%s... (truncated)", buf.output) |
| 569 | + default: |
| 570 | + return fmt.Sprintf("bad error data (err=%v)", err) |
| 571 | + } |
| 572 | +} |
0 commit comments