| package logging |
| |
| import ( |
| "bytes" |
| "encoding/json" |
| "log" |
| "net/http" |
| "net/http/httputil" |
| "strings" |
| ) |
| |
| type transport struct { |
| name string |
| transport http.RoundTripper |
| } |
| |
| func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) { |
| if IsDebugOrHigher() { |
| reqData, err := httputil.DumpRequestOut(req, true) |
| if err == nil { |
| log.Printf("[DEBUG] "+logReqMsg, t.name, prettyPrintJsonLines(reqData)) |
| } else { |
| log.Printf("[ERROR] %s API Request error: %#v", t.name, err) |
| } |
| } |
| |
| resp, err := t.transport.RoundTrip(req) |
| if err != nil { |
| return resp, err |
| } |
| |
| if IsDebugOrHigher() { |
| respData, err := httputil.DumpResponse(resp, true) |
| if err == nil { |
| log.Printf("[DEBUG] "+logRespMsg, t.name, prettyPrintJsonLines(respData)) |
| } else { |
| log.Printf("[ERROR] %s API Response error: %#v", t.name, err) |
| } |
| } |
| |
| return resp, nil |
| } |
| |
| func NewTransport(name string, t http.RoundTripper) *transport { |
| return &transport{name, t} |
| } |
| |
| // prettyPrintJsonLines iterates through a []byte line-by-line, |
| // transforming any lines that are complete json into pretty-printed json. |
| func prettyPrintJsonLines(b []byte) string { |
| parts := strings.Split(string(b), "\n") |
| for i, p := range parts { |
| if b := []byte(p); json.Valid(b) { |
| var out bytes.Buffer |
| json.Indent(&out, b, "", " ") |
| parts[i] = out.String() |
| } |
| } |
| return strings.Join(parts, "\n") |
| } |
| |
| const logReqMsg = `%s API Request Details: |
| ---[ REQUEST ]--------------------------------------- |
| %s |
| -----------------------------------------------------` |
| |
| const logRespMsg = `%s API Response Details: |
| ---[ RESPONSE ]-------------------------------------- |
| %s |
| -----------------------------------------------------` |