Add SignalFx output plugin.
Add back 'opencontainers' to 'Godeps' to fix CircleCI error.
This commit is contained in:
@@ -19,4 +19,5 @@ import (
|
||||
_ "github.com/influxdata/telegraf/plugins/outputs/opentsdb"
|
||||
_ "github.com/influxdata/telegraf/plugins/outputs/prometheus_client"
|
||||
_ "github.com/influxdata/telegraf/plugins/outputs/riemann"
|
||||
_ "github.com/influxdata/telegraf/plugins/outputs/signalfx"
|
||||
)
|
||||
|
||||
31
plugins/outputs/signalfx/README.md
Normal file
31
plugins/outputs/signalfx/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# SignalFx Output Plugin
|
||||
|
||||
This plugin writes to [SignalFx](https://signalfx.com/) via HTTP.<br/>
|
||||
For each Telegraf metric a SignalFx gauge datapoint is written per field.<br/>
|
||||
The datapoint's metric name is a concatention of the Telegraf metric name and the field name.<br/>
|
||||
Tags are written as datapoint dimensions.
|
||||
|
||||
### Configuration:
|
||||
|
||||
```toml
|
||||
# Send Telegraf metrics to SignalFx
|
||||
[[outputs.signalfx]]
|
||||
## Your organization's SignalFx API access token.
|
||||
auth_token = "SuperSecretToken"
|
||||
|
||||
## Optional HTTP User Agent value; Overrides the default.
|
||||
# user_agent = "Telegraf collector"
|
||||
|
||||
## Optional SignalFX API endpoint value; Overrides the default.
|
||||
# endpoint = "https://ingest.signalfx.com/v2/datapoint"
|
||||
```
|
||||
|
||||
### Required parameters:
|
||||
|
||||
* `auth_token`: Your organization's SignalFx API access token.
|
||||
|
||||
|
||||
### Optional parameters:
|
||||
|
||||
* `user_agent`: HTTP User Agent.
|
||||
* `endpoint`: SignalFX API endpoint.
|
||||
92
plugins/outputs/signalfx/signalfx.go
Normal file
92
plugins/outputs/signalfx/signalfx.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package signalfx
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/outputs"
|
||||
|
||||
"github.com/signalfx/golib/datapoint"
|
||||
"github.com/signalfx/golib/sfxclient"
|
||||
)
|
||||
|
||||
type SignalFx struct {
|
||||
AuthToken string `toml:"auth_token"`
|
||||
UserAgent string `toml:"user_agent"`
|
||||
Endpoint string `toml:"endpoint"`
|
||||
|
||||
sink *sfxclient.HTTPDatapointSink
|
||||
}
|
||||
|
||||
var sampleConfig = `
|
||||
## Your organization's SignalFx API access token.
|
||||
auth_token = "SuperSecretToken"
|
||||
|
||||
## Optional HTTP User Agent value; Overrides the default.
|
||||
# user_agent = "Telegraf collector"
|
||||
|
||||
## Optional SignalFX API endpoint value; Overrides the default.
|
||||
# endpoint = "https://ingest.signalfx.com/v2/datapoint"
|
||||
`
|
||||
|
||||
func (s *SignalFx) Description() string {
|
||||
return "Send Telegraf metrics to SignalFx"
|
||||
}
|
||||
|
||||
func (s *SignalFx) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (s *SignalFx) Connect() error {
|
||||
s.sink = sfxclient.NewHTTPDatapointSink()
|
||||
s.sink.AuthToken = s.AuthToken
|
||||
if len(s.UserAgent) > 0 {
|
||||
s.sink.UserAgent = s.UserAgent
|
||||
}
|
||||
if len(s.Endpoint) > 0 {
|
||||
s.sink.Endpoint = s.Endpoint
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SignalFx) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SignalFx) Write(metrics []telegraf.Metric) error {
|
||||
var datapoints []*datapoint.Datapoint
|
||||
for _, metric := range metrics {
|
||||
// One SignalFx metric per field.
|
||||
for fieldName, fieldValue := range metric.Fields() {
|
||||
var value datapoint.Value
|
||||
switch fieldValue.(type) {
|
||||
case float64:
|
||||
value = datapoint.NewFloatValue(fieldValue.(float64))
|
||||
case int64:
|
||||
value = datapoint.NewIntValue(fieldValue.(int64))
|
||||
default:
|
||||
log.Printf("Unhandled type %T for field %s\n", fieldValue, fieldName)
|
||||
continue
|
||||
}
|
||||
|
||||
metricName := metric.Name() + "." + fieldName
|
||||
datapoint := datapoint.New(metricName, metric.Tags(), value, datapoint.Gauge, metric.Time())
|
||||
datapoints = append(datapoints, datapoint)
|
||||
}
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
err := s.sink.AddDatapoints(ctx, datapoints)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
outputs.Add("signalfx", func() telegraf.Output { return &SignalFx{} })
|
||||
}
|
||||
32
plugins/outputs/signalfx/signalfx_test.go
Normal file
32
plugins/outputs/signalfx/signalfx_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package signalfx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/telegraf/testutil"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHTTPSignalFx(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
// https://developers.signalfx.com/docs/datapoint
|
||||
fmt.Fprintln(w, `"OK"`)
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
i := SignalFx{
|
||||
AuthToken: "Whatever",
|
||||
Endpoint: ts.URL,
|
||||
}
|
||||
|
||||
err := i.Connect()
|
||||
require.NoError(t, err)
|
||||
err = i.Write(testutil.MockMetrics())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
Reference in New Issue
Block a user