Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
245
plugins/serializers/csv/csv.go
Normal file
245
plugins/serializers/csv/csv.go
Normal file
|
@ -0,0 +1,245 @@
|
|||
package csv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/serializers"
|
||||
)
|
||||
|
||||
type Serializer struct {
|
||||
TimestampFormat string `toml:"csv_timestamp_format"`
|
||||
Separator string `toml:"csv_separator"`
|
||||
Header bool `toml:"csv_header"`
|
||||
Prefix bool `toml:"csv_column_prefix"`
|
||||
Columns []string `toml:"csv_columns"`
|
||||
|
||||
buffer bytes.Buffer
|
||||
writer *csv.Writer
|
||||
}
|
||||
|
||||
func (s *Serializer) Init() error {
|
||||
// Setting defaults
|
||||
if s.Separator == "" {
|
||||
s.Separator = ","
|
||||
}
|
||||
|
||||
// Check inputs
|
||||
if len(s.Separator) > 1 {
|
||||
return fmt.Errorf("invalid separator %q", s.Separator)
|
||||
}
|
||||
switch s.TimestampFormat {
|
||||
case "":
|
||||
s.TimestampFormat = "unix"
|
||||
case "unix", "unix_ms", "unix_us", "unix_ns":
|
||||
default:
|
||||
if time.Now().Format(s.TimestampFormat) == s.TimestampFormat {
|
||||
return fmt.Errorf("invalid timestamp format %q", s.TimestampFormat)
|
||||
}
|
||||
}
|
||||
|
||||
// Check columns if any
|
||||
for _, name := range s.Columns {
|
||||
switch {
|
||||
case name == "timestamp", name == "name",
|
||||
strings.HasPrefix(name, "tag."),
|
||||
strings.HasPrefix(name, "field."):
|
||||
default:
|
||||
return fmt.Errorf("invalid column reference %q", name)
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the writer
|
||||
s.writer = csv.NewWriter(&s.buffer)
|
||||
s.writer.Comma, _ = utf8.DecodeRuneInString(s.Separator)
|
||||
s.writer.UseCRLF = runtime.GOOS == "windows"
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Serializer) Serialize(metric telegraf.Metric) ([]byte, error) {
|
||||
return s.SerializeBatch([]telegraf.Metric{metric})
|
||||
}
|
||||
|
||||
func (s *Serializer) SerializeBatch(metrics []telegraf.Metric) ([]byte, error) {
|
||||
if len(metrics) < 1 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Clear the buffer
|
||||
s.buffer.Truncate(0)
|
||||
|
||||
// Write the header if the user wants us to
|
||||
if s.Header {
|
||||
if len(s.Columns) > 0 {
|
||||
if err := s.writeHeaderOrdered(); err != nil {
|
||||
return nil, fmt.Errorf("writing header failed: %w", err)
|
||||
}
|
||||
} else {
|
||||
if err := s.writeHeader(metrics[0]); err != nil {
|
||||
return nil, fmt.Errorf("writing header failed: %w", err)
|
||||
}
|
||||
}
|
||||
s.Header = false
|
||||
}
|
||||
|
||||
for _, m := range metrics {
|
||||
if len(s.Columns) > 0 {
|
||||
if err := s.writeDataOrdered(m); err != nil {
|
||||
return nil, fmt.Errorf("writing data failed: %w", err)
|
||||
}
|
||||
} else {
|
||||
if err := s.writeData(m); err != nil {
|
||||
return nil, fmt.Errorf("writing data failed: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finish up
|
||||
s.writer.Flush()
|
||||
return s.buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
func (s *Serializer) writeHeader(metric telegraf.Metric) error {
|
||||
columns := []string{
|
||||
"timestamp",
|
||||
"measurement",
|
||||
}
|
||||
for _, tag := range metric.TagList() {
|
||||
if s.Prefix {
|
||||
columns = append(columns, "tag_"+tag.Key)
|
||||
} else {
|
||||
columns = append(columns, tag.Key)
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the fields by name
|
||||
sort.Slice(metric.FieldList(), func(i, j int) bool {
|
||||
return metric.FieldList()[i].Key < metric.FieldList()[j].Key
|
||||
})
|
||||
for _, field := range metric.FieldList() {
|
||||
if s.Prefix {
|
||||
columns = append(columns, "field_"+field.Key)
|
||||
} else {
|
||||
columns = append(columns, field.Key)
|
||||
}
|
||||
}
|
||||
|
||||
return s.writer.Write(columns)
|
||||
}
|
||||
|
||||
func (s *Serializer) writeHeaderOrdered() error {
|
||||
columns := make([]string, 0, len(s.Columns))
|
||||
for _, name := range s.Columns {
|
||||
if s.Prefix {
|
||||
name = strings.ReplaceAll(name, ".", "_")
|
||||
} else {
|
||||
name = strings.TrimPrefix(name, "tag.")
|
||||
name = strings.TrimPrefix(name, "field.")
|
||||
}
|
||||
columns = append(columns, name)
|
||||
}
|
||||
|
||||
return s.writer.Write(columns)
|
||||
}
|
||||
|
||||
func (s *Serializer) writeData(metric telegraf.Metric) error {
|
||||
var timestamp string
|
||||
|
||||
// Format the time
|
||||
switch s.TimestampFormat {
|
||||
case "unix":
|
||||
timestamp = strconv.FormatInt(metric.Time().Unix(), 10)
|
||||
case "unix_ms":
|
||||
timestamp = strconv.FormatInt(metric.Time().UnixNano()/1_000_000, 10)
|
||||
case "unix_us":
|
||||
timestamp = strconv.FormatInt(metric.Time().UnixNano()/1_000, 10)
|
||||
case "unix_ns":
|
||||
timestamp = strconv.FormatInt(metric.Time().UnixNano(), 10)
|
||||
default:
|
||||
timestamp = metric.Time().UTC().Format(s.TimestampFormat)
|
||||
}
|
||||
|
||||
columns := []string{
|
||||
timestamp,
|
||||
metric.Name(),
|
||||
}
|
||||
for _, tag := range metric.TagList() {
|
||||
columns = append(columns, tag.Value)
|
||||
}
|
||||
|
||||
// Sort the fields by name
|
||||
sort.Slice(metric.FieldList(), func(i, j int) bool {
|
||||
return metric.FieldList()[i].Key < metric.FieldList()[j].Key
|
||||
})
|
||||
for _, field := range metric.FieldList() {
|
||||
v, err := internal.ToString(field.Value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("converting field %q to string failed: %w", field.Key, err)
|
||||
}
|
||||
columns = append(columns, v)
|
||||
}
|
||||
|
||||
return s.writer.Write(columns)
|
||||
}
|
||||
|
||||
func (s *Serializer) writeDataOrdered(metric telegraf.Metric) error {
|
||||
var timestamp string
|
||||
|
||||
// Format the time
|
||||
switch s.TimestampFormat {
|
||||
case "unix":
|
||||
timestamp = strconv.FormatInt(metric.Time().Unix(), 10)
|
||||
case "unix_ms":
|
||||
timestamp = strconv.FormatInt(metric.Time().UnixNano()/1_000_000, 10)
|
||||
case "unix_us":
|
||||
timestamp = strconv.FormatInt(metric.Time().UnixNano()/1_000, 10)
|
||||
case "unix_ns":
|
||||
timestamp = strconv.FormatInt(metric.Time().UnixNano(), 10)
|
||||
default:
|
||||
timestamp = metric.Time().UTC().Format(s.TimestampFormat)
|
||||
}
|
||||
|
||||
columns := make([]string, 0, len(s.Columns))
|
||||
for _, name := range s.Columns {
|
||||
switch {
|
||||
case name == "timestamp":
|
||||
columns = append(columns, timestamp)
|
||||
case name == "name":
|
||||
columns = append(columns, metric.Name())
|
||||
case strings.HasPrefix(name, "tag."):
|
||||
v, _ := metric.GetTag(strings.TrimPrefix(name, "tag."))
|
||||
columns = append(columns, v)
|
||||
case strings.HasPrefix(name, "field."):
|
||||
var v string
|
||||
field := strings.TrimPrefix(name, "field.")
|
||||
if raw, ok := metric.GetField(field); ok {
|
||||
var err error
|
||||
v, err = internal.ToString(raw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("converting field %q to string failed: %w", field, err)
|
||||
}
|
||||
}
|
||||
columns = append(columns, v)
|
||||
}
|
||||
}
|
||||
|
||||
return s.writer.Write(columns)
|
||||
}
|
||||
|
||||
func init() {
|
||||
serializers.Add("csv",
|
||||
func() telegraf.Serializer {
|
||||
return &Serializer{}
|
||||
},
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue