diff --git a/pkg/services/ngalert/state/historian/loki_http.go b/pkg/services/ngalert/state/historian/loki_http.go index 2404a5ce0a6..e4c5f337087 100644 --- a/pkg/services/ngalert/state/historian/loki_http.go +++ b/pkg/services/ngalert/state/historian/loki_http.go @@ -73,6 +73,7 @@ func NewLokiConfig(cfg setting.UnifiedAlertingStateHistorySettings) (LokiConfig, BasicAuthUser: cfg.LokiBasicAuthUsername, BasicAuthPassword: cfg.LokiBasicAuthPassword, TenantID: cfg.LokiTenantID, + ExternalLabels: cfg.ExternalLabels, // Snappy-compressed protobuf is the default, same goes for Promtail. Encoder: SnappyProtoEncoder{}, }, nil diff --git a/pkg/services/ngalert/state/historian/loki_http_test.go b/pkg/services/ngalert/state/historian/loki_http_test.go index 56b3062438d..82a4e0e48ca 100644 --- a/pkg/services/ngalert/state/historian/loki_http_test.go +++ b/pkg/services/ngalert/state/historian/loki_http_test.go @@ -72,6 +72,18 @@ func TestLokiConfig(t *testing.T) { }) } }) + + t.Run("captures external labels", func(t *testing.T) { + set := setting.UnifiedAlertingStateHistorySettings{ + LokiRemoteURL: "http://url.com", + ExternalLabels: map[string]string{"a": "b"}, + } + + res, err := NewLokiConfig(set) + + require.NoError(t, err) + require.Contains(t, res.ExternalLabels, "a") + }) } // This function can be used for local testing, just remove the skip call. diff --git a/pkg/services/ngalert/state/historian/loki_test.go b/pkg/services/ngalert/state/historian/loki_test.go index d499e4f9332..16d3e420713 100644 --- a/pkg/services/ngalert/state/historian/loki_test.go +++ b/pkg/services/ngalert/state/historian/loki_test.go @@ -346,14 +346,32 @@ grafana_alerting_state_history_writes_total{org="1"} 2 require.Contains(t, sent, "contains=equals") require.Contains(t, sent, "contains🤔emoji") }) + + t.Run("adds external labels to log lines", func(t *testing.T) { + req := NewFakeRequester() + loki := createTestLokiBackend(req, metrics.NewHistorianMetrics(prometheus.NewRegistry())) + rule := createTestRule() + states := singleFromNormal(&state.State{ + State: eval.Alerting, + }) + + err := <-loki.Record(context.Background(), rule, states) + + require.NoError(t, err) + require.Contains(t, "/loki/api/v1/push", req.lastRequest.URL.Path) + sent := string(readBody(t, req.lastRequest)) + require.Contains(t, sent, "externalLabelKey") + require.Contains(t, sent, "externalLabelValue") + }) } func createTestLokiBackend(req client.Requester, met *metrics.Historian) *RemoteLokiBackend { url, _ := url.Parse("http://some.url") cfg := LokiConfig{ - WritePathURL: url, - ReadPathURL: url, - Encoder: JsonEncoder{}, + WritePathURL: url, + ReadPathURL: url, + Encoder: JsonEncoder{}, + ExternalLabels: map[string]string{"externalLabelKey": "externalLabelValue"}, } return NewRemoteLokiBackend(cfg, req, met) }