2022-05-25 22:48:59 +08:00
|
|
|
//go:generate ../../../tools/readme_config_includer/generator
|
2015-11-06 17:27:17 +08:00
|
|
|
package amon
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
2022-05-25 22:48:59 +08:00
|
|
|
_ "embed"
|
2015-11-06 17:27:17 +08:00
|
|
|
"encoding/json"
|
2024-02-09 01:32:30 +08:00
|
|
|
"errors"
|
2015-11-06 17:27:17 +08:00
|
|
|
"fmt"
|
|
|
|
|
"net/http"
|
|
|
|
|
"strings"
|
2021-04-10 01:15:04 +08:00
|
|
|
"time"
|
2015-11-06 17:27:17 +08:00
|
|
|
|
2016-01-28 07:15:14 +08:00
|
|
|
"github.com/influxdata/telegraf"
|
2021-04-10 01:15:04 +08:00
|
|
|
"github.com/influxdata/telegraf/config"
|
2016-01-21 02:57:35 +08:00
|
|
|
"github.com/influxdata/telegraf/plugins/outputs"
|
2015-11-06 17:27:17 +08:00
|
|
|
)
|
|
|
|
|
|
2022-05-25 22:48:59 +08:00
|
|
|
//go:embed sample.conf
|
|
|
|
|
var sampleConfig string
|
|
|
|
|
|
2015-11-06 17:27:17 +08:00
|
|
|
type Amon struct {
|
2021-04-10 01:15:04 +08:00
|
|
|
ServerKey string `toml:"server_key"`
|
|
|
|
|
AmonInstance string `toml:"amon_instance"`
|
|
|
|
|
Timeout config.Duration `toml:"timeout"`
|
|
|
|
|
Log telegraf.Logger `toml:"-"`
|
2015-11-06 17:27:17 +08:00
|
|
|
|
|
|
|
|
client *http.Client
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type TimeSeries struct {
|
|
|
|
|
Series []*Metric `json:"series"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Metric struct {
|
|
|
|
|
Metric string `json:"metric"`
|
2016-01-28 07:15:14 +08:00
|
|
|
Points [1]Point `json:"metrics"`
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Point [2]float64
|
|
|
|
|
|
2022-05-25 22:48:59 +08:00
|
|
|
func (*Amon) SampleConfig() string {
|
|
|
|
|
return sampleConfig
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-06 17:27:17 +08:00
|
|
|
func (a *Amon) Connect() error {
|
|
|
|
|
if a.ServerKey == "" || a.AmonInstance == "" {
|
2024-02-09 01:32:30 +08:00
|
|
|
return errors.New("serverkey and amon_instance are required fields for amon output")
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
|
|
|
|
a.client = &http.Client{
|
2017-09-09 06:35:20 +08:00
|
|
|
Transport: &http.Transport{
|
|
|
|
|
Proxy: http.ProxyFromEnvironment,
|
|
|
|
|
},
|
2021-04-10 01:15:04 +08:00
|
|
|
Timeout: time.Duration(a.Timeout),
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-28 07:15:14 +08:00
|
|
|
func (a *Amon) Write(metrics []telegraf.Metric) error {
|
|
|
|
|
if len(metrics) == 0 {
|
2015-11-06 17:27:17 +08:00
|
|
|
return nil
|
|
|
|
|
}
|
2015-12-20 05:08:31 +08:00
|
|
|
|
2024-10-18 19:06:42 +08:00
|
|
|
metricCounter := 0
|
|
|
|
|
tempSeries := make([]*Metric, 0, len(metrics))
|
2016-01-28 07:15:14 +08:00
|
|
|
for _, m := range metrics {
|
2022-05-11 23:53:34 +08:00
|
|
|
mname := strings.ReplaceAll(m.Name(), "_", ".")
|
2016-01-28 07:15:14 +08:00
|
|
|
if amonPts, err := buildMetrics(m); err == nil {
|
2015-12-20 05:08:31 +08:00
|
|
|
for fieldName, amonPt := range amonPts {
|
|
|
|
|
metric := &Metric{
|
2022-05-11 23:53:34 +08:00
|
|
|
Metric: mname + "_" + strings.ReplaceAll(fieldName, "_", "."),
|
2015-12-20 05:08:31 +08:00
|
|
|
}
|
|
|
|
|
metric.Points[0] = amonPt
|
2015-12-20 05:19:43 +08:00
|
|
|
tempSeries = append(tempSeries, metric)
|
|
|
|
|
metricCounter++
|
2015-12-20 05:08:31 +08:00
|
|
|
}
|
2015-11-06 17:27:17 +08:00
|
|
|
} else {
|
2021-02-09 00:18:40 +08:00
|
|
|
a.Log.Infof("Unable to build Metric for %s, skipping", m.Name())
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
|
|
|
|
}
|
2015-12-20 05:08:31 +08:00
|
|
|
|
2024-10-18 19:06:42 +08:00
|
|
|
ts := TimeSeries{}
|
2015-12-20 05:19:43 +08:00
|
|
|
ts.Series = make([]*Metric, metricCounter)
|
2015-11-06 17:27:17 +08:00
|
|
|
copy(ts.Series, tempSeries[0:])
|
|
|
|
|
tsBytes, err := json.Marshal(ts)
|
|
|
|
|
if err != nil {
|
2023-02-22 20:38:16 +08:00
|
|
|
return fmt.Errorf("unable to marshal TimeSeries: %w", err)
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
2021-03-02 05:04:35 +08:00
|
|
|
req, err := http.NewRequest("POST", a.authenticatedURL(), bytes.NewBuffer(tsBytes))
|
2015-11-06 17:27:17 +08:00
|
|
|
if err != nil {
|
2023-02-22 20:38:16 +08:00
|
|
|
return fmt.Errorf("unable to create http.Request: %w", err)
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
|
|
|
|
req.Header.Add("Content-Type", "application/json")
|
|
|
|
|
|
|
|
|
|
resp, err := a.client.Do(req)
|
|
|
|
|
if err != nil {
|
2023-02-22 20:38:16 +08:00
|
|
|
return fmt.Errorf("error POSTing metrics: %w", err)
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
|
|
if resp.StatusCode < 200 || resp.StatusCode > 209 {
|
2021-02-09 00:18:40 +08:00
|
|
|
return fmt.Errorf("received bad status code, %d", resp.StatusCode)
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-02 05:04:35 +08:00
|
|
|
func (a *Amon) authenticatedURL() string {
|
2015-11-06 17:27:17 +08:00
|
|
|
return fmt.Sprintf("%s/api/system/%s", a.AmonInstance, a.ServerKey)
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-28 07:15:14 +08:00
|
|
|
func buildMetrics(m telegraf.Metric) (map[string]Point, error) {
|
|
|
|
|
ms := make(map[string]Point)
|
|
|
|
|
for k, v := range m.Fields() {
|
2015-12-20 05:08:31 +08:00
|
|
|
var p Point
|
|
|
|
|
if err := p.setValue(v); err != nil {
|
2023-02-22 20:38:16 +08:00
|
|
|
return ms, fmt.Errorf("unable to extract value from Fields: %w", err)
|
2015-12-20 05:08:31 +08:00
|
|
|
}
|
2016-01-28 07:15:14 +08:00
|
|
|
p[0] = float64(m.Time().Unix())
|
|
|
|
|
ms[k] = p
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
2016-01-28 07:15:14 +08:00
|
|
|
return ms, nil
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Point) setValue(v interface{}) error {
|
|
|
|
|
switch d := v.(type) {
|
|
|
|
|
case int:
|
2021-03-24 23:27:46 +08:00
|
|
|
p[1] = float64(d)
|
2015-11-06 17:27:17 +08:00
|
|
|
case int32:
|
2021-03-24 23:27:46 +08:00
|
|
|
p[1] = float64(d)
|
2015-11-06 17:27:17 +08:00
|
|
|
case int64:
|
2021-03-24 23:27:46 +08:00
|
|
|
p[1] = float64(d)
|
2015-11-06 17:27:17 +08:00
|
|
|
case float32:
|
|
|
|
|
p[1] = float64(d)
|
|
|
|
|
case float64:
|
2021-11-19 00:26:24 +08:00
|
|
|
p[1] = d
|
2015-11-06 17:27:17 +08:00
|
|
|
default:
|
2024-02-09 01:32:30 +08:00
|
|
|
return errors.New("undeterminable type")
|
2015-11-06 17:27:17 +08:00
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-16 03:58:39 +08:00
|
|
|
func (*Amon) Close() error {
|
2015-11-06 17:27:17 +08:00
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func init() {
|
2016-01-28 05:21:36 +08:00
|
|
|
outputs.Add("amon", func() telegraf.Output {
|
2015-11-06 17:27:17 +08:00
|
|
|
return &Amon{}
|
|
|
|
|
})
|
|
|
|
|
}
|