Skip to content

Commit

Permalink
30 support asctime field for timestamp (#139)
Browse files Browse the repository at this point in the history
* test(parse asctime field): add a test that fails to parse the asctime field

* feat(parse asctime field): add "asctime" into DefalutOptions.TimeFields

* feat(parse asctime field): try parse single element array([]interface{}) value into time field

* test(parse asctime): merge test cases into the table

* test(parse asctime): change into table-driven test
  • Loading branch information
KevRiver authored Dec 11, 2024
1 parent d50f608 commit b71cae5
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 3 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/fatih/color v1.16.0
github.com/gen2brain/beeep v0.0.0-20240516210008-9c006672e7f4
github.com/go-logfmt/logfmt v0.5.1
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/humanlogio/api/go v0.0.0-20241128170213-590d167300cd
github.com/humanlogio/humanlog-pro v0.0.0-20241129104809-3580d74828a9
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
github.com/humanlogio/api/go v0.0.0-20241128170213-590d167300cd h1:449C6cnB4W6DblDMPfCfA4xyEkiYMpngGf7TEX9O8ro=
github.com/humanlogio/api/go v0.0.0-20241128170213-590d167300cd/go.mod h1:+hU/MU1g6QvtbeknKOlUI1yEStVqkPJ8jmYIj63OV5I=
github.com/humanlogio/humanlog-pro v0.0.0-20241129104046-2603398b2ef1 h1:eDsZPPr9GBNNh8wy43wPlb/98R1uCHuxML/r99GIkP4=
github.com/humanlogio/humanlog-pro v0.0.0-20241129104046-2603398b2ef1/go.mod h1:q+Kj7V58BQVVzGgcoyhtE2RXXprEi6DrqmhV/cThKkc=
github.com/humanlogio/humanlog-pro v0.0.0-20241129104809-3580d74828a9 h1:tdUCzFh8qvnWNCmxub0KSj1lIiCeWqvRjsMSSIApneE=
github.com/humanlogio/humanlog-pro v0.0.0-20241129104809-3580d74828a9/go.mod h1:zq05mTZQXvKheFiAGlPx6+VSo29jw2ER8oy8DIQKW2Q=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
Expand Down
2 changes: 1 addition & 1 deletion handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Handler interface {

var DefaultOptions = func() *HandlerOptions {
opts := &HandlerOptions{
TimeFields: []string{"time", "ts", "@timestamp", "timestamp", "Timestamp"},
TimeFields: []string{"time", "ts", "@timestamp", "timestamp", "Timestamp", "asctime"},
MessageFields: []string{"message", "msg", "Body"},
LevelFields: []string{"level", "lvl", "loglevel", "severity", "SeverityText"},
timeNow: time.Now,
Expand Down
36 changes: 36 additions & 0 deletions json_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import (
"testing"
"time"

"github.com/google/go-cmp/cmp"
typesv1 "github.com/humanlogio/api/go/types/v1"
"github.com/humanlogio/humanlog"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/timestamppb"
)

func TestJSONHandler_UnmarshalJSON_ParsesFields(t *testing.T) {
Expand Down Expand Up @@ -199,3 +202,36 @@ func TestJsonHandler_TryHandle_FlattenedArrayFields_NestedArray(t *testing.T) {
require.Equal(t, "world", handler.Fields["peers.2.1"])
require.Equal(t, "\"bar\"", handler.Fields["peers.3.foo"])
}

func TestParseAsctimeFields(t *testing.T) {
tests := []struct {
name string
raw []byte
want *timestamppb.Timestamp
}{
{
name: "asctime",
raw: []byte(`{"asctime": ["12-05-05 22:11:08,506248"]}`),
want: timestamppb.New(time.Date(2012, 5, 5, 22, 11, 8, 506248000, time.UTC)),
},
{
name: "time",
raw: []byte(`{"time": "12-05-05 22:11:08,506248"}`),
want: timestamppb.New(time.Date(2012, 5, 5, 22, 11, 8, 506248000, time.UTC)),
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
opts := humanlog.DefaultOptions()
h := humanlog.JSONHandler{Opts: opts}
ev := new(typesv1.StructuredLogEvent)
if !h.TryHandle(test.raw, ev) {
t.Fatalf("failed to handle log")
}
// timezone should be identified before parsing... we can't just treat as UTC
got := ev.Timestamp
require.Empty(t, cmp.Diff(test.want, got, protocmp.Transform()))
})
}
}
13 changes: 13 additions & 0 deletions time_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var TimeFormats = []string{
time.StampNano,
"2006/01/02 15:04:05",
"2006/01/02 15:04:05.999999999",
"06-01-02 15:04:05,999",
}

func parseTimeFloat64(value float64) time.Time {
Expand Down Expand Up @@ -86,6 +87,18 @@ func tryParseTime(value interface{}) (time.Time, bool) {
return parseTimeFloat64(float64(v)), true
case int64:
return parseTimeFloat64(float64(v)), true
case []interface{}:
if len(v) == 1 {
if timeStr, ok := v[0].(string); ok {
for _, layout := range TimeFormats {
t, err := time.Parse(layout, timeStr)
if err == nil {
t = fixTimebeforeUnixZero(t)
return t, true
}
}
}
}
}
return t, false
}

0 comments on commit b71cae5

Please sign in to comment.