diff --git a/pkg/receive/config.go b/pkg/receive/config.go index e3af1cfa984..0ce7b8d8f49 100644 --- a/pkg/receive/config.go +++ b/pkg/receive/config.go @@ -20,6 +20,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/common/model" + "github.com/prometheus/prometheus/model/labels" ) var ( @@ -67,7 +68,7 @@ type HashringConfig struct { Tenants []string `json:"tenants,omitempty"` Endpoints []Endpoint `json:"endpoints"` Algorithm HashringAlgorithm `json:"algorithm,omitempty"` - ExternalLabels map[string]string `json:"external_labels,omitempty"` + ExternalLabels labels.Labels `json:"external_labels,omitempty"` } // ConfigWatcher is able to watch a file containing a hashring configuration diff --git a/pkg/receive/handler_test.go b/pkg/receive/handler_test.go index affabc085cc..143b3c25897 100644 --- a/pkg/receive/handler_test.go +++ b/pkg/receive/handler_test.go @@ -650,13 +650,7 @@ func testReceiveQuorum(t *testing.T, hashringAlgo HashringAlgorithm, withConsist // Test that each time series is stored // the correct amount of times in each fake DB. for _, ts := range tc.wreq.Timeseries { - lset := make(labels.Labels, len(ts.Labels)) - for j := range ts.Labels { - lset[j] = labels.Label{ - Name: ts.Labels[j].Name, - Value: ts.Labels[j].Value, - } - } + lset := labelpb.ZLabelsToPromLabels(ts.Labels) for j, a := range tc.appendables { if withConsistencyDelay { var expected int diff --git a/pkg/receive/multitsdb.go b/pkg/receive/multitsdb.go index 754b2ad6e73..e5a7e29c1d6 100644 --- a/pkg/receive/multitsdb.go +++ b/pkg/receive/multitsdb.go @@ -10,31 +10,28 @@ import ( "path" "path/filepath" "sort" - "strings" "sync" "time" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/pkg/errors" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/common/model" - "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/storage" - "github.com/prometheus/prometheus/tsdb" "go.uber.org/atomic" "golang.org/x/exp/slices" "golang.org/x/sync/errgroup" - "github.com/thanos-io/thanos/pkg/api/status" - "github.com/thanos-io/thanos/pkg/info/infopb" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/prometheus/model/labels" + "github.com/prometheus/prometheus/storage" + "github.com/prometheus/prometheus/tsdb" "github.com/thanos-io/objstore" - + "github.com/thanos-io/thanos/pkg/api/status" "github.com/thanos-io/thanos/pkg/block/metadata" "github.com/thanos-io/thanos/pkg/component" "github.com/thanos-io/thanos/pkg/errutil" "github.com/thanos-io/thanos/pkg/exemplars" + "github.com/thanos-io/thanos/pkg/info/infopb" "github.com/thanos-io/thanos/pkg/shipper" "github.com/thanos-io/thanos/pkg/store" "github.com/thanos-io/thanos/pkg/store/labelpb" @@ -572,12 +569,7 @@ func (t *MultiTSDB) startTSDB(logger log.Logger, tenantID string, tenant *tenant reg = NewUnRegisterer(reg) initialLset := labelpb.ExtendSortedLabels(t.labels, labels.FromStrings(t.tenantLabelName, tenantID)) - - lset, err := t.extractTenantsLabels(tenantID, initialLset) - if err != nil { - return err - } - + lset := t.extractTenantsLabels(tenantID, initialLset) dataDir := t.defaultTenantDataDir(tenantID) level.Info(logger).Log("msg", "opening TSDB") @@ -686,14 +678,7 @@ func (t *MultiTSDB) SetHashringConfig(cfg []HashringConfig) error { updatedTenants = append(updatedTenants, tenantID) lset := labelpb.ExtendSortedLabels(t.labels, labels.FromStrings(t.tenantLabelName, tenantID)) - - if hc.ExternalLabels != nil { - extendedLset, err := extendLabels(lset, hc.ExternalLabels, t.logger) - if err != nil { - return errors.Wrap(err, "failed to extend external labels for tenant "+tenantID) - } - lset = extendedLset - } + lset = labelpb.ExtendSortedLabels(hc.ExternalLabels, lset) if t.tenants[tenantID].ship != nil { t.tenants[tenantID].ship.SetLabels(lset) @@ -865,63 +850,14 @@ func (u *UnRegisterer) MustRegister(cs ...prometheus.Collector) { // extractTenantsLabels extracts tenant's external labels from hashring configs. // If one tenant appears in multiple hashring configs, // only the external label set from the first hashring config is applied. -func (t *MultiTSDB) extractTenantsLabels(tenantID string, initialLset labels.Labels) (labels.Labels, error) { +func (t *MultiTSDB) extractTenantsLabels(tenantID string, initialLset labels.Labels) labels.Labels { for _, hc := range t.hashringConfigs { for _, tenant := range hc.Tenants { if tenant != tenantID { continue } - - if hc.ExternalLabels != nil { - extendedLset, err := extendLabels(initialLset, hc.ExternalLabels, t.logger) - if err != nil { - return nil, errors.Wrap(err, "failed to extend external labels for tenant "+tenantID) - } - return extendedLset, nil - } - - return initialLset, nil + return labelpb.ExtendSortedLabels(hc.ExternalLabels, initialLset) } } - - return initialLset, nil -} - -// extendLabels extends external labels of the initial label set. -// If an external label shares same name with a label in the initial label set, -// use the label in the initial label set and inform user about it. -func extendLabels(labelSet labels.Labels, extend map[string]string, logger log.Logger) (labels.Labels, error) { - var extendLabels labels.Labels - for name, value := range extend { - if !model.LabelName.IsValid(model.LabelName(name)) { - return nil, errors.Errorf("unsupported format for label's name: %s", name) - } - extendLabels = append(extendLabels, labels.Label{Name: name, Value: value}) - } - - sort.Sort(labelSet) - sort.Sort(extendLabels) - - extendedLabelSet := make(labels.Labels, 0, len(labelSet)+len(extendLabels)) - for len(labelSet) > 0 && len(extendLabels) > 0 { - d := strings.Compare(labelSet[0].Name, extendLabels[0].Name) - if d == 0 { - extendedLabelSet = append(extendedLabelSet, labelSet[0]) - level.Info(logger).Log("msg", "Duplicate label found. Using initial label instead.", - "label's name", extendLabels[0].Name) - labelSet, extendLabels = labelSet[1:], extendLabels[1:] - } else if d < 0 { - extendedLabelSet = append(extendedLabelSet, labelSet[0]) - labelSet = labelSet[1:] - } else if d > 0 { - extendedLabelSet = append(extendedLabelSet, extendLabels[0]) - extendLabels = extendLabels[1:] - } - } - extendedLabelSet = append(extendedLabelSet, labelSet...) - extendedLabelSet = append(extendedLabelSet, extendLabels...) - - sort.Sort(extendedLabelSet) - - return extendedLabelSet, nil + return initialLset } diff --git a/pkg/receive/multitsdb_test.go b/pkg/receive/multitsdb_test.go index cc13b5c6abe..89aeebab734 100644 --- a/pkg/receive/multitsdb_test.go +++ b/pkg/receive/multitsdb_test.go @@ -775,7 +775,7 @@ func queryLabelValues(ctx context.Context, m *MultiTSDB) error { clients[0] = &slowClient{clients[0]} } return clients - }, component.Store, nil, 1*time.Minute, store.LazyRetrieval) + }, component.Store, labels.EmptyLabels(), 1*time.Minute, store.LazyRetrieval) req := &storepb.LabelValuesRequest{ Label: labels.MetricName, diff --git a/pkg/receive/receive_test.go b/pkg/receive/receive_test.go index 55b59d182a2..ea1b6d81fdb 100644 --- a/pkg/receive/receive_test.go +++ b/pkg/receive/receive_test.go @@ -8,16 +8,13 @@ import ( "time" "github.com/go-kit/log" - "github.com/stretchr/testify/require" "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/tsdb" "github.com/thanos-io/objstore" - "github.com/thanos-io/thanos/pkg/block/metadata" "github.com/thanos-io/thanos/pkg/store" "github.com/thanos-io/thanos/pkg/store/labelpb" @@ -50,11 +47,9 @@ func TestAddingExternalLabelsForTenants(t *testing.T) { name: "One tenant - One label", cfg: []HashringConfig{ { - Endpoints: []Endpoint{{Address: "node1"}}, - Tenants: []string{"tenant1"}, - ExternalLabels: map[string]string{ - "name1": "value1", - }, + Endpoints: []Endpoint{{Address: "node1"}}, + Tenants: []string{"tenant1"}, + ExternalLabels: labels.FromStrings("name1", "value1"), }, }, expectedExternalLabelSets: []labels.Labels{ @@ -67,11 +62,11 @@ func TestAddingExternalLabelsForTenants(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value1", "name2": "value2", "name3": "value3", - }, + }), }, }, expectedExternalLabelSets: []labels.Labels{ @@ -99,9 +94,9 @@ func TestAddingExternalLabelsForTenants(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value1", - }, + }), }, }, expectedExternalLabelSets: []labels.Labels{ @@ -116,11 +111,11 @@ func TestAddingExternalLabelsForTenants(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name3": "value3", "name2": "value2", "name1": "value1", - }, + }), }, }, expectedExternalLabelSets: []labels.Labels{ @@ -138,20 +133,20 @@ func TestAddingExternalLabelsForTenants(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value1", "name2": "value2", "name3": "value3", - }, + }), }, { Endpoints: []Endpoint{{Address: "node2"}}, Tenants: []string{"tenant4", "tenant5", "tenant6"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name6": "value6", "name5": "value5", "name4": "value4", - }, + }), }, }, expectedExternalLabelSets: []labels.Labels{ @@ -175,20 +170,20 @@ func TestAddingExternalLabelsForTenants(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name3": "value3", "name2": "value2", "name1": "value1", - }, + }), }, { Endpoints: []Endpoint{{Address: "node2"}}, Tenants: []string{"tenant4", "tenant5", "tenant1"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name4": "value4", "name5": "value5", "name6": "value6", - }, + }), }, }, expectedExternalLabelSets: []labels.Labels{ @@ -247,11 +242,11 @@ func TestLabelSetsOfTenantsWhenAddingTenants(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value1", "name2": "value2", "name3": "value3", - }, + }), }, } initialExpectedExternalLabelSets := []labels.Labels{ @@ -267,11 +262,11 @@ func TestLabelSetsOfTenantsWhenAddingTenants(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3", "tenant4", "tenant5"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value1", "name2": "value2", "name3": "value3", - }, + }), }, } changedExpectedExternalLabelSets := []labels.Labels{ @@ -356,20 +351,20 @@ func TestLabelSetsOfTenantsWhenChangingLabels(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value1", "name2": "value2", "name3": "value3", - }, + }), }, { Endpoints: []Endpoint{{Address: "node2"}}, Tenants: []string{"tenant4", "tenant5", "tenant6"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name6": "value6", "name5": "value5", "name4": "value4", - }, + }), }, } initialExpectedExternalLabelSets := []labels.Labels{ @@ -398,22 +393,22 @@ func TestLabelSetsOfTenantsWhenChangingLabels(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value1", "name2": "value2", "name3": "value3", "name4": "value4", - }, + }), }, { Endpoints: []Endpoint{{Address: "node2"}}, Tenants: []string{"tenant4", "tenant5", "tenant6"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name4": "value4", "name5": "value5", "name6": "value6", "name7": "value7", - }, + }), }, }, changedExpectedExternalLabelSets: []labels.Labels{ @@ -437,18 +432,18 @@ func TestLabelSetsOfTenantsWhenChangingLabels(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value1", "name2": "value2", - }, + }), }, { Endpoints: []Endpoint{{Address: "node2"}}, Tenants: []string{"tenant4", "tenant5", "tenant6"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name4": "value4", "name5": "value5", - }, + }), }, }, changedExpectedExternalLabelSets: []labels.Labels{ @@ -493,20 +488,20 @@ func TestLabelSetsOfTenantsWhenChangingLabels(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value3", "name2": "value2", "name3": "value3", - }, + }), }, { Endpoints: []Endpoint{{Address: "node2"}}, Tenants: []string{"tenant4", "tenant5", "tenant6"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name4": "value6", "name5": "value5", "name6": "value6", - }, + }), }, }, changedExpectedExternalLabelSets: []labels.Labels{ @@ -586,20 +581,20 @@ func TestAddingLabelsWhenTenantAppearsInMultipleHashrings(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name3": "value3", "name2": "value2", "name1": "value1", - }, + }), }, { Endpoints: []Endpoint{{Address: "node2"}}, Tenants: []string{"tenant4", "tenant5", "tenant1"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name4": "value4", "name5": "value5", "name6": "value6", - }, + }), }, } initialExpectedExternalLabelSets := []labels.Labels{ @@ -626,21 +621,21 @@ func TestAddingLabelsWhenTenantAppearsInMultipleHashrings(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value1", "name2": "value2", "name3": "value3", "name4": "value4", - }, + }), }, { Endpoints: []Endpoint{{Address: "node2"}}, Tenants: []string{"tenant4", "tenant5", "tenant1"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name4": "value4", "name5": "value5", "name6": "value6", - }, + }), }, }, changedExpectedExternalLabelSets: []labels.Labels{ @@ -662,21 +657,21 @@ func TestAddingLabelsWhenTenantAppearsInMultipleHashrings(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1", "tenant2", "tenant3"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name1": "value1", "name2": "value2", "name3": "value3", - }, + }), }, { Endpoints: []Endpoint{{Address: "node2"}}, Tenants: []string{"tenant4", "tenant5", "tenant1"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "name4": "value4", "name5": "value5", "name6": "value6", "name7": "value7", - }, + }), }, }, changedExpectedExternalLabelSets: []labels.Labels{ @@ -754,11 +749,11 @@ func TestReceiverLabelsNotOverwrittenByExternalLabels(t *testing.T) { { Endpoints: []Endpoint{{Address: "node1"}}, Tenants: []string{"tenant1"}, - ExternalLabels: map[string]string{ + ExternalLabels: labels.FromMap(map[string]string{ "replica": "0", "tenant_id": "tenant2", "name3": "value3", - }, + }), }, } expectedExternalLabelSets := []labels.Labels{