Skip to content

Commit 2fed9b7

Browse files
authored
Add an empty labels validation (#7052)
Signed-off-by: SungJin1212 <tjdwls1201@gmail.com>
1 parent 5b7b4f5 commit 2fed9b7

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* [FEATURE] Querier: Support for configuring query optimizers and enabling XFunctions in the Thanos engine. #6873
2525
* [FEATURE] Query Frontend: Add support /api/v1/format_query API for formatting queries. #6893
2626
* [FEATURE] Query Frontend: Add support for /api/v1/parse_query API (experimental) to parse a PromQL expression and return it as a JSON-formatted AST (abstract syntax tree). #6978
27+
* [ENHANCEMENT] Distributor: Emit an error with a 400 status code when empty labels are found before the relabelling or label dropping process. #7052
2728
* [ENHANCEMENT] Parquet Storage: Add support for additional sort columns during Parquet file generation #7003
2829
* [ENHANCEMENT] Modernizes the entire codebase by using go modernize tool. #7005
2930
* [ENHANCEMENT] Overrides Exporter: Expose all fields that can be converted to float64. Also, the label value `max_local_series_per_metric` got renamed to `max_series_per_metric`, and `max_local_series_per_user` got renamed to `max_series_per_user`. #6979

pkg/distributor/distributor.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,10 @@ func (d *Distributor) prepareSeriesKeys(ctx context.Context, req *cortexpb.Write
10121012
// check each sample and discard if outside limits.
10131013
skipLabelNameValidation := d.cfg.SkipLabelNameValidation || req.GetSkipLabelNameValidation()
10141014
for _, ts := range req.Timeseries {
1015+
if len(ts.Labels) == 0 {
1016+
return nil, nil, nil, nil, 0, 0, 0, nil, httpgrpc.Errorf(http.StatusBadRequest, "%s", "empty labels found")
1017+
}
1018+
10151019
if limits.AcceptHASamples && limits.AcceptMixedHASamples {
10161020
cluster, replica := findHALabels(limits.HAReplicaLabel, limits.HAClusterLabel, ts.Labels)
10171021
if cluster != "" && replica != "" {

pkg/distributor/distributor_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,69 @@ func TestDistributor_PushIngestionRateLimiter_Histograms(t *testing.T) {
849849

850850
}
851851

852+
func TestPush_EmptyLabels(t *testing.T) {
853+
t.Parallel()
854+
855+
var limits validation.Limits
856+
flagext.DefaultValues(&limits)
857+
858+
limits.IngestionRate = math.MaxFloat64
859+
860+
dists, _, _, _ := prepare(t, prepConfig{
861+
numDistributors: 1,
862+
numIngesters: 3,
863+
happyIngesters: 3,
864+
})
865+
866+
ctx := user.InjectOrgID(context.Background(), "user")
867+
868+
d := dists[0]
869+
ts := time.Now().UnixMilli()
870+
871+
tests := []struct {
872+
desc string
873+
request *cortexpb.WriteRequest
874+
isErr bool
875+
}{
876+
{
877+
desc: "1 series, a series has empty labels",
878+
request: &cortexpb.WriteRequest{
879+
Timeseries: []cortexpb.PreallocTimeseries{
880+
makeWriteRequestTimeseries(
881+
[]cortexpb.LabelAdapter{}, ts, 3, false),
882+
},
883+
},
884+
isErr: true,
885+
},
886+
{
887+
desc: "2 series, one series has empty labels",
888+
request: &cortexpb.WriteRequest{
889+
Timeseries: []cortexpb.PreallocTimeseries{
890+
makeWriteRequestTimeseries(
891+
[]cortexpb.LabelAdapter{}, ts, 3, false),
892+
makeWriteRequestTimeseries(
893+
[]cortexpb.LabelAdapter{
894+
{Name: model.MetricNameLabel, Value: "foo"},
895+
{Name: "bar", Value: "baz"},
896+
}, ts, 3, false),
897+
},
898+
},
899+
isErr: true,
900+
},
901+
}
902+
903+
for _, test := range tests {
904+
t.Run(test.desc, func(t *testing.T) {
905+
_, err := d.Push(ctx, test.request)
906+
require.Error(t, err)
907+
s, ok := status.FromError(err)
908+
require.True(t, ok)
909+
require.Equal(t, codes.Code(400), s.Code())
910+
require.Equal(t, "empty labels found", s.Message())
911+
})
912+
}
913+
}
914+
852915
func TestPush_QuorumError(t *testing.T) {
853916
t.Parallel()
854917

0 commit comments

Comments
 (0)