Skip to content

Commit

Permalink
Merge pull request #652 from kallydev/master
Browse files Browse the repository at this point in the history
🔥 Add logger middleware time zone support
  • Loading branch information
Fenny authored Jul 21, 2020
2 parents f5f2d99 + 8eaab1d commit 42d8f4d
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 3 deletions.
35 changes: 32 additions & 3 deletions middleware/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ type (
// Optional. Default: 15:04:05
TimeFormat string

// TimeZone can be specified, such as "UTC" and "America/New_York" and "Asia/Chongqing", etc
//
// Optional. Default: Local
TimeZone string

// Output is a writter where logs are written
//
// Default: os.Stderr
Expand Down Expand Up @@ -133,6 +138,7 @@ var LoggerConfigDefault = LoggerConfig{
Next: nil,
Format: "#${pid} - ${time} ${status} - ${latency} ${method} ${path}\n",
TimeFormat: "2006/01/02 15:04:05",
TimeZone: "Local",
Output: os.Stderr,
}

Expand All @@ -142,6 +148,7 @@ Logger allows the following config arguments in any order:
- Logger(next func(*fiber.Ctx) bool)
- Logger(output io.Writer)
- Logger(format string)
- Logger(timeZone string)
- Logger(timeFormat string)
- Logger(config LoggerConfig)
*/
Expand All @@ -157,6 +164,8 @@ func Logger(options ...interface{}) fiber.Handler {
case string:
if strings.Contains(opt, "${") {
config.Format = opt
} else if isTimeZone(opt) {
config.TimeZone = opt
} else {
config.TimeFormat = opt
}
Expand Down Expand Up @@ -184,6 +193,9 @@ func logger(config LoggerConfig) fiber.Handler {
if config.Format == "" {
config.Format = LoggerConfigDefault.Format
}
if config.TimeZone == "" {
config.TimeZone = LoggerConfigDefault.TimeZone
}
if config.TimeFormat == "" {
config.TimeFormat = LoggerConfigDefault.TimeFormat
}
Expand All @@ -203,14 +215,13 @@ func logger(config LoggerConfig) fiber.Handler {

var tmpl loggerTemplate
tmpl.new(config.Format, "${", "}")

timestamp := time.Now().Format(config.TimeFormat)
timestamp := nowTimeString(config.TimeZone, config.TimeFormat)
// Update date/time every second in a separate go routine
if strings.Contains(config.Format, "${time}") {
go func() {
for {
mutex.Lock()
timestamp = time.Now().Format(config.TimeFormat)
timestamp = nowTimeString(config.TimeZone, config.TimeFormat)
mutex.Unlock()
time.Sleep(500 * time.Millisecond)
}
Expand Down Expand Up @@ -354,6 +365,24 @@ func logger(config LoggerConfig) fiber.Handler {
}
}

func nowTimeString(timeZone, layout string) string {
// This is different from Golang's time package which returns UTC, and Local is better than it
if timeZone == "" {
timeZone = "UTC"
}
location, err := time.LoadLocation(timeZone)
if err != nil {
log.Fatalf("Logger: failed to load time zone: %e\n", err)
}
return time.Now().In(location).Format(layout)
}

// Use Golang's time package to determine whether the TimeZone is available
func isTimeZone(name string) bool {
_, err := time.LoadLocation(name)
return err == nil
}

// MIT License fasttemplate
// Copyright (c) 2015 Aliaksandr Valialkin
// https://github.com/valyala/fasttemplate/blob/master/LICENSE
Expand Down
9 changes: 9 additions & 0 deletions middleware/logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ func main() {
// Pass a custom output
app.Use(middleware.Logger(os.Stdout))

// Pass a custom time zone
app.Use(middleware.Logger("UTC"))

// Pass a custom timeformat
app.Use(middleware.Logger("15:04:05"))

Expand All @@ -34,6 +37,7 @@ func main() {
app.Use(middleware.Logger(middleware.LoggerConfig{
Format: "${time} ${method} ${path}",
TimeFormat: "15:04:05",
TimeZone: "Asia/Chongqing",
Output: os.Stdout,
}))

Expand Down Expand Up @@ -87,6 +91,11 @@ type LoggerConfig struct {
// Optional. Default: 15:04:05
TimeFormat string

// TimeZone can be specified, such as "UTC" and "America/New_York" and "Asia/Chongqing", etc
//
// Optional. Default: Local
TimeZone string

// Output is a writter where logs are written
//
// Default: os.Stderr
Expand Down
52 changes: 52 additions & 0 deletions middleware/logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func Test_Middleware_Logger_Options_And_WithConfig(t *testing.T) {
Logger("15:04:05"),
Logger("${time} ${method} ${path} - ${ip} - ${status} - ${latency}\n"),
Logger(LoggerConfig{Output: buf}),
Logger("UTC"),
}

for i, logger := range loggers {
Expand All @@ -128,10 +129,61 @@ func Test_Middleware_Logger_Options_And_WithConfig(t *testing.T) {
utils.AssertEqual(t, 51, len(res), fmt.Sprintf("Has length: %v, expected: %v, raw: %s", len(res), 51, res))
} else if i == 3 {
utils.AssertEqual(t, 48, len(res), fmt.Sprintf("Has length: %v, expected: %v, raw: %s", len(res), 48, res))
} else if i == 4 {
utils.AssertEqual(t, 48, len(res), fmt.Sprintf("Has length: %v, expected: %v, raw: %s", len(res), 48, res))
}
}
}

func Test_isTimeZone(t *testing.T) {
type args struct {
name string
}
tests := []struct {
name string
args args
want bool
}{
{
"Empty",
args{""},
true,
},
{
"Local",
args{name: "Local"},
true,
},
{
"UTC",
args{name: "UTC"},
true,
},
{
"America/New_York",
args{name: "America/New_York"},
true,
},
{
"Asia/Chongqing",
args{"Asia/Chongqing"},
true,
},
{
"Time format",
args{name: "2006-01-02 15:04:05"},
false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := isTimeZone(tt.args.name); got != tt.want {
t.Errorf("isTimeZone() = %v, want %v", got, tt.want)
}
})
}
}

// go test -v -run=^$ -bench=Benchmark_Middleware_Logger -benchmem -count=4
func Benchmark_Middleware_Logger(b *testing.B) {

Expand Down

0 comments on commit 42d8f4d

Please sign in to comment.