Skip to content

Commit

Permalink
Add date offset and timezone options to date processor (influxdata#6886)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielnelson authored and Mathieu Lecarme committed Apr 17, 2020
1 parent ee4685f commit 1336c84
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
renamed to `sqlserver_azure_db_resource_stats` due to an issue where numeric
metrics were previously being reported incorrectly as strings.

- The `date` processor now uses the UTC timezone when creating its tag. In
previous versions the local time was used.

#### New Outputs

- [warp10](/plugins/outputs/warp10/README.md) - Contributed by @aurrelhebert
Expand Down
19 changes: 19 additions & 0 deletions plugins/processors/date/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ A few example usecases include:
## Date format string, must be a representation of the Go "reference time"
## which is "Mon Jan 2 15:04:05 -0700 MST 2006".
date_format = "Jan"

## Offset duration added to the date string when writing the new tag.
# date_offset = "0s"

## Timezone to use when generating the date. This can be set to one of
## "Local", "UTC", or to a location name in the IANA Time Zone database.
## example: timezone = "America/Los_Angeles"
# timezone = "UTC"
```

#### timezone

On Windows, only the `Local` and `UTC` zones are available by default. To use
other timezones, set the `ZONEINFO` environment variable to the location of
[`zoneinfo.zip`][zoneinfo]:
```
set ZONEINFO=C:\zoneinfo.zip
```

### Example
Expand All @@ -27,3 +44,5 @@ A few example usecases include:
- throughput lower=10i,upper=1000i,mean=500i 1560540094000000000
+ throughput,month=Jun lower=10i,upper=1000i,mean=500i 1560540094000000000
```

[zoneinfo]: https://github.com/golang/go/raw/50bd1c4d4eb4fac8ddeb5f063c099daccfb71b26/lib/time/zoneinfo.zip
35 changes: 31 additions & 4 deletions plugins/processors/date/date.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package date

import (
"time"

"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/internal"
"github.com/influxdata/telegraf/plugins/processors"
)

Expand All @@ -12,11 +15,25 @@ const sampleConfig = `
## Date format string, must be a representation of the Go "reference time"
## which is "Mon Jan 2 15:04:05 -0700 MST 2006".
date_format = "Jan"
## Offset duration added to the date string when writing the new tag.
# date_offset = "0s"
## Timezone to use when creating the tag. This can be set to one of
## "UTC", "Local", or to a location name in the IANA Time Zone database.
## example: timezone = "America/Los_Angeles"
# timezone = "UTC"
`

const defaultTimezone = "UTC"

type Date struct {
TagKey string `toml:"tag_key"`
DateFormat string `toml:"date_format"`
TagKey string `toml:"tag_key"`
DateFormat string `toml:"date_format"`
DateOffset internal.Duration `toml:"date_offset"`
Timezone string `toml:"timezone"`

location *time.Location
}

func (d *Date) SampleConfig() string {
Expand All @@ -27,16 +44,26 @@ func (d *Date) Description() string {
return "Dates measurements, tags, and fields that pass through this filter."
}

func (d *Date) Init() error {
var err error
// LoadLocation returns UTC if timezone is the empty string.
d.location, err = time.LoadLocation(d.Timezone)
return err
}

func (d *Date) Apply(in ...telegraf.Metric) []telegraf.Metric {
for _, point := range in {
point.AddTag(d.TagKey, point.Time().Format(d.DateFormat))
tm := point.Time().In(d.location).Add(d.DateOffset.Duration)
point.AddTag(d.TagKey, tm.Format(d.DateFormat))
}

return in
}

func init() {
processors.Add("date", func() telegraf.Processor {
return &Date{}
return &Date{
Timezone: defaultTimezone,
}
})
}
48 changes: 48 additions & 0 deletions plugins/processors/date/date_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import (
"time"

"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/internal"
"github.com/influxdata/telegraf/metric"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func MustMetric(name string, tags map[string]string, fields map[string]interface{}, metricTime time.Time) telegraf.Metric {
Expand All @@ -25,6 +28,8 @@ func TestMonthTag(t *testing.T) {
TagKey: "month",
DateFormat: "Jan",
}
err := dateFormatMonth.Init()
require.NoError(t, err)

currentTime := time.Now()
month := currentTime.Format("Jan")
Expand All @@ -43,6 +48,10 @@ func TestYearTag(t *testing.T) {
TagKey: "year",
DateFormat: "2006",
}

err := dateFormatYear.Init()
require.NoError(t, err)

currentTime := time.Now()
year := currentTime.Format("2006")

Expand All @@ -61,7 +70,46 @@ func TestOldDateTag(t *testing.T) {
DateFormat: "2006",
}

err := dateFormatYear.Init()
require.NoError(t, err)

m7 := MustMetric("foo", nil, nil, time.Date(1993, 05, 27, 0, 0, 0, 0, time.UTC))
customDateApply := dateFormatYear.Apply(m7)
assert.Equal(t, map[string]string{"year": "1993"}, customDateApply[0].Tags(), "should add tag 'year'")
}

func TestDateOffset(t *testing.T) {
plugin := &Date{
TagKey: "hour",
DateFormat: "15",
DateOffset: internal.Duration{Duration: 2 * time.Hour},
}

err := plugin.Init()
require.NoError(t, err)

metric := testutil.MustMetric(
"cpu",
map[string]string{},
map[string]interface{}{
"time_idle": 42.0,
},
time.Unix(1578603600, 0),
)

expected := []telegraf.Metric{
testutil.MustMetric(
"cpu",
map[string]string{
"hour": "23",
},
map[string]interface{}{
"time_idle": 42.0,
},
time.Unix(1578603600, 0),
),
}

actual := plugin.Apply(metric)
testutil.RequireMetricsEqual(t, expected, actual)
}

0 comments on commit 1336c84

Please sign in to comment.