Skip to content

Commit

Permalink
Add logger middleware template variables: ${time_unix_milli} and `$…
Browse files Browse the repository at this point in the history
…{time_unix_micro}` (#2206)

This patch introduces two template variables `${time_unix_milli}` and
`${time_unix_micro}` into the logger middleware.
Currently, there is no way to interpolate that UNIX milli and micro
seconds timestamp in a log entry, and go 1.17 or later runtime supports
the utility functions `time#UnixMilli()` and `time#UnixMicro()`
so this patch adds them as well.

see also: golang/go#44196

Signed-off-by: moznion <moznion@mail.moznion.net>
  • Loading branch information
moznion committed Jul 5, 2022
1 parent 0644cd6 commit ddb66e1
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 0 deletions.
8 changes: 8 additions & 0 deletions middleware/logger.go
Expand Up @@ -23,6 +23,8 @@ type (
// Tags to construct the logger format.
//
// - time_unix
// - time_unix_milli
// - time_unix_micro
// - time_unix_nano
// - time_rfc3339
// - time_rfc3339_nano
Expand Down Expand Up @@ -126,6 +128,12 @@ func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc {
switch tag {
case "time_unix":
return buf.WriteString(strconv.FormatInt(time.Now().Unix(), 10))
case "time_unix_milli":
// go 1.17 or later, it supports time#UnixMilli()
return buf.WriteString(strconv.FormatInt(time.Now().UnixNano()/1000000, 10))
case "time_unix_micro":
// go 1.17 or later, it supports time#UnixMicro()
return buf.WriteString(strconv.FormatInt(time.Now().UnixNano()/1000, 10))
case "time_unix_nano":
return buf.WriteString(strconv.FormatInt(time.Now().UnixNano(), 10))
case "time_rfc3339":
Expand Down
47 changes: 47 additions & 0 deletions middleware/logger_test.go
Expand Up @@ -7,6 +7,7 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -244,3 +245,49 @@ func BenchmarkLoggerWithConfig_withMapFields(b *testing.B) {
buf.Reset()
}
}

func TestLoggerTemplateWithTimeUnixMilli(t *testing.T) {
buf := new(bytes.Buffer)

e := echo.New()
e.Use(LoggerWithConfig(LoggerConfig{
Format: `${time_unix_milli}`,
Output: buf,
}))

e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "OK")
})

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

rec := httptest.NewRecorder()
e.ServeHTTP(rec, req)

unixMillis, err := strconv.ParseInt(buf.String(), 10, 64)
assert.NoError(t, err)
assert.WithinDuration(t, time.Unix(unixMillis/1000, 0), time.Now(), 3*time.Second)
}

func TestLoggerTemplateWithTimeUnixMicro(t *testing.T) {
buf := new(bytes.Buffer)

e := echo.New()
e.Use(LoggerWithConfig(LoggerConfig{
Format: `${time_unix_micro}`,
Output: buf,
}))

e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "OK")
})

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

rec := httptest.NewRecorder()
e.ServeHTTP(rec, req)

unixMicros, err := strconv.ParseInt(buf.String(), 10, 64)
assert.NoError(t, err)
assert.WithinDuration(t, time.Unix(unixMicros/1000000, 0), time.Now(), 3*time.Second)
}

0 comments on commit ddb66e1

Please sign in to comment.