accesslog: new HumanTime option as requested at #1661

This commit is contained in:
Gerasimos (Makis) Maropoulos 2020-10-16 09:53:22 +03:00
parent 8e51a296b9
commit b816156e77
No known key found for this signature in database
GPG Key ID: 5DBE766BD26A54E7
2 changed files with 52 additions and 4 deletions

View File

@ -1,7 +1,9 @@
package accesslog package accesslog
import ( import (
"bytes"
"io" "io"
"strconv"
"strings" "strings"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
@ -13,6 +15,7 @@ type JSON struct {
// Note that, if set to > 0 then jsoniter is used instead of easyjson. // Note that, if set to > 0 then jsoniter is used instead of easyjson.
Indent string Indent string
EscapeHTML bool EscapeHTML bool
HumanTime bool
jsoniter jsoniter.API jsoniter jsoniter.API
ac *AccessLog ac *AccessLog
@ -23,6 +26,8 @@ type JSON struct {
func (f *JSON) SetOutput(dest io.Writer) { func (f *JSON) SetOutput(dest io.Writer) {
f.ac, _ = dest.(*AccessLog) f.ac, _ = dest.(*AccessLog)
if indentStep := strings.Count(f.Indent, " "); indentStep > 0 { if indentStep := strings.Count(f.Indent, " "); indentStep > 0 {
// Note that: indent setting should always be spaces
// as the jsoniter does not support other chars.
f.jsoniter = jsoniter.Config{ f.jsoniter = jsoniter.Config{
TagKey: "json", TagKey: "json",
IndentionStep: indentStep, IndentionStep: indentStep,
@ -32,15 +37,52 @@ func (f *JSON) SetOutput(dest io.Writer) {
} }
} }
var (
timestampKeyB = []byte(`"timestamp":`)
timestampKeyIndentB = append(timestampKeyB, ' ')
timestampKeyVB = append(timestampKeyB, '0')
timestampIndentKeyVB = append(timestampKeyIndentB, '0')
)
// Format prints the logs in JSON format. // Format prints the logs in JSON format.
// Writes to the destination directly, // Writes to the destination directly,
// locks on each Format call. // locks on each Format call.
func (f *JSON) Format(log *Log) (bool, error) { func (f *JSON) Format(log *Log) (bool, error) {
if f.jsoniter != nil { if f.jsoniter != nil {
if f.HumanTime {
// 1. Don't write the unix timestamp,
// key will be visible though as we don't omit the field.
log.Timestamp = 0
}
b, err := f.jsoniter.Marshal(log) b, err := f.jsoniter.Marshal(log)
if err != nil { if err != nil {
return true, err return true, err
} }
if f.HumanTime {
// 2. Get the time text based on the configuration.
t := log.Now.Format(log.TimeFormat)
// 3. Find the "timestamp:$indent"
// and set it to the text one.
var (
oldT []byte
tsKey []byte
)
if f.Indent != "" {
oldT = timestampIndentKeyVB
tsKey = timestampKeyIndentB
} else {
oldT = timestampKeyVB
tsKey = timestampKeyB
}
newT := append(tsKey, strconv.Quote(t)...)
b = bytes.Replace(b, oldT, newT, 1)
}
f.ac.Write(append(b, newLine)) f.ac.Write(append(b, newLine))
return true, nil return true, nil
} }

View File

@ -25,7 +25,13 @@ func (f *JSON) writeEasyJSON(in *Log) error {
} else { } else {
out.RawString(prefix) out.RawString(prefix)
} }
out.Int64(int64(in.Timestamp))
if f.HumanTime {
t := in.Now.Format(in.TimeFormat)
out.String(t)
} else {
out.Int64(in.Timestamp)
}
} }
{ {
const prefix string = ",\"latency\":" const prefix string = ",\"latency\":"
@ -40,17 +46,17 @@ func (f *JSON) writeEasyJSON(in *Log) error {
{ {
const prefix string = ",\"method\":" const prefix string = ",\"method\":"
out.RawString(prefix) out.RawString(prefix)
out.String(string(in.Method)) out.String(in.Method)
} }
{ {
const prefix string = ",\"path\":" const prefix string = ",\"path\":"
out.RawString(prefix) out.RawString(prefix)
out.String(string(in.Path)) out.String(in.Path)
} }
if in.IP != "" { if in.IP != "" {
const prefix string = ",\"ip\":" const prefix string = ",\"ip\":"
out.RawString(prefix) out.RawString(prefix)
out.String(string(in.IP)) out.String(in.IP)
} }
if len(in.Query) != 0 { if len(in.Query) != 0 {
const prefix string = ",\"query\":" const prefix string = ",\"query\":"