feat!: splitting Logger function in FromRequest and FromCtx
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing

This commit is contained in:
Marvin Preuss 2022-01-24 11:45:27 +01:00
parent bc05c16a44
commit 930e291456
11 changed files with 3481 additions and 7 deletions

View File

@ -58,7 +58,7 @@ In other handlers you can access the UUID:
```golang
func anotherHandler(w http.ResponseWriter, r *http.Request) {
log := logginghandler.Logger(r)
log := logginghandler.FromRequest(r)
uuid, ok := logginghandler.GetUUID(r)
if !ok {
@ -77,6 +77,6 @@ func anotherHandler(w http.ResponseWriter, r *http.Request) {
The already prepared logger is also available:
```golang
l := logginghandler.Logger(r)
l := logginghandler.FromRequest(r)
l.Info().Msg("foo bar")
```

View File

@ -3,12 +3,14 @@
package logginghandler
import (
"context"
"net/http"
"time"
"github.com/justinas/alice"
"github.com/rs/zerolog"
"github.com/rs/zerolog/hlog"
"github.com/rs/zerolog/log"
)
// GetUUID gets the requests UUID from a request.
@ -21,11 +23,16 @@ func GetUUID(r *http.Request) (string, bool) {
return uuid.String(), true
}
// Logger returns a logger with the UUID set.
func Logger(r *http.Request) zerolog.Logger {
// FromRequest returns a logger with the UUID set from request.
func FromRequest(r *http.Request) zerolog.Logger {
return *hlog.FromRequest(r)
}
// FromCtx returns a logger with the UUID set from ctx.
func FromCtx(ctx context.Context) zerolog.Logger {
return *log.Ctx(ctx)
}
func Handler(log zerolog.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
chain := alice.New(

View File

@ -1,13 +1,17 @@
package logginghandler_test
import (
"bytes"
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.xsfx.dev/logginghandler"
)
@ -15,7 +19,7 @@ func Example() {
logger := log.With().Logger()
handler := logginghandler.Handler(logger)(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logger := logginghandler.Logger(r)
logger := logginghandler.FromRequest(r)
logger.Info().Msg("this is a request")
@ -32,7 +36,7 @@ func testHandler(w http.ResponseWriter, r *http.Request) {
func TestUUID(t *testing.T) {
t.Parallel()
assert := assert.New(t)
assert := require.New(t)
req, err := http.NewRequestWithContext(context.Background(), "GET", "/test", nil)
assert.NoError(err)
@ -43,3 +47,31 @@ func TestUUID(t *testing.T) {
assert.NotEmpty(rr.Header().Get("X-Request-ID"))
}
func TestFromCtx(t *testing.T) {
t.Parallel()
assert := require.New(t)
req, err := http.NewRequestWithContext(context.Background(), "GET", "/test", nil)
assert.NoError(err)
// Create buffer to store output.
var output bytes.Buffer
rr := httptest.NewRecorder()
handler := logginghandler.Handler(zerolog.New(&output))(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log := logginghandler.FromCtx(r.Context())
log.Info().Msg("hello world")
}))
handler.ServeHTTP(rr, req)
logs := strings.Split(output.String(), "\n")
assert.Len(logs, 3)
var jOut struct{ UUID string }
err = json.Unmarshal([]byte(logs[0]), &jOut)
assert.NoError(err)
assert.NotEmpty(jOut)
}

28
vendor/github.com/stretchr/testify/require/doc.go generated vendored Normal file
View File

@ -0,0 +1,28 @@
// Package require implements the same assertions as the `assert` package but
// stops test execution when a test fails.
//
// Example Usage
//
// The following is a complete example using require in a standard test function:
// import (
// "testing"
// "github.com/stretchr/testify/require"
// )
//
// func TestSomething(t *testing.T) {
//
// var a string = "Hello"
// var b string = "Hello"
//
// require.Equal(t, a, b, "The two words should be the same.")
//
// }
//
// Assertions
//
// The `require` package have same global functions as in the `assert` package,
// but instead of returning a boolean result they call `t.FailNow()`.
//
// Every assertion function also takes an optional string message as the final argument,
// allowing custom error messages to be appended to the message the assertion method outputs.
package require

View File

@ -0,0 +1,16 @@
package require
// Assertions provides assertion methods around the
// TestingT interface.
type Assertions struct {
t TestingT
}
// New makes a new Assertions object for the specified TestingT.
func New(t TestingT) *Assertions {
return &Assertions{
t: t,
}
}
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require_forward.go.tmpl -include-format-funcs"

1879
vendor/github.com/stretchr/testify/require/require.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
{{.Comment}}
func {{.DocInfo.Name}}(t TestingT, {{.Params}}) {
if h, ok := t.(tHelper); ok { h.Helper() }
if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return }
t.FailNow()
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
{{.CommentWithoutT "a"}}
func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) {
if h, ok := a.t.(tHelper); ok { h.Helper() }
{{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
}

View File

@ -0,0 +1,29 @@
package require
// TestingT is an interface wrapper around *testing.T
type TestingT interface {
Errorf(format string, args ...interface{})
FailNow()
}
type tHelper interface {
Helper()
}
// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful
// for table driven tests.
type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{})
// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful
// for table driven tests.
type ValueAssertionFunc func(TestingT, interface{}, ...interface{})
// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful
// for table driven tests.
type BoolAssertionFunc func(TestingT, bool, ...interface{})
// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful
// for table driven tests.
type ErrorAssertionFunc func(TestingT, error, ...interface{})
//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require.go.tmpl -include-format-funcs"

1
vendor/modules.txt vendored
View File

@ -21,6 +21,7 @@ github.com/rs/zerolog/log
# github.com/stretchr/testify v1.7.0
## explicit
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
# gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
## explicit
# gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b