Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,18 @@ import "go.ajitem.com/zapdriver"
This package provides three building blocks to support the full array of
structured logging capabilities of Stackdriver:

* [Special purpose logging fields](#special-purpose-logging-fields)
* [Pre-configured Stackdriver-optimized encoder](#pre-configured-stackdriver-optimized-encoder)
* [Custom Stackdriver Zap core](#custom-stackdriver-zap-core)
* [Using Error Reporting](#using-error-reporting)
- [:zap: Zapdriver](#zap-zapdriver)
- [Usage](#usage)
- [Special purpose logging fields](#special-purpose-logging-fields)
- [HTTP](#http)
- [Label](#label)
- [SourceLocation](#sourcelocation)
- [Operation](#operation)
- [TraceContext](#tracecontext)
- [Pre-configured Stackdriver-optimized encoder](#pre-configured-stackdriver-optimized-encoder)
- [Custom Stackdriver Zap core](#custom-stackdriver-zap-core)
- [Using Error Reporting](#using-error-reporting)
- [Reporting errors manually](#reporting-errors-manually)

The above components can be used separately, but to start, you can create a new
Zap logger with all of the above included:
Expand Down Expand Up @@ -93,7 +101,7 @@ one or the other will be omitted if `nil` is passed in.
Note that there are some fields that are not populated by either the request or
response object, and need to be set manually:

* `ServerIP string`

* `Latency string`
* `CacheLookup bool`
* `CacheHit bool`
Expand Down
36 changes: 32 additions & 4 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,33 +117,58 @@ func NewHTTP(req *http.Request, res *http.Response) *HTTPPayload {
RemoteIP: req.RemoteAddr,
Referer: req.Referer(),
Protocol: req.Proto,
ServerIP: req.Host,
}

if req.URL != nil {
sdreq.RequestURL = req.URL.String()
}

// Count the requestSize: both headers and body
var requestSize int64

for hKey, hValue := range req.Header {
requestSize += int64(len([]byte(hKey)))
for _, v := range hValue {
requestSize += int64(len([]byte(v)))
}
}

buf := &bytes.Buffer{}
if req.Body != nil {
n, _ := io.Copy(buf, req.Body) // nolint: gas
sdreq.RequestSize = strconv.FormatInt(n, 10)
requestSize += n
}

sdreq.RequestSize = strconv.FormatInt(requestSize, 10)

// Count the response size, both headers and body
var responseSize int64

for hKey, hValue := range res.Header {
responseSize += int64(len([]byte(hKey)))
for _, v := range hValue {
responseSize += int64(len([]byte(v)))
}
}

if res.Body != nil {
buf.Reset()
n, _ := io.Copy(buf, res.Body) // nolint: gas
sdreq.ResponseSize = strconv.FormatInt(n, 10)
responseSize += n
}

sdreq.ResponseSize = strconv.FormatInt(responseSize, 10)

return sdreq
}

// MarshalLogObject implements zapcore.ObjectMarshaller interface.
func (req HTTPPayload) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddString("requestMethod", req.RequestMethod)
enc.AddString("requestUrl", req.RequestURL)
enc.AddString("requestSize", req.RequestSize)
enc.AddInt("status", req.Status)
enc.AddString("requestSize", req.RequestSize)
enc.AddString("responseSize", req.ResponseSize)
enc.AddString("userAgent", req.UserAgent)
enc.AddString("remoteIp", req.RemoteIP)
Expand All @@ -153,8 +178,11 @@ func (req HTTPPayload) MarshalLogObject(enc zapcore.ObjectEncoder) error {
enc.AddBool("cacheLookup", req.CacheLookup)
enc.AddBool("cacheHit", req.CacheHit)
enc.AddBool("cacheValidatedWithOriginServer", req.CacheValidatedWithOriginServer)
enc.AddString("cacheFillBytes", req.CacheFillBytes)
enc.AddString("protocol", req.Protocol)

if req.CacheFillBytes != "" {
enc.AddString("cacheFillBytes", req.CacheFillBytes)
}

return nil
}
26 changes: 14 additions & 12 deletions http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,61 +35,61 @@ func TestNewHTTP(t *testing.T) {
"empty": {
nil,
nil,
&zapdriver.HTTPPayload{},
&zapdriver.HTTPPayload{RequestSize: "0", ResponseSize: "0"},
},

"RequestMethod": {
&http.Request{Method: "GET"},
nil,
&zapdriver.HTTPPayload{RequestMethod: "GET"},
&zapdriver.HTTPPayload{RequestMethod: "GET", RequestSize: "0", ResponseSize: "0"},
},

"Status": {
nil,
&http.Response{StatusCode: 404},
&zapdriver.HTTPPayload{Status: 404},
&zapdriver.HTTPPayload{Status: 404, RequestSize: "0", ResponseSize: "0"},
},

"UserAgent": {
&http.Request{Header: http.Header{"User-Agent": []string{"hello world"}}},
nil,
&zapdriver.HTTPPayload{UserAgent: "hello world"},
&zapdriver.HTTPPayload{UserAgent: "hello world", RequestSize: "21", ResponseSize: "0"},
},

"RemoteIP": {
&http.Request{RemoteAddr: "127.0.0.1"},
nil,
&zapdriver.HTTPPayload{RemoteIP: "127.0.0.1"},
&zapdriver.HTTPPayload{RemoteIP: "127.0.0.1", RequestSize: "0", ResponseSize: "0"},
},

"Referrer": {
&http.Request{Header: http.Header{"Referer": []string{"hello universe"}}},
nil,
&zapdriver.HTTPPayload{Referer: "hello universe"},
&zapdriver.HTTPPayload{Referer: "hello universe", RequestSize: "21", ResponseSize: "0"},
},

"Protocol": {
&http.Request{Proto: "HTTP/1.1"},
nil,
&zapdriver.HTTPPayload{Protocol: "HTTP/1.1"},
&zapdriver.HTTPPayload{Protocol: "HTTP/1.1", RequestSize: "0", ResponseSize: "0"},
},

"RequestURL": {
&http.Request{URL: &url.URL{Host: "example.com", Scheme: "https"}},
nil,
&zapdriver.HTTPPayload{RequestURL: "https://example.com"},
&zapdriver.HTTPPayload{RequestURL: "https://example.com", RequestSize: "0", ResponseSize: "0"},
},

"RequestSize": {
&http.Request{Body: ioutil.NopCloser(strings.NewReader("12345"))},
nil,
&zapdriver.HTTPPayload{RequestSize: "5"},
&zapdriver.HTTPPayload{RequestSize: "5", ResponseSize: "0"},
},

"ResponseSize": {
nil,
&http.Response{Body: ioutil.NopCloser(strings.NewReader("12345"))},
&zapdriver.HTTPPayload{ResponseSize: "5"},
&zapdriver.HTTPPayload{ResponseSize: "5", RequestSize: "0"},
},

"simple request": {
Expand All @@ -101,19 +101,21 @@ func TestNewHTTP(t *testing.T) {
RemoteIP: "192.0.2.1:1234",
Protocol: "HTTP/1.1",
RequestURL: "/",
ResponseSize: "0",
ServerIP: "example.com",
},
},

"simple response": {
nil,
&http.Response{Body: ioutil.NopCloser(strings.NewReader("12345")), StatusCode: 404},
&zapdriver.HTTPPayload{ResponseSize: "5", Status: 404},
&zapdriver.HTTPPayload{RequestSize: "0", ResponseSize: "5", Status: 404},
},

"request & response": {
&http.Request{Method: "POST", Proto: "HTTP/1.1"},
&http.Response{StatusCode: 200},
&zapdriver.HTTPPayload{RequestMethod: "POST", Protocol: "HTTP/1.1", Status: 200},
&zapdriver.HTTPPayload{RequestMethod: "POST", Protocol: "HTTP/1.1", Status: 200, RequestSize: "0", ResponseSize: "0"},
},
}

Expand Down