Skip to content

Commit

Permalink
v3: Updates to fiberlog benchmarks and documentation (#3059)
Browse files Browse the repository at this point in the history
* Add missing benchmarks for fiberlog. Rewrite docs

* Update log.md
  • Loading branch information
gaby authored Jul 5, 2024
1 parent 6108475 commit 04528f7
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 30 deletions.
55 changes: 38 additions & 17 deletions docs/api/log.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ description: Fiber's built-in log package
sidebar_position: 6
---

We can use logs to observe program behavior, diagnose problems, or configure corresponding alarms.
And defining a well structured log can improve search efficiency and facilitate handling of problems.
Logs serve as an essential tool for observing program behavior, diagnosing issues, and setting up corresponding alerts. Well-structured logs can significantly enhance search efficiency and streamline the troubleshooting process.

Fiber provides a default way to print logs in the standard output.
It also provides several global functions, such as `log.Info`, `log.Errorf`, `log.Warnw`, etc.
Fiber offers a default mechanism for logging to standard output. Additionally, it provides several global functions, including `log.Info`, `log.Errorf`, `log.Warnw`, among others, to facilitate comprehensive logging capabilities.

## Log levels

Expand Down Expand Up @@ -44,8 +42,10 @@ type AllLogger interface {
```

## Print log
Note: The method of calling the Fatal level will interrupt the program running after printing the log, please use it with caution.
Directly print logs of different levels, which will be entered into messageKey, the default is msg.
Note: The Fatal level method will terminate the program after printing the log message. Please use it with caution.

### Basic Logging
Logs of different levels can be directly printed. These will be entered into `messageKey`, with the default key being `msg`.

```go
log.Info("Hello, World!")
Expand All @@ -56,7 +56,9 @@ log.Error("Houston, we have a problem.")
log.Fatal("So Long, and Thanks for All the Fislog.")
log.Panic("The system is down.")
```
Format and print logs of different levels, all methods end with f

### Formatted Logging
Logs of different levels can be formatted before printing. All such methods end with an `f`.

```go
log.Debugf("Hello %s", "boy")
Expand All @@ -66,7 +68,8 @@ log.Errorf("%s, we have a problem.", "Master Shifu")
log.Fatalf("So Long, and Thanks for All the %s.", "banana")
```

Print a message with the key and value, or `KEYVALS UNPAIRED` if the key and value are not a pair.
### Key-Value Logging
Print a message with key-value pairs. If the key and value are not paired correctly, the log will output `KEYVALS UNPAIRED`.

```go
log.Debugw("", "Hello", "boy")
Expand All @@ -77,7 +80,7 @@ log.Fatalw("", "fruit", "banana")
```

## Global log
If you are in a project and just want to use a simple log function that can be printed at any time in the global, we provide a global log.
For projects that require a simple, global logging function to print messages at any time, Fiber provides a global log.

```go
import "github.com/gofiber/fiber/v3/log"
Expand All @@ -86,8 +89,11 @@ log.Info("info")
log.Warn("warn")
```

The above is using the default `log.DefaultLogger` standard output.
You can also find an already implemented adaptation under contrib, or use your own implemented Logger and use `log.SetLogger` to set the global log logger.
These global log functions allow you to log messages conveniently throughout your project.

The above example uses the default `log.DefaultLogger` for standard output. You can also find various pre-implemented adapters under the [contrib](https://github.com/gofiber/contrib) package such as `fiberzap` and `fiberzerolog`, or you can implement your own logger and set it as the global logger using `log.SetLogger`.This flexibility allows you to tailor the logging behavior to suit your project's needs.

Here's an example using a custom logger:

```go
import (
Expand All @@ -107,8 +113,7 @@ fiberlog.SetLogger(customLogger)
```

## Set Level
`log.SetLevel` sets the level of logs below which logs will not be output.
The default logger is LevelTrace.
`log.SetLevel` sets the minimum level of logs that will be output. The default log level is `LevelTrace`.

Note that this method is not **concurrent-safe**.

Expand All @@ -117,9 +122,14 @@ import "github.com/gofiber/fiber/v3/log"

log.SetLevel(log.LevelInfo)
```

Setting the log level allows you to control the verbosity of the logs, filtering out messages below the specified level.

## Set output

`log.SetOutput` sets the output destination of the logger. The default logger types the log in the console.
`log.SetOutput` sets the output destination of the logger. By default, the logger outputs logs to the console.

### Writing logs to stderr

```go
var logger AllLogger = &defaultLogger{
Expand All @@ -128,7 +138,11 @@ var logger AllLogger = &defaultLogger{
}
```

Set the output destination to the file.
This allows you to customize where the logs are written, such as to a file, an external logging service, or any other desired destination.

### Writing logs to a file

Set the output destination to the file, in this case `test.log`:

```go
// Output to ./test.log file
Expand All @@ -138,18 +152,25 @@ if err != nil {
}
log.SetOutput(f)
```
Set the output destination to the console and file.

### Writing logs to both console and file

The following example will write the logs to both `test.log` and `stdout`:

```go
// Output to ./test.log file
file, _ := os.OpenFile("test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
iw := io.MultiWriter(os.Stdout, file)
log.SetOutput(iw)
```

## Bind context
Set the context, using the following method will return a `CommonLogger` instance bound to the specified context

To bind a logger to a specific context, use the following method. This will return a `CommonLogger` instance that is bound to the specified context.

```go
commonLogger := log.WithContext(ctx)
commonLogger.Info("info")
```

Binding the logger to a context allows you to include context-specific information in your logs, improving traceability and debugging.
2 changes: 1 addition & 1 deletion log/default_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ func Benchmark_LogfKeyAndValues(b *testing.B) {
}
}

func Benchmark_LogfKeyAndValuesParallel(b *testing.B) {
func Benchmark_LogfKeyAndValues_Parallel(b *testing.B) {
tests := []struct {
name string
level Level
Expand Down
144 changes: 144 additions & 0 deletions log/fiberlog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,147 @@ func Test_Fiberlog_SetLevel(t *testing.T) {
})
}
}

func Benchmark_DefaultSystemLogger(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = DefaultLogger()
}
}

func Benchmark_SetLogger(b *testing.B) {
setLog := &defaultLogger{
stdlog: log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds),
depth: 6,
}

b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
SetLogger(setLog)
}
}

