diff --git a/CHANGELOG.md b/CHANGELOG.md index e2f10620bf6c..76a1fce9d595 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,8 @@ Main (unreleased) - `otelcol.processor.filter` - filters OTLP telemetry data using OpenTelemetry Transformation Language (OTTL). (@hainenber) +- Agent Management: Introduce support for remotely managed external labels for logs. (@jcreixell) + ### Enhancements - The `loki.write` WAL now has snappy compression enabled by default. (@thepalbi) diff --git a/pkg/config/agent_management_remote_config_test.go b/pkg/config/agent_management_remote_config_test.go index 887173411994..af97bd70190a 100644 --- a/pkg/config/agent_management_remote_config_test.go +++ b/pkg/config/agent_management_remote_config_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/grafana/agent/pkg/metrics/instance" + "github.com/prometheus/common/model" "github.com/prometheus/prometheus/model/labels" "github.com/stretchr/testify/require" ) @@ -199,7 +200,13 @@ server: metrics: global: external_labels: - foo: bar` + foo: bar +logs: + global: + clients: + - external_labels: + foo: bar +` rc := RemoteConfig{ BaseConfig: BaseConfigContent(baseConfig), Snippets: allSnippets, @@ -207,11 +214,26 @@ metrics: c, err := rc.BuildAgentConfig() require.NoError(t, err) require.Equal(t, 1, len(c.Logs.Configs)) + require.Equal(t, 1, len(c.Logs.Global.ClientConfigs)) + require.Equal(t, c.Logs.Global.ClientConfigs[0].ExternalLabels.LabelSet, model.LabelSet{"foo": "bar"}) require.Equal(t, 1, len(c.Metrics.Global.Prometheus.ExternalLabels)) require.Contains(t, c.Metrics.Global.Prometheus.ExternalLabels, labels.Label{Name: "foo", Value: "bar"}) }) t.Run("external labels provided", func(t *testing.T) { + baseConfig := ` +server: + log_level: debug +metrics: + global: + remote_write: + - url: http://localhost:9090/api/prom/push +logs: + global: + clients: + - url: http://localhost:3100/loki/api/v1/push +` + rc := RemoteConfig{ BaseConfig: BaseConfigContent(baseConfig), Snippets: allSnippets, @@ -225,6 +247,8 @@ metrics: require.NoError(t, err) require.Equal(t, 1, len(c.Logs.Configs)) require.Equal(t, 1, len(c.Metrics.Configs)) + require.Equal(t, 1, len(c.Logs.Global.ClientConfigs)) + require.Equal(t, c.Logs.Global.ClientConfigs[0].ExternalLabels.LabelSet, model.LabelSet{"foo": "bar"}) require.Contains(t, c.Metrics.Global.Prometheus.ExternalLabels, labels.Label{Name: "foo", Value: "bar"}) }) @@ -236,6 +260,11 @@ metrics: global: external_labels: foo: bar +logs: + global: + clients: + - external_labels: + foo: bar ` rc := RemoteConfig{ BaseConfig: BaseConfigContent(baseConfig), @@ -250,6 +279,8 @@ metrics: require.NoError(t, err) require.Equal(t, 1, len(c.Logs.Configs)) require.Equal(t, 1, len(c.Metrics.Configs)) + require.Equal(t, 1, len(c.Logs.Global.ClientConfigs)) + require.Equal(t, c.Logs.Global.ClientConfigs[0].ExternalLabels.LabelSet, model.LabelSet{"foo": "bar"}) require.Contains(t, c.Metrics.Global.Prometheus.ExternalLabels, labels.Label{Name: "foo", Value: "bar"}) require.NotContains(t, c.Metrics.Global.Prometheus.ExternalLabels, labels.Label{Name: "foo", Value: "baz"}) }) diff --git a/pkg/config/agentmanagement_remote_config.go b/pkg/config/agentmanagement_remote_config.go index f5deeed9a47c..c1f87615930d 100644 --- a/pkg/config/agentmanagement_remote_config.go +++ b/pkg/config/agentmanagement_remote_config.go @@ -5,6 +5,7 @@ import ( "github.com/grafana/agent/pkg/logs" "github.com/grafana/agent/pkg/metrics/instance" "github.com/grafana/loki/clients/pkg/promtail/scrapeconfig" + "github.com/prometheus/common/model" pc "github.com/prometheus/prometheus/config" "github.com/prometheus/prometheus/model/labels" "gopkg.in/yaml.v2" @@ -130,11 +131,20 @@ func appendExternalLabels(c *Config, externalLabels map[string]string) { return } // Start off with the existing external labels, which will only be added to (not replaced) - newExternalLabels := c.Metrics.Global.Prometheus.ExternalLabels.Map() + metricsExternalLabels := c.Metrics.Global.Prometheus.ExternalLabels.Map() for k, v := range externalLabels { - if _, ok := newExternalLabels[k]; !ok { - newExternalLabels[k] = v + if _, ok := metricsExternalLabels[k]; !ok { + metricsExternalLabels[k] = v } } - c.Metrics.Global.Prometheus.ExternalLabels = labels.FromMap(newExternalLabels) + + logsExternalLabels := make(model.LabelSet) + for k, v := range externalLabels { + logsExternalLabels[model.LabelName(k)] = model.LabelValue(v) + } + + c.Metrics.Global.Prometheus.ExternalLabels = labels.FromMap(metricsExternalLabels) + for i, cc := range c.Logs.Global.ClientConfigs { + c.Logs.Global.ClientConfigs[i].ExternalLabels.LabelSet = logsExternalLabels.Merge(cc.ExternalLabels.LabelSet) + } }