Skip to content

Commit 057647a

Browse files
authored
🔥 feat: Add support for ForceColors in Logger middleware (#3428)
* Force the use of terminal colors via config option * docs: add example for forcing terminal colors in logger middleware * test: add benchmarks for logger middleware with forced colors * Add ForceColors field to 'whats new' * Show example in 'whats new'
1 parent bfef962 commit 057647a

File tree

5 files changed

+75
-2
lines changed

5 files changed

+75
-2
lines changed

docs/middleware/logger.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ app.Use(logger.New(logger.Config{
8989
DisableColors: true,
9090
}))
9191

92+
// Force the use of colors
93+
app.Use(logger.New(logger.Config{
94+
ForceColors: true,
95+
}))
96+
9297
// Use predefined formats
9398
app.Use(logger.New(logger.Config{
9499
Format: logger.FormatCommon,
@@ -166,6 +171,7 @@ Writing to os.File is goroutine-safe, but if you are using a custom Stream that
166171
| Stream | `io.Writer` | Stream is a writer where logs are written. | `os.Stdout` |
167172
| LoggerFunc | `func(c fiber.Ctx, data *Data, cfg Config) error` | Custom logger function for integration with logging libraries (Zerolog, Zap, Logrus, etc). Defaults to Fiber's default logger if not defined. | `see default_logger.go defaultLoggerInstance` |
168173
| DisableColors | `bool` | DisableColors defines if the logs output should be colorized. | `false` |
174+
| ForceColors | `bool` | ForceColors defines if the logs output should be colorized even when the output is not a terminal. | `false` |
169175

170176
## Default Config
171177

docs/whats_new.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,18 @@ curl "http://localhost:3000/header"
794794

795795
You can find more details about this feature in [/docs/api/log.md](./api/log.md#logger).
796796

797+
`logger.Config` now supports a new field called `ForceColors`. This field allows you to force the logger to always use colors, even if the output is not a terminal. This is useful when you want to ensure that the logs are always colored, regardless of the output destination.
798+
799+
```go
800+
package main
801+
802+
import "github.com/gofiber/fiber/v3/middleware/logger"
803+
804+
app.Use(logger.New(logger.Config{
805+
ForceColors: true,
806+
}))
807+
```
808+
797809
## 🧬 Middlewares
798810

799811
### Adaptor

middleware/logger/config.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ type Config struct {
8989
// Default: false
9090
DisableColors bool
9191

92+
// ForceColors forces the colors to be enabled even if the output is not a terminal
93+
//
94+
// Default: false
95+
ForceColors bool
96+
9297
enableColors bool
9398
enableLatency bool
9499
}
@@ -174,7 +179,7 @@ func configDefault(config ...Config) Config {
174179
}
175180

176181
// Enable colors if no custom format or output is given
177-
if !cfg.DisableColors && cfg.Stream == ConfigDefault.Stream {
182+
if (!cfg.DisableColors && cfg.Stream == ConfigDefault.Stream) || cfg.ForceColors {
178183
cfg.enableColors = true
179184
}
180185

middleware/logger/default_logger.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func beforeHandlerFunc(cfg Config) {
148148
// If colors are enabled, check terminal compatibility
149149
if cfg.enableColors {
150150
cfg.Stream = colorable.NewColorableStdout()
151-
if os.Getenv("TERM") == "dumb" || os.Getenv("NO_COLOR") == "1" || (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) {
151+
if !cfg.ForceColors && (os.Getenv("TERM") == "dumb" || os.Getenv("NO_COLOR") == "1" || (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))) {
152152
cfg.Stream = colorable.NewNonColorable(os.Stdout)
153153
}
154154
}

middleware/logger/logger_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,32 @@ func Test_Logger_EnableColors(t *testing.T) {
10181018
require.EqualValues(t, 1, *o)
10191019
}
10201020

1021+
// go test -run Test_Logger_ForceColors
1022+
func Test_Logger_ForceColors(t *testing.T) {
1023+
t.Parallel()
1024+
buf := bytebufferpool.Get()
1025+
defer bytebufferpool.Put(buf)
1026+
1027+
app := fiber.New()
1028+
1029+
app.Use(New(Config{
1030+
Format: "${ip}${status}${method}${path}${error}\n",
1031+
Stream: buf,
1032+
DisableColors: true,
1033+
ForceColors: true,
1034+
}))
1035+
1036+
// Alias colors
1037+
colors := app.Config().ColorScheme
1038+
1039+
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
1040+
require.NoError(t, err)
1041+
require.Equal(t, fiber.StatusNotFound, resp.StatusCode)
1042+
1043+
expected := fmt.Sprintf("0.0.0.0%s404%s%sGET%s/%sCannot GET /%s\n", colors.Yellow, colors.Reset, colors.Cyan, colors.Reset, colors.Red, colors.Reset)
1044+
require.Equal(t, expected, buf.String())
1045+
}
1046+
10211047
// go test -v -run=^$ -bench=Benchmark_Logger$ -benchmem -count=4
10221048
func Benchmark_Logger(b *testing.B) {
10231049
b.Run("NoMiddleware", func(bb *testing.B) {
@@ -1064,6 +1090,18 @@ func Benchmark_Logger(b *testing.B) {
10641090
benchmarkSetup(bb, app, "/")
10651091
})
10661092

1093+
b.Run("DefaultFormatForceColors", func(bb *testing.B) {
1094+
app := fiber.New()
1095+
app.Use(New(Config{
1096+
Stream: io.Discard,
1097+
ForceColors: true,
1098+
}))
1099+
app.Get("/", func(c fiber.Ctx) error {
1100+
return c.SendString("Hello, World!")
1101+
})
1102+
benchmarkSetup(bb, app, "/")
1103+
})
1104+
10671105
b.Run("DefaultFormatWithFiberLog", func(bb *testing.B) {
10681106
app := fiber.New()
10691107
logger := fiberlog.DefaultLogger()
@@ -1245,6 +1283,18 @@ func Benchmark_Logger_Parallel(b *testing.B) {
12451283
benchmarkSetupParallel(bb, app, "/")
12461284
})
12471285

1286+
b.Run("DefaultFormatForceColors", func(bb *testing.B) {
1287+
app := fiber.New()
1288+
app.Use(New(Config{
1289+
Stream: io.Discard,
1290+
ForceColors: true,
1291+
}))
1292+
app.Get("/", func(c fiber.Ctx) error {
1293+
return c.SendString("Hello, World!")
1294+
})
1295+
benchmarkSetupParallel(bb, app, "/")
1296+
})
1297+
12481298
b.Run("WithTagParameter", func(bb *testing.B) {
12491299
app := fiber.New()
12501300
app.Use(New(Config{

0 commit comments

Comments
 (0)