func Benchmark_Fiberlog_SetLevel(b *testing.B) {
mockLogger := &defaultLogger{}
SetLogger(mockLogger)

// Test cases
testCases := []struct {
name string
level Level
expected Level
}{
{
name: "Test case 1",
level: LevelDebug,
expected: LevelDebug,
},
{
name: "Test case 2",
level: LevelInfo,
expected: LevelInfo,
},
{
name: "Test case 3",
level: LevelWarn,
expected: LevelWarn,
},
{
name: "Test case 4",
level: LevelError,
expected: LevelError,
},
{
name: "Test case 5",
level: LevelFatal,
expected: LevelFatal,
},
}

for _, tc := range testCases {
b.ReportAllocs()
b.ResetTimer()
b.Run(tc.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
SetLevel(tc.level)
}
})
}
}

func Benchmark_DefaultSystemLogger_Parallel(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
_ = DefaultLogger()
}
})
}

func Benchmark_SetLogger_Parallel(b *testing.B) {
setLog := &defaultLogger{
stdlog: log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds),
depth: 6,
}

b.ReportAllocs()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
SetLogger(setLog)
}
})
}

func Benchmark_Fiberlog_SetLevel_Parallel(b *testing.B) {
mockLogger := &defaultLogger{}
SetLogger(mockLogger)

// Test cases
testCases := []struct {
name string
level Level
expected Level
}{
{
name: "Test case 1",
level: LevelDebug,
expected: LevelDebug,
},
{
name: "Test case 2",
level: LevelInfo,
expected: LevelInfo,
},
{
name: "Test case 3",
level: LevelWarn,
expected: LevelWarn,
},
{
name: "Test case 4",
level: LevelError,
expected: LevelError,
},
{
name: "Test case 5",
level: LevelFatal,
expected: LevelFatal,
},
}

for _, tc := range testCases {
b.Run(tc.name+"_Parallel", func(bb *testing.B) {
bb.ReportAllocs()
bb.ResetTimer()
bb.RunParallel(func(pb *testing.PB) {
for pb.Next() {
SetLevel(tc.level)
}
})
})
}
}
24 changes: 12 additions & 12 deletions middleware/cors/cors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1060,8 +1060,8 @@ func Benchmark_CORS_NewHandler(b *testing.B) {
}
}

// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerParallel -benchmem -count=4
func Benchmark_CORS_NewHandlerParallel(b *testing.B) {
// go test -v -run=^$ -bench=Benchmark_CORS_NewHandler_Parallel -benchmem -count=4
func Benchmark_CORS_NewHandler_Parallel(b *testing.B) {
app := fiber.New()
c := New(Config{
AllowOrigins: []string{"http://localhost", "http://example.com"},
Expand Down Expand Up @@ -1133,8 +1133,8 @@ func Benchmark_CORS_NewHandlerSingleOrigin(b *testing.B) {
}
}

// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerSingleOriginParallel -benchmem -count=4
func Benchmark_CORS_NewHandlerSingleOriginParallel(b *testing.B) {
// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerSingleOrigin_Parallel -benchmem -count=4
func Benchmark_CORS_NewHandlerSingleOrigin_Parallel(b *testing.B) {
app := fiber.New()
c := New(Config{
AllowOrigins: []string{"http://example.com"},
Expand Down Expand Up @@ -1205,8 +1205,8 @@ func Benchmark_CORS_NewHandlerWildcard(b *testing.B) {
}
}

// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerWildcardParallel -benchmem -count=4
func Benchmark_CORS_NewHandlerWildcardParallel(b *testing.B) {
// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerWildcard_Parallel -benchmem -count=4
func Benchmark_CORS_NewHandlerWildcard_Parallel(b *testing.B) {
app := fiber.New()
c := New(Config{
AllowMethods: []string{fiber.MethodGet, fiber.MethodPost, fiber.MethodPut, fiber.MethodDelete},
Expand Down Expand Up @@ -1279,8 +1279,8 @@ func Benchmark_CORS_NewHandlerPreflight(b *testing.B) {
}
}

// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerPreflightParallel -benchmem -count=4
func Benchmark_CORS_NewHandlerPreflightParallel(b *testing.B) {
// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerPreflight_Parallel -benchmem -count=4
func Benchmark_CORS_NewHandlerPreflight_Parallel(b *testing.B) {
app := fiber.New()
c := New(Config{
AllowOrigins: []string{"http://localhost", "http://example.com"},
Expand Down Expand Up @@ -1354,8 +1354,8 @@ func Benchmark_CORS_NewHandlerPreflightSingleOrigin(b *testing.B) {
}
}

// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerPreflightSingleOriginParallel -benchmem -count=4
func Benchmark_CORS_NewHandlerPreflightSingleOriginParallel(b *testing.B) {
// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerPreflightSingleOrigin_Parallel -benchmem -count=4
func Benchmark_CORS_NewHandlerPreflightSingleOrigin_Parallel(b *testing.B) {
app := fiber.New()
c := New(Config{
AllowOrigins: []string{"http://example.com"},
Expand Down Expand Up @@ -1428,8 +1428,8 @@ func Benchmark_CORS_NewHandlerPreflightWildcard(b *testing.B) {
}
}

// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerPreflightWildcardParallel -benchmem -count=4
func Benchmark_CORS_NewHandlerPreflightWildcardParallel(b *testing.B) {
// go test -v -run=^$ -bench=Benchmark_CORS_NewHandlerPreflightWildcard_Parallel -benchmem -count=4
func Benchmark_CORS_NewHandlerPreflightWildcard_Parallel(b *testing.B) {
app := fiber.New()
c := New(Config{
AllowMethods: []string{fiber.MethodGet, fiber.MethodPost, fiber.MethodPut, fiber.MethodDelete},
Expand Down

0 comments on commit 04528f7

Please sign in to comment.