github.com/influxdata/telegraf@v1.30.3/docs/PROCESSORS.md (about) 1 # Processor Plugins 2 3 This section is for developers who want to create a new processor plugin. 4 5 ## Processor Plugin Guidelines 6 7 * A processor must conform to the [telegraf.Processor][] interface. 8 * Processors should call `processors.Add` in their `init` function to register 9 themselves. See below for a quick example. 10 * To be available within Telegraf itself, plugins must register themselves 11 using a file in `github.com/influxdata/telegraf/plugins/processors/all` 12 named according to the plugin name. Make sure you also add build-tags to 13 conditionally build the plugin. 14 * Each plugin requires a file called `sample.conf` containing the sample 15 configuration for the plugin in TOML format. 16 Please consult the [Sample Config][] page for the latest style guidelines. 17 * Each plugin `README.md` file should include the `sample.conf` file in a 18 section describing the configuration by specifying a `toml` section in the 19 form `toml @sample.conf`. The specified file(s) are then injected 20 automatically into the Readme. 21 * Follow the recommended [Code Style][]. 22 23 [Sample Config]: /docs/developers/SAMPLE_CONFIG.md 24 [Code Style]: /docs/developers/CODE_STYLE.md 25 [telegraf.Processor]: https://godoc.org/github.com/influxdata/telegraf#Processor 26 27 ## Streaming Processors 28 29 Streaming processors are a new processor type available to you. They are 30 particularly useful to implement processor types that use background processes 31 or goroutines to process multiple metrics at the same time. Some examples of 32 this are the execd processor, which pipes metrics out to an external process 33 over stdin and reads them back over stdout, and the reverse_dns processor, which 34 does reverse dns lookups on IP addresses in fields. While both of these come 35 with a speed cost, it would be significantly worse if you had to process one 36 metric completely from start to finish before handling the next metric, and thus 37 they benefit significantly from a streaming-pipe approach. 38 39 Some differences from classic Processors: 40 41 * Streaming processors must conform to the [telegraf.StreamingProcessor][] interface. 42 * Processors should call `processors.AddStreaming` in their `init` function to register 43 themselves. See below for a quick example. 44 45 [telegraf.StreamingProcessor]: https://godoc.org/github.com/influxdata/telegraf#StreamingProcessor 46 47 ## Processor Plugin Example 48 49 ### Registration 50 51 Registration of the plugin on `plugins/processors/all/printer.go`: 52 53 ```go 54 //go:build !custom || processors || processors.printer 55 56 package all 57 58 import _ "github.com/influxdata/telegraf/plugins/processors/printer" // register plugin 59 ``` 60 61 The _build-tags_ in the first line allow to selectively include/exclude your 62 plugin when customizing Telegraf. 63 64 ### Plugin 65 66 Content of your plugin file e.g. `printer.go` 67 68 ```go 69 //go:generate ../../../tools/readme_config_includer/generator 70 package printer 71 72 import ( 73 _ "embed" 74 "fmt" 75 76 "github.com/influxdata/telegraf" 77 "github.com/influxdata/telegraf/plugins/processors" 78 ) 79 80 //go:embed sample.conf 81 var sampleConfig string 82 83 type Printer struct { 84 Log telegraf.Logger `toml:"-"` 85 } 86 87 func (*Printer) SampleConfig() string { 88 return sampleConfig 89 } 90 91 // Init is for setup, and validating config. 92 func (p *Printer) Init() error { 93 return nil 94 } 95 96 func (p *Printer) Apply(in ...telegraf.Metric) []telegraf.Metric { 97 for _, metric := range in { 98 fmt.Println(metric.String()) 99 } 100 return in 101 } 102 103 func init() { 104 processors.Add("printer", func() telegraf.Processor { 105 return &Printer{} 106 }) 107 } 108 ``` 109 110 ## Streaming Processor Example 111 112 ```go 113 //go:generate ../../../tools/readme_config_includer/generator 114 package printer 115 116 import ( 117 _ "embed" 118 "fmt" 119 120 "github.com/influxdata/telegraf" 121 "github.com/influxdata/telegraf/plugins/processors" 122 ) 123 124 //go:embed sample.conf 125 var sampleConfig string 126 127 type Printer struct { 128 Log telegraf.Logger `toml:"-"` 129 } 130 131 func (*Printer) SampleConfig() string { 132 return sampleConfig 133 } 134 135 // Init is for setup, and validating config. 136 func (p *Printer) Init() error { 137 return nil 138 } 139 140 // Start is called once when the plugin starts; it is only called once per 141 // plugin instance, and never in parallel. 142 // Start should return once it is ready to receive metrics. 143 // The passed in accumulator is the same as the one passed to Add(), so you 144 // can choose to save it in the plugin, or use the one received from Add(). 145 func (p *Printer) Start(acc telegraf.Accumulator) error { 146 } 147 148 // Add is called for each metric to be processed. The Add() function does not 149 // need to wait for the metric to be processed before returning, and it may 150 // be acceptable to let background goroutine(s) handle the processing if you 151 // have slow processing you need to do in parallel. 152 // Keep in mind Add() should not spawn unbounded goroutines, so you may need 153 // to use a semaphore or pool of workers (eg: reverse_dns plugin does this). 154 // Metrics you don't want to pass downstream should have metric.Drop() called, 155 // rather than simply omitting the acc.AddMetric() call 156 func (p *Printer) Add(metric telegraf.Metric, acc telegraf.Accumulator) error { 157 // print! 158 fmt.Println(metric.String()) 159 // pass the metric downstream, or metric.Drop() it. 160 // Metric will be dropped if this function returns an error. 161 acc.AddMetric(metric) 162 163 return nil 164 } 165 166 // Stop gives you an opportunity to gracefully shut down the processor. 167 // Once Stop() is called, Add() will not be called any more. If you are using 168 // goroutines, you should wait for any in-progress metrics to be processed 169 // before returning from Stop(). 170 // When stop returns, you should no longer be writing metrics to the 171 // accumulator. 172 func (p *Printer) Stop() error { 173 } 174 175 func init() { 176 processors.AddStreaming("printer", func() telegraf.StreamingProcessor { 177 return &Printer{} 178 }) 179 } 180 ```