Dynatrace Plugin: Make conversion to counters possible / Changed large bulk handling (#8397)

This commit is contained in:
Thomas Schuetz 2021-03-02 21:55:38 +01:00 committed by GitHub
parent c17cc8cabb
commit 15d45ec0bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 15 deletions

View File

@ -35,6 +35,8 @@ You will also need to configure an API token for secure access. Find out how to
prefix = "telegraf." prefix = "telegraf."
## Flag for skipping the tls certificate check, just for testing purposes, should be false by default ## Flag for skipping the tls certificate check, just for testing purposes, should be false by default
insecure_skip_verify = false insecure_skip_verify = false
## If you want to convert values represented as gauges to counters, add the metric names here
additional_counters = [ ]
``` ```

View File

@ -19,7 +19,8 @@ import (
) )
const ( const (
oneAgentMetricsURL = "http://127.0.0.1:14499/metrics/ingest" oneAgentMetricsURL = "http://127.0.0.1:14499/metrics/ingest"
dtIngestApiLineLimit = 1000
) )
var ( var (
@ -30,13 +31,14 @@ var (
// Dynatrace Configuration for the Dynatrace output plugin // Dynatrace Configuration for the Dynatrace output plugin
type Dynatrace struct { type Dynatrace struct {
URL string `toml:"url"` URL string `toml:"url"`
APIToken string `toml:"api_token"` APIToken string `toml:"api_token"`
Prefix string `toml:"prefix"` Prefix string `toml:"prefix"`
Log telegraf.Logger `toml:"-"` Log telegraf.Logger `toml:"-"`
Timeout internal.Duration `toml:"timeout"` Timeout internal.Duration `toml:"timeout"`
State map[string]string AddCounterMetrics []string `toml:"additional_counters"`
SendCounter int State map[string]string
SendCounter int
tls.ClientConfig tls.ClientConfig
@ -73,6 +75,9 @@ const sampleConfig = `
## Connection timeout, defaults to "5s" if not set. ## Connection timeout, defaults to "5s" if not set.
timeout = "5s" timeout = "5s"
## If you want to convert values represented as gauges to counters, add the metric names here
additional_counters = [ ]
` `
// Connect Connects the Dynatrace output plugin to the Telegraf stream // Connect Connects the Dynatrace output plugin to the Telegraf stream
@ -130,6 +135,7 @@ func (d *Dynatrace) escape(v string) string {
func (d *Dynatrace) Write(metrics []telegraf.Metric) error { func (d *Dynatrace) Write(metrics []telegraf.Metric) error {
var buf bytes.Buffer var buf bytes.Buffer
metricCounter := 1
var tagb bytes.Buffer var tagb bytes.Buffer
if len(metrics) == 0 { if len(metrics) == 0 {
return nil return nil
@ -151,8 +157,9 @@ func (d *Dynatrace) Write(metrics []telegraf.Metric) error {
if err != nil { if err != nil {
continue continue
} }
fmt.Fprintf(&tagb, ",%s=%s", strings.ToLower(tagKey), d.escape(metric.Tags()[k])) if len(metric.Tags()[k]) > 0 {
fmt.Fprintf(&tagb, ",%s=%s", strings.ToLower(tagKey), d.escape(metric.Tags()[k]))
}
} }
} }
if len(metric.Fields()) > 0 { if len(metric.Fields()) > 0 {
@ -194,7 +201,15 @@ func (d *Dynatrace) Write(metrics []telegraf.Metric) error {
continue continue
} }
// write metric id,tags and value // write metric id,tags and value
switch metric.Type() {
metricType := metric.Type()
for _, i := range d.AddCounterMetrics {
if metric.Name()+"."+metricKey == i {
metricType = telegraf.Counter
}
}
switch metricType {
case telegraf.Counter: case telegraf.Counter:
var delta float64 var delta float64
@ -209,7 +224,7 @@ func (d *Dynatrace) Write(metrics []telegraf.Metric) error {
if err != nil { if err != nil {
d.Log.Debugf("Could not parse current value: %s", value) d.Log.Debugf("Could not parse current value: %s", value)
} }
if floatCurrentValue > floatLastValue { if floatCurrentValue >= floatLastValue {
delta = floatCurrentValue - floatLastValue delta = floatCurrentValue - floatLastValue
fmt.Fprintf(&buf, "%s%s count,delta=%f\n", metricID, tagb.String(), delta) fmt.Fprintf(&buf, "%s%s count,delta=%f\n", metricID, tagb.String(), delta)
} }
@ -219,6 +234,15 @@ func (d *Dynatrace) Write(metrics []telegraf.Metric) error {
default: default:
fmt.Fprintf(&buf, "%s%s %v\n", metricID, tagb.String(), value) fmt.Fprintf(&buf, "%s%s %v\n", metricID, tagb.String(), value)
} }
if metricCounter%dtIngestApiLineLimit == 0 {
err = d.send(buf.Bytes())
if err != nil {
return err
}
buf.Reset()
}
metricCounter++
} }
} }
} }
@ -249,13 +273,12 @@ func (d *Dynatrace) send(msg []byte) error {
resp, err := d.client.Do(req) resp, err := d.client.Do(req)
if err != nil { if err != nil {
d.Log.Errorf("Dynatrace error: %s", err.Error()) d.Log.Errorf("Dynatrace error: %s", err.Error())
fmt.Println(req)
return fmt.Errorf("error while sending HTTP request:, %s", err.Error()) return fmt.Errorf("error while sending HTTP request:, %s", err.Error())
} }
defer resp.Body.Close() defer resp.Body.Close()
// print metric line results as info log // print metric line results as info log
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusAccepted { if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusAccepted || resp.StatusCode == http.StatusBadRequest {
bodyBytes, err := ioutil.ReadAll(resp.Body) bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
d.Log.Errorf("Dynatrace error reading response") d.Log.Errorf("Dynatrace error reading response")
@ -265,7 +288,6 @@ func (d *Dynatrace) send(msg []byte) error {
} else { } else {
return fmt.Errorf("request failed with response code:, %d", resp.StatusCode) return fmt.Errorf("request failed with response code:, %d", resp.StatusCode)
} }
return nil return nil
} }