...
1 package log
2
3 import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "fmt"
8 "net"
9 "reflect"
10 "time"
11 )
12
13
14
15
16
17 const TimeFormat = "2006-01-02T15:04:05.000000000Z07:00"
18
19 func FormatTime(t time.Time) string {
20 return t.Format(TimeFormat)
21 }
22
23
24
25
26 type DurationFormat func(time.Duration) interface{}
27
28 func DurationFormatString(d time.Duration) interface{} { return d.String() }
29 func DurationFormatSeconds(d time.Duration) interface{} { return d.Seconds() }
30 func DurationFormatMilliseconds(d time.Duration) interface{} { return d.Milliseconds() }
31
32
33
34
35 func FormatIO(ctx context.Context, v interface{}) string {
36 m := make(map[string]string)
37 m["type"] = reflect.TypeOf(v).String()
38
39 switch t := v.(type) {
40 case net.Conn:
41 m["localAddress"] = formatAddr(t.LocalAddr())
42 m["remoteAddress"] = formatAddr(t.RemoteAddr())
43 case interface{ Addr() net.Addr }:
44 m["address"] = formatAddr(t.Addr())
45 default:
46 return Format(ctx, t)
47 }
48
49 return Format(ctx, m)
50 }
51
52 func formatAddr(a net.Addr) string {
53 return a.Network() + "://" + a.String()
54 }
55
56
57
58
59
60
61 func Format(ctx context.Context, v interface{}) string {
62 b, err := encode(v)
63 if err != nil {
64 G(ctx).WithError(err).Warning("could not format value")
65 return ""
66 }
67
68 return string(b)
69 }
70
71 func encode(v interface{}) ([]byte, error) {
72 return encodeBuffer(&bytes.Buffer{}, v)
73 }
74
75 func encodeBuffer(buf *bytes.Buffer, v interface{}) ([]byte, error) {
76 enc := json.NewEncoder(buf)
77 enc.SetEscapeHTML(false)
78 enc.SetIndent("", "")
79
80 if err := enc.Encode(v); err != nil {
81 err = fmt.Errorf("could not marshall %T to JSON for logging: %w", v, err)
82 return nil, err
83 }
84
85
86 return bytes.TrimSpace(buf.Bytes()), nil
87 }
88
View as plain text