From 1c0d3a0eb9bb2c4bbb274bb463ae0b41ed5a2cc4 Mon Sep 17 00:00:00 2001 From: Kristoffer Berdal Date: Sun, 2 Jun 2019 02:11:47 +0200 Subject: [PATCH] Add file rotation based on file age to file output plugin (#5547) --- plugins/outputs/file/README.md | 3 +++ plugins/outputs/file/file.go | 43 +++++++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/plugins/outputs/file/README.md b/plugins/outputs/file/README.md index de577eacf..a6c4ac53f 100644 --- a/plugins/outputs/file/README.md +++ b/plugins/outputs/file/README.md @@ -8,6 +8,9 @@ This plugin writes telegraf metrics to files ## Files to write to, "stdout" is a specially handled file. files = ["stdout", "/tmp/metrics.out"] + ## If this is defined, files will be rotated by the time.Duration specified + # rotate_max_age = "1m" + ## Data format to output. ## Each data format has its own unique set of configuration options, read ## more about them here: diff --git a/plugins/outputs/file/file.go b/plugins/outputs/file/file.go index 0ef61df51..89380ae7e 100644 --- a/plugins/outputs/file/file.go +++ b/plugins/outputs/file/file.go @@ -4,16 +4,19 @@ import ( "fmt" "io" "os" + "time" "github.com/influxdata/telegraf" + "github.com/influxdata/telegraf/internal/rotate" "github.com/influxdata/telegraf/plugins/outputs" "github.com/influxdata/telegraf/plugins/serializers" ) type File struct { - Files []string + Files []string + RotateMaxAge string - writers []io.Writer + writer io.Writer closers []io.Closer serializer serializers.Serializer @@ -23,6 +26,9 @@ var sampleConfig = ` ## Files to write to, "stdout" is a specially handled file. files = ["stdout", "/tmp/metrics.out"] + ## If this is defined, files will be rotated by the time.Duration specified + # rotate_max_age = "1m" + ## Data format to output. ## Each data format has its own unique set of configuration options, read ## more about them here: @@ -35,23 +41,38 @@ func (f *File) SetSerializer(serializer serializers.Serializer) { } func (f *File) Connect() error { + writers := []io.Writer{} + if len(f.Files) == 0 { f.Files = []string{"stdout"} } for _, file := range f.Files { if file == "stdout" { - f.writers = append(f.writers, os.Stdout) + writers = append(writers, os.Stdout) } else { - of, err := os.OpenFile(file, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModeAppend|0644) + var of io.WriteCloser + var err error + if f.RotateMaxAge != "" { + maxAge, err := time.ParseDuration(f.RotateMaxAge) + if err != nil { + return err + } + + // Only rotate by file age for now, keep no archives. + of, err = rotate.NewFileWriter(file, maxAge, 0, -1) + } else { + // Just open a normal file + of, err = rotate.NewFileWriter(file, 0, 0, -1) + } if err != nil { return err } - - f.writers = append(f.writers, of) + writers = append(writers, of) f.closers = append(f.closers, of) } } + f.writer = io.MultiWriter(writers...) return nil } @@ -76,19 +97,19 @@ func (f *File) Description() string { func (f *File) Write(metrics []telegraf.Metric) error { var writeErr error = nil + for _, metric := range metrics { b, err := f.serializer.Serialize(metric) if err != nil { return fmt.Errorf("failed to serialize message: %s", err) } - for _, writer := range f.writers { - _, err = writer.Write(b) - if err != nil && writer != os.Stdout { - writeErr = fmt.Errorf("E! failed to write message: %s, %s", b, err) - } + _, err = f.writer.Write(b) + if err != nil { + writeErr = fmt.Errorf("E! failed to write message: %s, %s", b, err) } } + return writeErr }