-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Expand file tree
/
Copy pathexample.go
More file actions
139 lines (114 loc) · 3.8 KB
/
example.go
File metadata and controls
139 lines (114 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//go:generate ../../../tools/readme_config_includer/generator
package example
import (
"crypto/rand"
_ "embed"
"errors"
"fmt"
"math"
"math/big"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/inputs"
)
//go:embed sample.conf
var sampleConfig string
// Example struct should be named the same as the Plugin
type Example struct {
// Example for a mandatory option to set a tag
DeviceName string `toml:"device_name"`
// Config options are converted to the correct type automatically
NumberFields int64 `toml:"number_fields"`
// We can also use booleans and have diverging names between user-configuration options and struct members
EnableRandomVariable bool `toml:"enable_random"`
// Example of passing a duration option allowing the format of e.g. "100ms", "5m" or "1h"
Timeout config.Duration `toml:"timeout"`
// Example of passing a password/token/username or other sensitive data with the secret-store
UserName config.Secret `toml:"username"`
Password config.Secret `toml:"password"`
// Telegraf logging facility
// The exact name is important to allow automatic initialization by telegraf.
Log telegraf.Logger `toml:"-"`
// This is a non-exported internal state.
count int64
}
func (*Example) SampleConfig() string {
return sampleConfig
}
// Init can be implemented to do one-time processing stuff like initializing variables
func (m *Example) Init() error {
// Check your options according to your requirements
if m.DeviceName == "" {
return errors.New("device name cannot be empty")
}
// Set your defaults.
// Please note: In golang all fields are initialized to their nil value, so you should not
// set these fields if the nil value is what you want (e.g. for booleans).
if m.NumberFields < 1 {
m.Log.Debugf("Setting number of fields to default from invalid value %d", m.NumberFields)
m.NumberFields = 2
}
// Check using the secret-store
if m.UserName.Empty() {
// For example, use a default value
m.Log.Debug("using default username")
}
// Retrieve credentials using the secret-store
password, err := m.Password.Get()
if err != nil {
return fmt.Errorf("getting password failed: %w", err)
}
defer password.Destroy()
// Initialize your internal states
m.count = 1
return nil
}
// Gather defines what data the plugin will gather.
func (m *Example) Gather(acc telegraf.Accumulator) error {
// Imagine some completely arbitrary error occurring here
if m.NumberFields > 10 {
return errors.New("too many fields")
}
// For illustration, we gather three metrics in one go
for run := 0; run < 3; run++ {
// Imagine an error occurs here, but you want to keep the other
// metrics, then you cannot simply return, as this would drop
// all later metrics. Simply accumulate errors in this case
// and ignore the metric.
if m.EnableRandomVariable && m.DeviceName == "flappy" && run > 1 {
acc.AddError(errors.New("too many runs for random values"))
continue
}
// Construct the fields
fields := map[string]interface{}{"count": m.count}
for i := int64(1); i < m.NumberFields; i++ {
name := fmt.Sprintf("field%d", i)
var err error
value := big.NewInt(0)
if m.EnableRandomVariable {
value, err = rand.Int(rand.Reader, big.NewInt(math.MaxUint32))
if err != nil {
acc.AddError(err)
continue
}
}
fields[name] = float64(value.Int64())
}
// Construct the tags
tags := map[string]string{"device": m.DeviceName}
// Add the metric with the current timestamp
acc.AddFields("example", fields, tags)
m.count++
}
return nil
}
// Register the plugin
func init() {
inputs.Add("example", func() telegraf.Input {
return &Example{
// Set the default timeout here to distinguish it from the user setting it to zero
Timeout: config.Duration(100 * time.Millisecond),
}
})
}