Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds an 'output_precision' configuration parameter #2139

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ ie, a jitter of 5s and flush_interval 10s means flushes will happen every 10-15s
* **precision**: By default, precision will be set to the same timestamp order
as the collection interval, with the maximum being 1s. Precision will NOT
be used for service inputs, such as logparser and statsd. Valid values are
"ns", "us" (or "µs"), "ms", "s".
"1ns", "1us" (or "1µs"), "1ms", "1s".
* **logfile**: Specify the log file name. The empty string means to log to stdout.
* **debug**: Run telegraf in debug mode.
* **quiet**: Run telegraf in quiet mode (error messages only).
Expand Down
2 changes: 1 addition & 1 deletion etc/telegraf.conf
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
## By default, precision will be set to the same timestamp order as the
## collection interval, with the maximum being 1s.
## Precision will NOT be used for service inputs, such as logparser and statsd.
## Valid values are "ns", "us" (or "µs"), "ms", "s".
## Valid values are "1ns", "1us" (or "1µs"), "1ms", "1s".
precision = ""

## Logging configuration:
Expand Down
2 changes: 1 addition & 1 deletion etc/telegraf_windows.conf
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
urls = ["http://localhost:8086"] # required
# The target database for metrics (telegraf will create it if not exists)
database = "telegraf" # required
# Precision of writes, valid values are "ns", "us" (or "µs"), "ms", "s", "m", "h".
# Precision of writes, valid values are "1ns", "1us" (or "1µs"), "1ms", "1s", "1m", "1h".
# note: using second precision greatly helps InfluxDB compression
precision = "s"

Expand Down
2 changes: 1 addition & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ var header = `# Telegraf Configuration
## By default, precision will be set to the same timestamp order as the
## collection interval, with the maximum being 1s.
## Precision will NOT be used for service inputs, such as logparser and statsd.
## Valid values are "ns", "us" (or "µs"), "ms", "s".
## Valid values are "1ns", "1us" (or "1µs"), "1ms", "1s".
precision = ""

## Logging configuration:
Expand Down
14 changes: 13 additions & 1 deletion plugins/outputs/amqp/amqp.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ type AMQP struct {
RetentionPolicy string
// InfluxDB precision (DEPRECATED)
Precision string
// OutputPrecision string (parsed as a duration,
// only used for JSON output)
OutputPrecision string

// Path to CA file
SSLCA string `toml:"ssl_ca"`
Expand Down Expand Up @@ -78,6 +81,15 @@ var sampleConfig = `
## InfluxDB database
# database = "telegraf"

## The output_precision parameter can be used to specify the units that should
## be used when creating timestamps and is only used when the data_format is
## set to "json"; in that case valid values are "1ns", "1us" (or "1µs"), "1ms",
## or "1s"; for the other supported data_format types, the precision will depend
## on the data_format (seconds for "graphite" data, nanoseconds for "influx"
## data); if unspecified, then the timestamps output with "json" data
## will be in seconds
output_precision = ""

## Optional SSL Config
# ssl_ca = "/etc/telegraf/ca.pem"
# ssl_cert = "/etc/telegraf/cert.pem"
Expand Down Expand Up @@ -187,7 +199,7 @@ func (q *AMQP) Write(metrics []telegraf.Metric) error {
}
}

