Skip to content

Commit

Permalink
feat(outputs.loki): add option for metric name label
Browse files Browse the repository at this point in the history
This allows the user to specify the label name used to store the metric
name. This label was added in influxdata#10001, but a user may not want this value
in which case they could set it to an empty string or use some other
customer value.

fixes: influxdata#13146
  • Loading branch information
powersj committed Apr 27, 2023
1 parent f297d3e commit 4882906
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 12 deletions.
6 changes: 6 additions & 0 deletions plugins/outputs/loki/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,10 @@ to use them.
# tls_ca = "/etc/telegraf/ca.pem"
# tls_cert = "/etc/telegraf/cert.pem"
# tls_key = "/etc/telegraf/key.pem"

## Metric Name Label
## Label to use for the metric name to when sending metrics. If set to an
## empty string, this will not add the label. This is NOT suggested as there
## is no way to differentiate between multiple metrics.
# metric_name_label = "__name"
```
36 changes: 24 additions & 12 deletions plugins/outputs/loki/loki.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,18 @@ const (
)

type Loki struct {
Domain string `toml:"domain"`
Endpoint string `toml:"endpoint"`
Timeout config.Duration `toml:"timeout"`
Username config.Secret `toml:"username"`
Password config.Secret `toml:"password"`
Headers map[string]string `toml:"http_headers"`
ClientID string `toml:"client_id"`
ClientSecret string `toml:"client_secret"`
TokenURL string `toml:"token_url"`
Scopes []string `toml:"scopes"`
GZipRequest bool `toml:"gzip_request"`
Domain string `toml:"domain"`
Endpoint string `toml:"endpoint"`
Timeout config.Duration `toml:"timeout"`
Username config.Secret `toml:"username"`
Password config.Secret `toml:"password"`
Headers map[string]string `toml:"http_headers"`
ClientID string `toml:"client_id"`
ClientSecret string `toml:"client_secret"`
TokenURL string `toml:"token_url"`
Scopes []string `toml:"scopes"`
GZipRequest bool `toml:"gzip_request"`
MetricNameLabel *string `toml:"metric_name_label"`

url string
client *http.Client
Expand Down Expand Up @@ -77,6 +78,15 @@ func (l *Loki) createClient(ctx context.Context) (*http.Client, error) {
return client, nil
}

func (l *Loki) Init() error {
if l.MetricNameLabel == nil {
defaultMetricName := "__name"
l.MetricNameLabel = &defaultMetricName
}

return nil
}

func (*Loki) SampleConfig() string {
return sampleConfig
}
Expand Down Expand Up @@ -119,7 +129,9 @@ func (l *Loki) Write(metrics []telegraf.Metric) error {
})

for _, m := range metrics {
m.AddTag("__name", m.Name())
if *l.MetricNameLabel != "" {
m.AddTag(*l.MetricNameLabel, m.Name())
}

tags := m.TagList()
var line string
Expand Down
62 changes: 62 additions & 0 deletions plugins/outputs/loki/loki_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,68 @@ func TestContentEncodingGzip(t *testing.T) {
}
}

func TestMetricNameLabel(t *testing.T) {
ts := httptest.NewServer(http.NotFoundHandler())
defer ts.Close()

u, err := url.Parse(fmt.Sprintf("http://%s", ts.Listener.Addr().String()))
require.NoError(t, err)

tests := []struct {
name string
metricNameLabel string
}{
{
name: "ensure default value of __name",
metricNameLabel: "nil",
},
{
name: "no label",
metricNameLabel: "",
},
{
name: "custom label",
metricNameLabel: "foobar",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ts.Config.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
payload, err := io.ReadAll(r.Body)
require.NoError(t, err)

var s Request
require.NoError(t, json.Unmarshal(payload, &s))

switch tt.metricNameLabel {
case "nil":
require.Equal(t, map[string]string{"__name": "log", "key1": "value1"}, s.Streams[0].Labels)
case "":
require.Equal(t, map[string]string{"key1": "value1"}, s.Streams[0].Labels)
case "foobar":
require.Equal(t, map[string]string{"foobar": "log", "key1": "value1"}, s.Streams[0].Labels)
}

w.WriteHeader(http.StatusNoContent)
})

var metricNameLabel *string
if tt.metricNameLabel != "nil" {
metricNameLabel = &tt.metricNameLabel //nolint:revive // different values
}

l := Loki{
Domain: u.String(),
MetricNameLabel: metricNameLabel,
}
require.NoError(t, l.Init())
require.NoError(t, l.Connect())
require.NoError(t, l.Write([]telegraf.Metric{getMetric()}))
})
}
}

func TestBasicAuth(t *testing.T) {
ts := httptest.NewServer(http.NotFoundHandler())
defer ts.Close()
Expand Down
6 changes: 6 additions & 0 deletions plugins/outputs/loki/sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@
# tls_ca = "/etc/telegraf/ca.pem"
# tls_cert = "/etc/telegraf/cert.pem"
# tls_key = "/etc/telegraf/key.pem"

## Metric Name Label
## Label to use for the metric name to when sending metrics. If set to an
## empty string, this will not add the label. This is NOT suggested as there
## is no way to differentiate between multiple metrics.
# metric_name_label = "__name"

0 comments on commit 4882906

Please sign in to comment.