From 616771aeff37ab24823391e30b1f73e3aa236914 Mon Sep 17 00:00:00 2001 From: Felix Ruess Date: Mon, 6 Jul 2020 20:58:46 +0200 Subject: [PATCH] Promtail: support unix timestamps with fractional seconds (#2301) * support unix timestamps with fractional seconds see #2193 * add test for parsing unix timestamp with fractions * mention Unix timestamp with fractions in docs * return error if timestamp is not split into two parts * don't capitalize error Co-authored-by: Cyril Tovena Co-authored-by: Cyril Tovena --- docs/clients/promtail/stages/timestamp.md | 2 +- pkg/logentry/stages/timestamp_test.go | 22 ++++++++++++++++++++++ pkg/logentry/stages/util.go | 17 +++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/docs/clients/promtail/stages/timestamp.md b/docs/clients/promtail/stages/timestamp.md index 9aac07abb1..3c1de27a94 100644 --- a/docs/clients/promtail/stages/timestamp.md +++ b/docs/clients/promtail/stages/timestamp.md @@ -44,7 +44,7 @@ of pre-defined formats to represent common forms: Additionally, support for common Unix timestamps is supported with the following `format` values: -- `Unix`: `1562708916` +- `Unix`: `1562708916` or with fractions `1562708916.000000123` - `UnixMs`: `1562708916414` - `UnixUs`: `1562708916414123` - `UnixNs`: `1562708916000000123` diff --git a/pkg/logentry/stages/timestamp_test.go b/pkg/logentry/stages/timestamp_test.go index 2736c812d0..b2f31d4480 100644 --- a/pkg/logentry/stages/timestamp_test.go +++ b/pkg/logentry/stages/timestamp_test.go @@ -223,6 +223,28 @@ func TestTimestampStage_Process(t *testing.T) { }, time.Date(2019, 7, 9, 21, 48, 36, 0, time.UTC), }, + "unix fractions ms success": { + TimestampConfig{ + Source: "ts", + Format: "Unix", + }, + map[string]interface{}{ + "somethigelse": "notimportant", + "ts": "1562708916.414123", + }, + time.Date(2019, 7, 9, 21, 48, 36, 414123*1000, time.UTC), + }, + "unix fractions ns success": { + TimestampConfig{ + Source: "ts", + Format: "Unix", + }, + map[string]interface{}{ + "somethigelse": "notimportant", + "ts": "1562708916.000000123", + }, + time.Date(2019, 7, 9, 21, 48, 36, 123, time.UTC), + }, "unix millisecond success": { TimestampConfig{ Source: "ts", diff --git a/pkg/logentry/stages/util.go b/pkg/logentry/stages/util.go index bd4eac044f..407387f7c4 100644 --- a/pkg/logentry/stages/util.go +++ b/pkg/logentry/stages/util.go @@ -2,6 +2,7 @@ package stages import ( "fmt" + "math" "strconv" "strings" "time" @@ -64,6 +65,22 @@ func convertDateLayout(predef string, location *time.Location) parser { } case "Unix": return func(t string) (time.Time, error) { + if strings.Count(t, ".") == 1 { + split := strings.Split(t, ".") + if len(split) != 2 { + return time.Time{}, fmt.Errorf("can't split %v into two parts", t) + } + sec, err := strconv.ParseInt(split[0], 10, 64) + if err != nil { + return time.Time{}, err + } + frac, err := strconv.ParseInt(split[1], 10, 64) + if err != nil { + return time.Time{}, err + } + nsec := int64(float64(frac) * math.Pow(10, float64(9-len(split[1])))) + return time.Unix(sec, nsec), nil + } i, err := strconv.ParseInt(t, 10, 64) if err != nil { return time.Time{}, err