From 884c7e8962ad34b4f70d7fe995afb4d37a2e311c Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Tue, 18 Jul 2017 13:19:59 -0400 Subject: [PATCH] Cherry-pick #4658 to 5.x: Normalize times to common.Time with UTC time zone (#4684) * Normalize times to common.Time with UTC time zone (#4658) During event normalization convert any time objects to a common.Time and ensure that the time zone is UTC. Fixes #4569 (cherry picked from commit 29f4cc755ec7def513ae9222c1b69b7072c7ea15) * Fix changelog --- CHANGELOG.asciidoc | 1 + libbeat/common/event.go | 21 +++++++++++++++++++++ libbeat/common/event_test.go | 22 ++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index dc529d3e2240..cd59c6902153 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -30,6 +30,7 @@ https://github.com/elastic/beats/compare/v5.4.1...master[Check the HEAD diff] - Fix console output {pull}4045[4045] - Usage of field `_type` is now ignored and hardcoded to `doc`. {pull}3757[3757] +- Normalize all times to UTC to ensure proper index naming. {issue}4569[4569] *Filebeat* diff --git a/libbeat/common/event.go b/libbeat/common/event.go index 28b36209add1..24addc3b19c5 100644 --- a/libbeat/common/event.go +++ b/libbeat/common/event.go @@ -7,6 +7,7 @@ import ( "reflect" "strconv" "strings" + "time" "github.com/elastic/beats/libbeat/logp" @@ -118,6 +119,26 @@ func normalizeValue(value interface{}, keys ...string) (interface{}, []error) { return nil, nil } + // Normalize time values to a common.Time with UTC time zone. + switch v := value.(type) { + case time.Time: + value = Time(v.UTC()) + case []time.Time: + times := make([]Time, 0, len(v)) + for _, t := range v { + times = append(times, Time(t.UTC())) + } + value = times + case Time: + value = Time(time.Time(v).UTC()) + case []Time: + times := make([]Time, 0, len(v)) + for _, t := range v { + times = append(times, Time(time.Time(t).UTC())) + } + value = times + } + switch value.(type) { case encoding.TextMarshaler: text, err := value.(encoding.TextMarshaler).MarshalText() diff --git a/libbeat/common/event_test.go b/libbeat/common/event_test.go index 6a8a7fa6a324..59e41afcd6db 100644 --- a/libbeat/common/event_test.go +++ b/libbeat/common/event_test.go @@ -3,6 +3,7 @@ package common import ( "encoding/json" "testing" + "time" "github.com/elastic/beats/libbeat/logp" "github.com/stretchr/testify/assert" @@ -315,6 +316,27 @@ func TestMarshalFloatValues(t *testing.T) { assert.Equal(string(b), "{\"f\":5.000000}") } +func TestNormalizeTime(t *testing.T) { + ny, err := time.LoadLocation("America/New_York") + if err != nil { + t.Fatal(err) + } + + now := time.Now().In(ny) + v, errs := normalizeValue(now, "@timestamp") + if len(errs) > 0 { + t.Fatal(errs) + } + + utcCommonTime, ok := v.(Time) + if !ok { + t.Fatalf("expected common.Time, but got %T (%v)", v, v) + } + + assert.Equal(t, time.UTC, time.Time(utcCommonTime).Location()) + assert.True(t, now.Equal(time.Time(utcCommonTime))) +} + // Uses TextMarshaler interface. func BenchmarkConvertToGenericEventNetString(b *testing.B) { for i := 0; i < b.N; i++ {