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
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Created by .ignore support plugin (hsz.mobi)
### Go template
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

vendor
21 changes: 21 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
language: go

cache:
directories:
- $GOPATH/pkg/mod

# The coverprofile for multiple packages works in go 1.10
# see https://tip.golang.org/doc/go1.10#test
go:
- master

before_script:
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
- chmod +x ./cc-test-reporter
- ./cc-test-reporter before-build

script:
- go test --race -gcflags=-l -coverprofile c.out ./...

after_script:
- CC_TEST_REPORTER_ID=$CC_TEST_REPORTER_ID ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
128 changes: 127 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,128 @@
# logger-http
Gol4ng logger sub package for http

[![Build Status](https://travis-ci.org/gol4ng/logger-http.svg?branch=master)](https://travis-ci.org/gol4ng/logger-http)
[![GoDoc](https://godoc.org/github.com/gol4ng/logger-http?status.svg)](https://godoc.org/github.com/gol4ng/logger-http)

Gol4ng logger sub package for logging http
Related package [gol4ng/logger](https://github.com/gol4ng/logger) and [gol4ng/httpware](https://github.com/gol4ng/httpware)

## Installation

`go get -u github.com/gol4ng/logger-http`

## Quick Start

You can refer at [gol4ng/httpware](https://github.com/gol4ng/httpware) documentation for the middleware/tripperware usage

### Tripperware

Log you're `http.Client` request

```
<debug> http client gonna GET http://google.com {"http_url":"http://google.com","http_start_time":"2019-12-13T17:01:13+01:00","http_kind":"client","Correlation-Id":"yhyBI94zyl","http_header":{"Correlation-Id":["yhyBI94zyl"]},"http_method":"GET"}
<info> http client GET http://google.com [status_code:301, duration:39.70726ms, content_length:219] {"Correlation-Id":"yhyBI94zyl","http_start_time":"2019-12-13T17:01:13+01:00","http_method":"GET","http_duration":0.03970726,"http_response_length":219,"http_header":{"Correlation-Id":["yhyBI94zyl"]},"http_url":"http://google.com","http_status":"301 Moved Permanently","http_status_code":301,"http_kind":"client"}
<debug> http client gonna GET http://www.google.com/ {"http_kind":"client","Correlation-Id":"uQzaMO9JC0","http_header":{"Correlation-Id":["uQzaMO9JC0"],"Referer":["http://google.com"]},"http_method":"GET","http_url":"http://www.google.com/","http_start_time":"2019-12-13T17:01:13+01:00"}
<info> http client GET http://www.google.com/ [status_code:200, duration:72.582736ms, content_length:-1] {"Correlation-Id":"uQzaMO9JC0","http_header":{"Correlation-Id":["uQzaMO9JC0"],"Referer":["http://google.com"]},"http_method":"GET","http_kind":"client","http_response_length":-1,"http_duration":0.072582736,"http_status_code":200,"http_url":"http://www.google.com/","http_start_time":"2019-12-13T17:01:13+01:00","http_status":"200 OK"}
```

```go
package main

import (
"net/http"
"os"

"github.com/gol4ng/httpware/v2"
"github.com/gol4ng/logger"
"github.com/gol4ng/logger-http/tripperware"
"github.com/gol4ng/logger/formatter"
"github.com/gol4ng/logger/handler"
)

func main(){
// logger will print on STDOUT with default line format
myLogger := logger.NewLogger(handler.Stream(os.Stdout, formatter.NewDefaultFormatter()))

clientStack := httpware.TripperwareStack(
tripperware.InjectLogger(myLogger),
tripperware.CorrelationId(),
tripperware.Logger(myLogger),
)

c := http.Client{
Transport: clientStack.DecorateRoundTripper(http.DefaultTransport),
}

c.Get("http://google.com")
// Will log
//<info> http client GET http://google.com [status_code:301, duration:27.524999ms, content_length:219] {"http_duration":0.027524999,"http_status":"301 Moved Permanently","http_status_code":301,"http_response_length":219,"http_method":"GET","http_url":"http://google.com","http_start_time":"2019-12-03T10:47:38+01:00","http_kind":"client"}
//<info> http client GET http://www.google.com/ [status_code:200, duration:51.047002ms, content_length:-1] {"http_kind":"client","http_duration":0.051047002,"http_status":"200 OK","http_status_code":200,"http_response_length":-1,"http_method":"GET","http_url":"http://www.google.com/","http_start_time":"2019-12-03T10:47:38+01:00"}
}
```

### Middleware
Log you're incoming http server request

```
<debug> http server received GET / {"http_url":"/","http_start_time":"2019-12-13T17:15:30+01:00","http_kind":"server","Correlation-Id":"SBeEdhRhUl","http_header":{"Accept-Encoding":["gzip"],"Correlation-Id":["SBeEdhRhUl"],"User-Agent":["Go-http-client/1.1"]},"http_method":"GET"}
<info> handler log info {"Correlation-Id":"SBeEdhRhUl"}
<info> http server GET / [status_code:200, duration:290.156µs, content_length:0] {"http_kind":"server","http_duration":0.000290156,"http_status_code":200,"Correlation-Id":"SBeEdhRhUl","http_method":"GET","http_url":"/","http_start_time":"2019-12-13T17:15:30+01:00","http_status":"OK","http_response_length":0,"http_header":{"Accept-Encoding":["gzip"],"Correlation-Id":["SBeEdhRhUl"],"User-Agent":["Go-http-client/1.1"]}}
```

```go
package main

import (
"context"
"net"
"net/http"
"os"

"github.com/gol4ng/httpware/v2"
"github.com/gol4ng/logger"
"github.com/gol4ng/logger-http/middleware"
"github.com/gol4ng/logger/formatter"
"github.com/gol4ng/logger/handler"
)

func main() {
addr := ":5001"

myLogger := logger.NewLogger(
handler.Stream(os.Stdout, formatter.NewDefaultFormatter()),
)

// we recommend to use MiddlewareStack to simplify managing all wanted middlewares
// caution middleware order matters
stack := httpware.MiddlewareStack(
//middleware.InjectLogger(myLogger), // we recommend to use http.Server.BaseContext instead of this middleware
middleware.CorrelationId(),
middleware.Logger(myLogger),
)

h := http.HandlerFunc(func(writer http.ResponseWriter, innerRequest *http.Request) {
l := logger.FromContext(innerRequest.Context(), myLogger)
l.Info("handler log info", nil)
})

server := http.Server{
Addr: addr,
Handler: stack.DecorateHandler(h),
BaseContext: func(listener net.Listener) context.Context {
return logger.InjectInContext(context.Background(), myLogger)
},
}

go func() {
if err := server.ListenAndServe(); err != nil {
panic(err)
}
}()

http.Get("http://localhost" + addr)

//<debug> http server received GET / {"Correlation-Id":"zEDWO9gmZ6","http_header":{"Accept-Encoding":["gzip"],"Correlation-Id":["zEDWO9gmZ6"],"User-Agent":["Go-http-client/1.1"]},"http_method":"GET","http_url":"/","http_start_time":"2019-12-13T17:05:53+01:00","http_kind":"server"}
//<info> handler log info {"Correlation-Id":"zEDWO9gmZ6"}
//<info> http server GET / [status_code:200, duration:232.491µs, content_length:0] {"Correlation-Id":"zEDWO9gmZ6","http_header":{"Accept-Encoding":["gzip"],"Correlation-Id":["zEDWO9gmZ6"],"User-Agent":["Go-http-client/1.1"]},"http_method":"GET","http_url":"/","http_start_time":"2019-12-13T17:05:53+01:00","http_duration":0.000232491,"http_status":"OK","http_status_code":200,"http_kind":"server","http_response_length":0}
}
```
9 changes: 9 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module github.com/gol4ng/logger-http

go 1.13

require (
github.com/gol4ng/httpware/v2 v2.1.1
github.com/gol4ng/logger v0.3.0
github.com/stretchr/testify v1.4.0
)
75 changes: 75 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
bou.ke/monkey v1.0.1 h1:zEMLInw9xvNakzUUPjfS4Ds6jYPqCFx3m7bRmG5NH2U=
bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gol4ng/httpware/v2 v2.1.0 h1:eKtzvaoW/dw8YIAYTfhAvPDVmj0zDw8BkQSlLhjunUI=
github.com/gol4ng/httpware/v2 v2.1.0/go.mod h1:SIOrsksHg+ydQWikEj5KUVANB4lmwB8c5/NIBtdVzFM=
github.com/gol4ng/httpware/v2 v2.1.1 h1:8xd4iN+6e/xjBSy8jjF2Vm8/PvxswJznu8GdaNu+vs8=
github.com/gol4ng/httpware/v2 v2.1.1/go.mod h1:SIOrsksHg+ydQWikEj5KUVANB4lmwB8c5/NIBtdVzFM=
github.com/gol4ng/logger v0.3.0 h1:06RSztlRiQziN2uAcjAPfGhSisbcVcoDUpwg55QFq7I=
github.com/gol4ng/logger v0.3.0/go.mod h1:br5HY3VkhGzF83IhjDNE+PHkg2rV2Zy2uGPIfVfWZWg=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5 h1:mzjBh+S5frKOsOBobWIMAbXavqjmgO17k/2puhcFR94=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
14 changes: 14 additions & 0 deletions helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package logger_http

import (
"runtime"
"strconv"
)

func MessageWithFileLine(message string, skip int) string {
_, file, line, ok := runtime.Caller(1 + skip)
if ok {
message += " " + file + ":" + strconv.Itoa(line)
}
return message
}
48 changes: 48 additions & 0 deletions middleware/correlation_id.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package middleware

import (
"fmt"
"net/http"

"github.com/gol4ng/httpware/v2"
"github.com/gol4ng/httpware/v2/correlation_id"
http_middleware "github.com/gol4ng/httpware/v2/middleware"
"github.com/gol4ng/logger"
"github.com/gol4ng/logger/middleware"

logger_http "github.com/gol4ng/logger-http"
)

// CorrelationId is a decoration of CorrelationId(github.com/gol4ng/httpware/v2/middleware)
// it will add correlationId to gol4ng/logger context
// this middleware require request context with a WrappableLoggerInterface in order to properly add
// correlationID to the logger context
// eg:
// stack := httpware.MiddlewareStack(
// middleware.InjectLogger(l), // << Inject logger before CorrelationId
// middleware.CorrelationId(),
// )
func CorrelationId(options ...correlation_id.Option) httpware.Middleware {
warning := logger_http.MessageWithFileLine("correlationId need a wrappable logger", 1)
config := correlation_id.GetConfig(options...)
orig := http_middleware.CorrelationId(options...)
return func(next http.Handler) http.Handler {
return orig(http.HandlerFunc(func(writer http.ResponseWriter, req *http.Request) {
ctx := req.Context()
requestLogger := logger.FromContext(ctx, nil)
injected := false
if requestLogger != nil {
if wrappableLogger, ok := requestLogger.(logger.WrappableLoggerInterface); ok {
req = req.WithContext(logger.InjectInContext(ctx, wrappableLogger.WrapNew(middleware.Context(
logger.NewContext().Add(config.HeaderName, ctx.Value(config.HeaderName)),
))))
injected = true
}
}
if !injected {
fmt.Println(warning)
}
next.ServeHTTP(writer, req)
}))
}
}
Loading