Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔥 feat: Add Filter option to logger middleware #3333

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8a74eba
🔥 Feature(logger): Add Filter option to logger middleware
JIeJaitt Feb 27, 2025
0a70ee8
📚 Doc(logger): Clarify Filter middleware description
JIeJaitt Feb 27, 2025
efdd738
🚨 Test(logger): Enhance logger filter test with parallel subtests
JIeJaitt Feb 27, 2025
a652e62
🔒 Test(logger): Add mutex to prevent race conditions in logger test
JIeJaitt Feb 27, 2025
c1f2278
🔥 Feature(logger): Add Filter option to logger middleware
JIeJaitt Feb 27, 2025
2794761
📚 Doc(logger): Clarify Filter middleware description
JIeJaitt Feb 27, 2025
2fd940e
🚨 Test(logger): Enhance logger filter test with parallel subtests
JIeJaitt Feb 27, 2025
7dcc904
🔒 Test(logger): Add mutex to prevent race conditions in logger test
JIeJaitt Feb 27, 2025
d6e64a0
🚨 Test(logger): Refactor logger test to improve test isolation
JIeJaitt Feb 27, 2025
4cb5e1c
Merge branch 'jiejaitt-feature/filter-logger' of github.com:JIeJaitt/…
JIeJaitt Feb 27, 2025
93b57a9
Fix issue with unit-tests
gaby Feb 27, 2025
572233e
Merge branch 'main' into jiejaitt-feature/filter-logger
gaby Feb 27, 2025
b600183
Update middleware/logger/logger_test.go
gaby Feb 27, 2025
2154baf
Apply logger filter as soon as possible
gaby Mar 1, 2025
10e6cb9
Merge branch 'main' into jiejaitt-feature/filter-logger
gaby Mar 1, 2025
6528b9f
📚 Doc: Add logger filter configuration example to whats_new.md
JIeJaitt Mar 3, 2025
75976af
Merge branch 'main' into jiejaitt-feature/filter-logger
JIeJaitt Mar 3, 2025
288edb2
📚 Doc: Update logger filter documentation in whats_new.md
JIeJaitt Mar 3, 2025
e2295e5
📚 Doc: Update logger filter documentation and examples
JIeJaitt Mar 4, 2025
0ac13c8
🩹 Fix: improve what_new.md
JIeJaitt Mar 4, 2025
bb05227
Merge branch 'main' into jiejaitt-feature/filter-logger
JIeJaitt Mar 4, 2025
d3030b1
Merge branch 'main' into jiejaitt-feature/filter-logger
JIeJaitt Mar 6, 2025
82e27f3
Merge branch 'main' into jiejaitt-feature/filter-logger
JIeJaitt Mar 6, 2025
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
2 changes: 2 additions & 0 deletions docs/middleware/logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ Writing to os.File is goroutine-safe, but if you are using a custom Output that
| Property | Type | Description | Default |
|:-----------------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------|
| Next | `func(fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| Filter | `func(fiber.Ctx) bool` | Filter is a function that is called before the log string for a request is written to Output. | `nil` |
| Done | `func(fiber.Ctx, []byte)` | Done is a function that is called after the log string for a request is written to Output, and pass the log string as parameter. | `nil` |
| CustomTags | `map[string]LogFunc` | tagFunctions defines the custom tag action. | `map[string]LogFunc` |
| Format | `string` | Format defines the logging tags. | `[${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}\n` |
Expand All @@ -157,6 +158,7 @@ Writing to os.File is goroutine-safe, but if you are using a custom Output that
```go
var ConfigDefault = Config{
Next: nil,
Filter nil,
Done: nil,
Format: "[${time}] ${ip} ${status} - ${latency} ${method} ${path} ${error}\n",
TimeFormat: "15:04:05",
Expand Down
10 changes: 10 additions & 0 deletions middleware/logger/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ type Config struct {
// Optional. Default: nil
Next func(c fiber.Ctx) bool

// Filter is a function that is called before writing the log string.
// If it returns true, the log will be written; otherwise, it will be skipped.
//
// Optional. Default: nil
Filter func(c fiber.Ctx) bool

// Done is a function that is called after the log string for a request is written to Output,
// and pass the log string as parameter.
//
Expand Down Expand Up @@ -98,6 +104,7 @@ type LogFunc func(output Buffer, c fiber.Ctx, data *Data, extraParam string) (in
// ConfigDefault is the default config
var ConfigDefault = Config{
Next: nil,
Filter: nil,
Done: nil,
Format: defaultFormat,
TimeFormat: "15:04:05",
Expand Down Expand Up @@ -126,6 +133,9 @@ func configDefault(config ...Config) Config {
if cfg.Next == nil {
cfg.Next = ConfigDefault.Next
}
if cfg.Filter == nil {
cfg.Filter = ConfigDefault.Filter
}
if cfg.Done == nil {
cfg.Done = ConfigDefault.Done
}
Expand Down
5 changes: 5 additions & 0 deletions middleware/logger/default_logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ func defaultLoggerInstance(c fiber.Ctx, data *Data, cfg Config) error {
buf.WriteString("\n")
}

// Check if Filter is defined and call it
if cfg.Filter != nil && !cfg.Filter(c) {
return nil // Skip logging if Filter returns false
}

// Write buffer to output
writeLog(cfg.Output, buf.Bytes())

Expand Down
52 changes: 52 additions & 0 deletions middleware/logger/logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,58 @@ func Test_Logger_Done(t *testing.T) {
require.Positive(t, buf.Len(), 0)
}

func Test_Logger_Filter(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about how this is working.

If the condition is True, it will become False in defaultLogger. But we dont check for that in the test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gaby Thanks for the heads up. I've just checked and found a few things that need to be refined, it's almost midnight here, I'll submit a more complete unit test and documentation note tomorrow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. Thanks!

t.Parallel()

t.Run("Test Not Found", func(t *testing.T) {
t.Parallel()
app := fiber.New()

logOutput := bytes.Buffer{}

// Create a single logging middleware with both filter and output capture
app.Use(New(Config{
Filter: func(c fiber.Ctx) bool {
return c.Response().StatusCode() == fiber.StatusNotFound
},
Output: &logOutput,
}))

resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/nonexistent", nil))
require.NoError(t, err)
require.Equal(t, fiber.StatusNotFound, resp.StatusCode)

// Verify the log output contains the "404" message
require.Contains(t, logOutput.String(), "404")
})

t.Run("Test OK", func(t *testing.T) {
t.Parallel()
app := fiber.New()

logOutput := bytes.Buffer{}

// Create a single logging middleware with both filter and output capture
app.Use(New(Config{
Filter: func(c fiber.Ctx) bool {
return c.Response().StatusCode() == fiber.StatusNotFound
},
Output: &logOutput,
}))

app.Get("/", func(c fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})

resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
require.NoError(t, err)
require.Equal(t, fiber.StatusOK, resp.StatusCode)

// Verify the log output does not contain the "200" message
require.NotContains(t, logOutput.String(), "200")
})
}

// go test -run Test_Logger_ErrorTimeZone
func Test_Logger_ErrorTimeZone(t *testing.T) {
t.Parallel()
Expand Down
Loading