diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index fa1b398ca3..f5f27a701b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -44,6 +44,7 @@ The following tip changes can be tested by building VictoriaMetrics components f * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): fix a panic during target discovery when `vmagent` runs with `-promscrape.dropOriginalLabels` command-line flag. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3580). The bug has been introduced in [v1.85.0](https://docs.victoriametrics.com/CHANGELOG.html#v1850). * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): [dockerswarm_sd_configs](https://docs.victoriametrics.com/sd_configs.html#dockerswarm_sd_configs): properly encode `filters` field. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3579). * BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent.html): fix possible resource leak after hot reload of the updated [consul_sd_configs](https://docs.victoriametrics.com/sd_configs.html#consul_sd_configs). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3468). +* BUGFIX: properly return label names starting from uppercase such as `CamelCaseLabel` from [/api/v1/labels](https://docs.victoriametrics.com/url-examples.html#apiv1labels). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3566). ## [v1.85.3](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.85.3) diff --git a/lib/storage/index_db.go b/lib/storage/index_db.go index 589a5f38d0..5b322eb61a 100644 --- a/lib/storage/index_db.go +++ b/lib/storage/index_db.go @@ -880,7 +880,7 @@ func (is *indexSearch) searchLabelNamesWithFiltersOnDate(qt *querytracer.Tracer, if len(labelName) == 0 { labelName = []byte("__name__") } - if isArtificialTagKey(labelName) || string(labelName) == string(prevLabelName) { + if isArtificialTagKey(labelName) { // Search for the next tag key. // The last char in kb.B must be tagSeparatorChar. // Just increment it in order to jump to the next tag key. @@ -895,6 +895,17 @@ func (is *indexSearch) searchLabelNamesWithFiltersOnDate(qt *querytracer.Tracer, ts.Seek(kb.B) continue } + if string(labelName) == string(prevLabelName) { + var tagValue []byte + if string(labelName) != "__name__" { + tagValue = labelName + } + kb.B = is.marshalCommonPrefixForDate(kb.B[:0], date) + kb.B = marshalTagValue(kb.B, tagValue) + kb.B[len(kb.B)-1]++ + ts.Seek(kb.B) + continue + } lns[string(labelName)] = struct{}{} prevLabelName = append(prevLabelName[:0], labelName...) } diff --git a/lib/storage/index_db_test.go b/lib/storage/index_db_test.go index 1c57a24174..c266ccdd30 100644 --- a/lib/storage/index_db_test.go +++ b/lib/storage/index_db_test.go @@ -1695,7 +1695,7 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { perDayMetricIDs := make(map[uint64]*uint64set.Set) var allMetricIDs uint64set.Set labelNames := []string{ - "__name__", "constant", "day", "uniqueid", + "__name__", "constant", "day", "UniqueId", "some_unique_id", } labelValues := []string{ "testMetric", @@ -1718,9 +1718,13 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { fmt.Sprintf("%v", day), ) mn.AddTag( - "uniqueid", + "UniqueId", fmt.Sprintf("%v", metric), ) + mn.AddTag( + "some_unique_id", + fmt.Sprintf("%v", day), + ) mn.sortTags() metricNameBuf = mn.Marshal(metricNameBuf[:0]) @@ -1893,6 +1897,10 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { t.Fatalf("unexpected SeriesCountByMetricName;\ngot\n%v\nwant\n%v", status.SeriesCountByMetricName, expectedSeriesCountByMetricName) } expectedSeriesCountByLabelName := []TopHeapEntry{ + { + Name: "UniqueId", + Count: 1000, + }, { Name: "__name__", Count: 1000, @@ -1906,7 +1914,7 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { Count: 1000, }, { - Name: "uniqueid", + Name: "some_unique_id", Count: 1000, }, } @@ -1924,7 +1932,7 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { } expectedLabelValueCountByLabelName := []TopHeapEntry{ { - Name: "uniqueid", + Name: "UniqueId", Count: 1000, }, { @@ -1939,6 +1947,10 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { Name: "day", Count: 1, }, + { + Name: "some_unique_id", + Count: 1, + }, } if !reflect.DeepEqual(status.LabelValueCountByLabelName, expectedLabelValueCountByLabelName) { t.Fatalf("unexpected LabelValueCountByLabelName;\ngot\n%v\nwant\n%v", status.LabelValueCountByLabelName, expectedLabelValueCountByLabelName) @@ -1957,11 +1969,11 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { Count: 1000, }, { - Name: "uniqueid=0", - Count: 1, + Name: "some_unique_id=0", + Count: 1000, }, { - Name: "uniqueid=1", + Name: "UniqueId=1", Count: 1, }, } @@ -1972,7 +1984,7 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { if status.TotalSeries != expectedTotalSeries { t.Fatalf("unexpected TotalSeries; got %d; want %d", status.TotalSeries, expectedTotalSeries) } - expectedLabelValuePairs := uint64(4000) + expectedLabelValuePairs := uint64(5000) if status.TotalLabelValuePairs != expectedLabelValuePairs { t.Fatalf("unexpected TotalLabelValuePairs; got %d; want %d", status.TotalLabelValuePairs, expectedLabelValuePairs) } @@ -2002,7 +2014,7 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { if status.TotalSeries != expectedTotalSeries { t.Fatalf("unexpected TotalSeries; got %d; want %d", status.TotalSeries, expectedTotalSeries) } - expectedLabelValuePairs = 4000 + expectedLabelValuePairs = 5000 if status.TotalLabelValuePairs != expectedLabelValuePairs { t.Fatalf("unexpected TotalLabelValuePairs; got %d; want %d", status.TotalLabelValuePairs, expectedLabelValuePairs) } @@ -2028,7 +2040,7 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { if status.TotalSeries != expectedTotalSeries { t.Fatalf("unexpected TotalSeries; got %d; want %d", status.TotalSeries, expectedTotalSeries) } - expectedLabelValuePairs = 20000 + expectedLabelValuePairs = 25000 if status.TotalLabelValuePairs != expectedLabelValuePairs { t.Fatalf("unexpected TotalLabelValuePairs; got %d; want %d", status.TotalLabelValuePairs, expectedLabelValuePairs) } @@ -2060,7 +2072,7 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { // Check GetTSDBStatus with non-nil filter, which matches only 3 series tfs = NewTagFilters(accountID, projectID) - if err := tfs.Add([]byte("uniqueid"), []byte("0|1|3"), false, true); err != nil { + if err := tfs.Add([]byte("UniqueId"), []byte("0|1|3"), false, true); err != nil { t.Fatalf("cannot add filter: %s", err) } status, err = db.GetTSDBStatus(nil, accountID, projectID, []*TagFilters{tfs}, baseDate, "", 5, 1e6, noDeadline) @@ -2083,7 +2095,7 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { if status.TotalSeries != expectedTotalSeries { t.Fatalf("unexpected TotalSeries; got %d; want %d", status.TotalSeries, expectedTotalSeries) } - expectedLabelValuePairs = 12 + expectedLabelValuePairs = 15 if status.TotalLabelValuePairs != expectedLabelValuePairs { t.Fatalf("unexpected TotalLabelValuePairs; got %d; want %d", status.TotalLabelValuePairs, expectedLabelValuePairs) } @@ -2109,7 +2121,7 @@ func TestSearchTSIDWithTimeRange(t *testing.T) { if status.TotalSeries != expectedTotalSeries { t.Fatalf("unexpected TotalSeries; got %d; want %d", status.TotalSeries, expectedTotalSeries) } - expectedLabelValuePairs = 60 + expectedLabelValuePairs = 75 if status.TotalLabelValuePairs != expectedLabelValuePairs { t.Fatalf("unexpected TotalLabelValuePairs; got %d; want %d", status.TotalLabelValuePairs, expectedLabelValuePairs) }