Skip to content

Commit

Permalink
Merge pull request #965 from roman-wb/zerolog_headers_dict
Browse files Browse the repository at this point in the history
Improve Dict log for reqHeaders & resHeaders
  • Loading branch information
ReneWerner87 authored Feb 24, 2024
2 parents 611d7ed + 4e8d5ce commit 0a4bfe2
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 5 deletions.
4 changes: 2 additions & 2 deletions fiberzerolog/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ fiberzerolog.New(config ...fiberzerolog.Config) fiber.Handler
| Logger | `*zerolog.Logger` | Add custom zerolog logger. | `zerolog.New(os.Stderr).With().Timestamp().Logger()` |
| GetLogger | `func(*fiber.Ctx) zerolog.Logger` | Get custom zerolog logger, if it's defined the returned logger will replace the `Logger` value. | `nil` |
| Fields | `[]string` | Add fields what you want see. | `[]string{"latency", "status", "method", "url", "error"}` |
| WrapHeaders | bool | Wrap headers to dictionary.<br />If false: `{"method":"POST", "header-key":"header value"}`<br>If true: `{"method":"POST", "reqHeaders": {"header-key":"header value"}}` | `false` |
| Messages | `[]string` | Custom response messages. | `[]string{"Server error", "Client error", "Success"}` |
| Levels | `[]zerolog.Level` | Custom response levels. | `[]zerolog.Level{zerolog.ErrorLevel, zerolog.WarnLevel, zerolog.InfoLevel}` |
| SkipURIs | `[]string` | Skip logging these URI. | `[]string{}` |
| GetResBody | func(c *fiber.Ctx) []byte | Define a function to get response body when return non-nil.<br />eg: When use compress middleware, resBody is unreadable. you can set GetResBody func to get readable resBody. | `nil` |

| GetResBody | func(c *fiber.Ctx) []byte | Define a function to get response body when return non-nil.<br />eg: When use compress middleware, resBody is unreadable. you can set GetResBody func to get readable resBody. | `nil` |
## Example

```go
Expand Down
34 changes: 31 additions & 3 deletions fiberzerolog/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const (
FieldRequestID = "requestId"
FieldError = "error"
FieldReqHeaders = "reqHeaders"
FieldResHeaders = "resHeaders"
)

// Config defines the config for middleware.
Expand Down Expand Up @@ -79,6 +80,13 @@ type Config struct {
// Optional. Default: {"ip", "latency", "status", "method", "url", "error"}
Fields []string

// Wrap headers to dictionary.
// If false: {"method":"POST", "header-key":"header value"}
// If true: {"method":"POST", "reqHeaders": {"header-key":"header value"}}
//
// Optional. Default: false
WrapHeaders bool

// Custom response messages.
// Response codes >= 500 will be logged with Messages[0].
// Response codes >= 400 will be logged with Messages[1].
Expand Down Expand Up @@ -166,9 +174,29 @@ func (c *Config) logger(fc *fiber.Ctx, latency time.Duration, err error) zerolog
zc = zc.Err(err)
}
case FieldReqHeaders:
fc.Request().Header.VisitAll(func(k, v []byte) {
zc = zc.Bytes(string(k), v)
})
if c.WrapHeaders {
dict := zerolog.Dict()
fc.Request().Header.VisitAll(func(k, v []byte) {
dict.Bytes(string(k), v)
})
zc = zc.Dict(FieldReqHeaders, dict)
} else {
fc.Request().Header.VisitAll(func(k, v []byte) {
zc = zc.Bytes(string(k), v)
})
}
case FieldResHeaders:
if c.WrapHeaders {
dict := zerolog.Dict()
fc.Response().Header.VisitAll(func(k, v []byte) {
dict.Bytes(string(k), v)
})
zc = zc.Dict(FieldResHeaders, dict)
} else {
fc.Response().Header.VisitAll(func(k, v []byte) {
zc = zc.Bytes(string(k), v)
})
}
}
}

Expand Down
120 changes: 120 additions & 0 deletions fiberzerolog/zerolog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,126 @@ func Test_Req_Headers(t *testing.T) {
utils.AssertEqual(t, expected, logs)
}

func Test_Req_Headers_WrapHeaders(t *testing.T) {
t.Parallel()

var buf bytes.Buffer
logger := zerolog.New(&buf)

app := fiber.New()
app.Use(New(Config{
Logger: &logger,
Fields: []string{FieldReqHeaders},
WrapHeaders: true,
}))

app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("hello")
})

req := httptest.NewRequest("GET", "/", nil)
req.Header.Add("foo", "bar")
req.Header.Add("baz", "foo")

resp, err := app.Test(req)
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)

expected := map[string]interface{}{
"reqHeaders": map[string]interface{}{
"Host": "example.com",
"Baz": "foo",
"Foo": "bar",
},
"level": "info",
"message": "Success",
}

var logs map[string]any
_ = json.Unmarshal(buf.Bytes(), &logs)

utils.AssertEqual(t, expected, logs)
}

func Test_Res_Headers(t *testing.T) {
t.Parallel()

var buf bytes.Buffer
logger := zerolog.New(&buf)

app := fiber.New()
app.Use(New(Config{
Logger: &logger,
Fields: []string{FieldResHeaders},
}))

app.Get("/", func(c *fiber.Ctx) error {
c.Set("foo", "bar")
c.Set("baz", "foo")
return c.SendString("hello")
})

req := httptest.NewRequest("GET", "/", nil)

resp, err := app.Test(req)
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)

expected := map[string]interface{}{
"Content-Type": "text/plain; charset=utf-8",
"Baz": "foo",
"Foo": "bar",
"level": "info",
"message": "Success",
}

var logs map[string]any
_ = json.Unmarshal(buf.Bytes(), &logs)

utils.AssertEqual(t, expected, logs)
}

func Test_Res_Headers_WrapHeaders(t *testing.T) {
t.Parallel()

var buf bytes.Buffer
logger := zerolog.New(&buf)

app := fiber.New()
app.Use(New(Config{
Logger: &logger,
Fields: []string{FieldResHeaders},
WrapHeaders: true,
}))

app.Get("/", func(c *fiber.Ctx) error {
c.Set("foo", "bar")
c.Set("baz", "foo")
return c.SendString("hello")
})

req := httptest.NewRequest("GET", "/", nil)

resp, err := app.Test(req)
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)

expected := map[string]interface{}{
"resHeaders": map[string]interface{}{
"Content-Type": "text/plain; charset=utf-8",
"Baz": "foo",
"Foo": "bar",
},
"level": "info",
"message": "Success",
}

var logs map[string]any
_ = json.Unmarshal(buf.Bytes(), &logs)

utils.AssertEqual(t, expected, logs)
}

func Test_LoggerLevelsAndMessages(t *testing.T) {
t.Parallel()

Expand Down

0 comments on commit 0a4bfe2

Please sign in to comment.