buf, err := q.serializer.Serialize(metric)
buf, err := q.serializer.Serialize(metric, q.OutputPrecision)
if err != nil {
return err
}
Expand Down
14 changes: 13 additions & 1 deletion plugins/outputs/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (

type File struct {
Files []string
// OutputPrecision string (parsed as a duration,
// only used for JSON output)
OutputPrecision string

writer io.Writer
closers []io.Closer
Expand All @@ -23,6 +26,15 @@ var sampleConfig = `
## Files to write to, "stdout" is a specially handled file.
files = ["stdout", "/tmp/metrics.out"]

## The output_precision parameter can be used to specify the units that should
## be used when creating timestamps and is only used when the data_format is
## set to "json"; in that case valid values are "1ns", "1us" (or "1µs"), "1ms",
## or "1s"; for the other supported data_format types, the precision will depend
## on the data_format (seconds for "graphite" data, nanoseconds for "influx"
## data); if unspecified, then the timestamps output with "json" data
## will be in seconds
output_precision = ""

## Data format to output.
## Each data format has it's own unique set of configuration options, read
## more about them here:
Expand Down Expand Up @@ -92,7 +104,7 @@ func (f *File) Write(metrics []telegraf.Metric) error {
}

for _, metric := range metrics {
b, err := f.serializer.Serialize(metric)
b, err := f.serializer.Serialize(metric, f.OutputPrecision)
if err != nil {
return fmt.Errorf("failed to serialize message: %s", err)
}
Expand Down
14 changes: 13 additions & 1 deletion plugins/outputs/kafka/kafka.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ type Kafka struct {
RequiredAcks int
// MaxRetry Tag
MaxRetry int
// OutputPrecision string (parsed as a duration,
// only used for JSON output)
OutputPrecision string

// Legacy SSL config options
// TLS client certificate
Expand Down Expand Up @@ -85,6 +88,15 @@ var sampleConfig = `
## The total number of times to retry sending a message
max_retry = 3

## The output_precision parameter can be used to specify the units that should
## be used when creating timestamps and is only used when the data_format is
## set to "json"; in that case valid values are "1ns", "1us" (or "1µs"), "1ms",
## or "1s"; for the other supported data_format types, the precision will depend
## on the data_format (seconds for "graphite" data, nanoseconds for "influx"
## data); if unspecified, then the timestamps output with "json" data
## will be in seconds
output_precision = ""

## Optional SSL Config
# ssl_ca = "/etc/telegraf/ca.pem"
# ssl_cert = "/etc/telegraf/cert.pem"
Expand Down Expand Up @@ -154,7 +166,7 @@ func (k *Kafka) Write(metrics []telegraf.Metric) error {
}

for _, metric := range metrics {
buf, err := k.serializer.Serialize(metric)
buf, err := k.serializer.Serialize(metric, k.OutputPrecision)
if err != nil {
return err
}
Expand Down
14 changes: 13 additions & 1 deletion plugins/outputs/mqtt/mqtt.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ var sampleConfig = `
# username = "telegraf"
# password = "metricsmetricsmetricsmetrics"

## The output_precision parameter can be used to specify the units that should
## be used when creating timestamps and is only used when the data_format is
## set to "json"; in that case valid values are "1ns", "1us" (or "1µs"), "1ms",
## or "1s"; for the other supported data_format types, the precision will depend
## on the data_format (seconds for "graphite" data, nanoseconds for "influx"
## data); if unspecified, then the timestamps output with "json" data
## will be in seconds
output_precision = ""

## Optional SSL Config
# ssl_ca = "/etc/telegraf/ca.pem"
# ssl_cert = "/etc/telegraf/cert.pem"
Expand All @@ -47,6 +56,9 @@ type MQTT struct {
Timeout internal.Duration
TopicPrefix string
QoS int `toml:"qos"`
// OutputPrecision string (parsed as a duration,
// only used for JSON output)
OutputPrecision string

// Path to CA file
SSLCA string `toml:"ssl_ca"`
Expand Down Expand Up @@ -128,7 +140,7 @@ func (m *MQTT) Write(metrics []telegraf.Metric) error {
t = append(t, metric.Name())
topic := strings.Join(t, "/")

buf, err := m.serializer.Serialize(metric)
buf, err := m.serializer.Serialize(metric, m.OutputPrecision)
if err != nil {
return fmt.Errorf("MQTT Could not serialize metric: %s",
metric.String())
Expand Down
13 changes: 12 additions & 1 deletion plugins/outputs/nats/nats.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ type NATS struct {
Password string
// NATS subject to publish metrics to
Subject string
// OutputPrecision string (parsed as a duration,
// only used for JSON output)
OutputPrecision string

// Path to CA file
SSLCA string `toml:"ssl_ca"`
Expand All @@ -41,6 +44,14 @@ var sampleConfig = `
# password = ""
## NATS subject for producer messages
subject = "telegraf"
## The output_precision parameter can be used to specify the units that should
## be used when creating timestamps and is only used when the data_format is
## set to "json"; in that case valid values are "1ns", "1us" (or "1µs"), "1ms",
## or "1s"; for the other supported data_format types, the precision will depend
## on the data_format (seconds for "graphite" data, nanoseconds for "influx"
## data); if unspecified, then the timestamps output with "json" data
## will be in seconds
output_precision = ""

## Optional SSL Config
# ssl_ca = "/etc/telegraf/ca.pem"
Expand Down Expand Up @@ -115,7 +126,7 @@ func (n *NATS) Write(metrics []telegraf.Metric) error {
}

for _, metric := range metrics {
buf, err := n.serializer.Serialize(metric)
buf, err := n.serializer.Serialize(metric, n.OutputPrecision)
if err != nil {
return err
}
Expand Down
18 changes: 15 additions & 3 deletions plugins/outputs/nsq/nsq.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ import (
)

type NSQ struct {
Server string
Topic string
Server string
Topic string
// OutputPrecision string (parsed as a duration,
// only used for JSON output)
OutputPrecision string

producer *nsq.Producer

serializer serializers.Serializer
Expand All @@ -23,6 +27,14 @@ var sampleConfig = `
server = "localhost:4150"
## NSQ topic for producer messages
topic = "telegraf"
## The output_precision parameter can be used to specify the units that should
## be used when creating timestamps and is only used when the data_format is
## set to "json"; in that case valid values are "1ns", "1us" (or "1µs"), "1ms",
## or "1s"; for the other supported data_format types, the precision will depend
## on the data_format (seconds for "graphite" data, nanoseconds for "influx"
## data); if unspecified, then the timestamps output with "json" data
## will be in seconds
output_precision = ""

## Data format to output.
## Each data format has it's own unique set of configuration options, read
Expand Down Expand Up @@ -66,7 +78,7 @@ func (n *NSQ) Write(metrics []telegraf.Metric) error {
}

for _, metric := range metrics {
buf, err := n.serializer.Serialize(metric)
buf, err := n.serializer.Serialize(metric, n.OutputPrecision)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/serializers/graphite/graphite.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type GraphiteSerializer struct {
Template string
}

func (s *GraphiteSerializer) Serialize(metric telegraf.Metric) ([]byte, error) {
func (s *GraphiteSerializer) Serialize(metric telegraf.Metric, output_precision ...string) ([]byte, error) {
out := []byte{}

// Convert UnixNano to Unix timestamps
Expand Down
2 changes: 1 addition & 1 deletion plugins/serializers/influx/influx.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ import (
type InfluxSerializer struct {
}

func (s *InfluxSerializer) Serialize(m telegraf.Metric) ([]byte, error) {
func (s *InfluxSerializer) Serialize(m telegraf.Metric, output_precision ...string) ([]byte, error) {
return m.Serialize(), nil
}
24 changes: 22 additions & 2 deletions plugins/serializers/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,39 @@ package json

import (
ejson "encoding/json"
"time"

"github.com/influxdata/telegraf"
)

type JsonSerializer struct {
}

func (s *JsonSerializer) Serialize(metric telegraf.Metric) ([]byte, error) {
func (s *JsonSerializer) Serialize(metric telegraf.Metric, output_precision ...string) ([]byte, error) {
// if no duration is specified, or if the output_precision value passed
// in represents a duration that is not greater than zero, then default
// to an output resolution for our timestamp values of 1 second (timestamps
// will be returned to the nearest second)
default_val := "1s"
var output_resolution time.Duration
if len(output_precision) > 0 && len(output_precision[0]) > 0 {
parsed_val, err := time.ParseDuration(output_precision[0])
if err != nil {
return nil, err
}
if parsed_val > 0.0 {
output_resolution = parsed_val
} else {
output_resolution, _ = time.ParseDuration(default_val)
}
} else {
output_resolution, _ = time.ParseDuration(default_val)
}
m := make(map[string]interface{})
m["tags"] = metric.Tags()
m["fields"] = metric.Fields()
m["name"] = metric.Name()
m["timestamp"] = metric.UnixNano() / 1000000000
m["timestamp"] = metric.UnixNano() / output_resolution.Nanoseconds()
serialized, err := ejson.Marshal(m)
if err != nil {
return []byte{}, err
Expand Down
2 changes: 1 addition & 1 deletion plugins/serializers/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Serializer interface {
// Serialize takes a single telegraf metric and turns it into a byte buffer.
// separate metrics should be separated by a newline, and there should be
// a newline at the end of the buffer.
Serialize(metric telegraf.Metric) ([]byte, error)
Serialize(metric telegraf.Metric, output_precision ...string) ([]byte, error)
}

// Config is a struct that covers the data types needed for all serializer types,
Expand Down