Add filepath processor plugin (#7418)
This commit is contained in:
150
plugins/processors/filepath/filepath.go
Normal file
150
plugins/processors/filepath/filepath.go
Normal file
@@ -0,0 +1,150 @@
|
||||
package filepath
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/processors"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
BaseName []BaseOpts `toml:"basename"`
|
||||
DirName []BaseOpts `toml:"dirname"`
|
||||
Stem []BaseOpts
|
||||
Clean []BaseOpts
|
||||
Rel []RelOpts
|
||||
ToSlash []BaseOpts `toml:"toslash"`
|
||||
}
|
||||
|
||||
type ProcessorFunc func(s string) string
|
||||
|
||||
// BaseOpts contains options applicable to every function
|
||||
type BaseOpts struct {
|
||||
Field string
|
||||
Tag string
|
||||
Dest string
|
||||
}
|
||||
|
||||
type RelOpts struct {
|
||||
BaseOpts
|
||||
BasePath string
|
||||
}
|
||||
|
||||
const sampleConfig = `
|
||||
## Treat the tag value as a path and convert it to its last element, storing the result in a new tag
|
||||
# [[processors.filepath.basename]]
|
||||
# tag = "path"
|
||||
# dest = "basepath"
|
||||
|
||||
## Treat the field value as a path and keep all but the last element of path, typically the path's directory
|
||||
# [[processors.filepath.dirname]]
|
||||
# field = "path"
|
||||
|
||||
## Treat the tag value as a path, converting it to its the last element without its suffix
|
||||
# [[processors.filepath.stem]]
|
||||
# tag = "path"
|
||||
|
||||
## Treat the tag value as a path, converting it to the shortest path name equivalent
|
||||
## to path by purely lexical processing
|
||||
# [[processors.filepath.clean]]
|
||||
# tag = "path"
|
||||
|
||||
## Treat the tag value as a path, converting it to a relative path that is lexically
|
||||
## equivalent to the source path when joined to 'base_path'
|
||||
# [[processors.filepath.rel]]
|
||||
# tag = "path"
|
||||
# base_path = "/var/log"
|
||||
|
||||
## Treat the tag value as a path, replacing each separator character in path with a '/' character. Has only
|
||||
## effect on Windows
|
||||
# [[processors.filepath.toslash]]
|
||||
# tag = "path"
|
||||
`
|
||||
|
||||
func (o *Options) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (o *Options) Description() string {
|
||||
return "Performs file path manipulations on tags and fields"
|
||||
}
|
||||
|
||||
// applyFunc applies the specified function to the metric
|
||||
func (o *Options) applyFunc(bo BaseOpts, fn ProcessorFunc, metric telegraf.Metric) {
|
||||
if bo.Tag != "" {
|
||||
if v, ok := metric.GetTag(bo.Tag); ok {
|
||||
targetTag := bo.Tag
|
||||
|
||||
if bo.Dest != "" {
|
||||
targetTag = bo.Dest
|
||||
}
|
||||
metric.AddTag(targetTag, fn(v))
|
||||
}
|
||||
}
|
||||
|
||||
if bo.Field != "" {
|
||||
if v, ok := metric.GetField(bo.Field); ok {
|
||||
targetField := bo.Field
|
||||
|
||||
if bo.Dest != "" {
|
||||
targetField = bo.Dest
|
||||
}
|
||||
|
||||
// Only string fields are considered
|
||||
if v, ok := v.(string); ok {
|
||||
metric.AddField(targetField, fn(v))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func stemFilePath(path string) string {
|
||||
return strings.TrimSuffix(filepath.Base(path), filepath.Ext(path))
|
||||
}
|
||||
|
||||
// processMetric processes fields and tag values for a given metric applying the selected transformations
|
||||
func (o *Options) processMetric(metric telegraf.Metric) {
|
||||
// Stem
|
||||
for _, v := range o.Stem {
|
||||
o.applyFunc(v, stemFilePath, metric)
|
||||
}
|
||||
// Basename
|
||||
for _, v := range o.BaseName {
|
||||
o.applyFunc(v, filepath.Base, metric)
|
||||
}
|
||||
// Rel
|
||||
for _, v := range o.Rel {
|
||||
o.applyFunc(v.BaseOpts, func(s string) string {
|
||||
relPath, _ := filepath.Rel(v.BasePath, s)
|
||||
return relPath
|
||||
}, metric)
|
||||
}
|
||||
// Dirname
|
||||
for _, v := range o.DirName {
|
||||
o.applyFunc(v, filepath.Dir, metric)
|
||||
}
|
||||
// Clean
|
||||
for _, v := range o.Clean {
|
||||
o.applyFunc(v, filepath.Clean, metric)
|
||||
}
|
||||
// ToSlash
|
||||
for _, v := range o.ToSlash {
|
||||
o.applyFunc(v, filepath.ToSlash, metric)
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Options) Apply(in ...telegraf.Metric) []telegraf.Metric {
|
||||
for _, m := range in {
|
||||
o.processMetric(m)
|
||||
}
|
||||
|
||||
return in
|
||||
}
|
||||
|
||||
func init() {
|
||||
processors.Add("filepath", func() telegraf.Processor {
|
||||
return &Options{}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user