diff --git a/app/vmselect/netstorage/netstorage.go b/app/vmselect/netstorage/netstorage.go index f520f97688..b7b30f2d5f 100644 --- a/app/vmselect/netstorage/netstorage.go +++ b/app/vmselect/netstorage/netstorage.go @@ -514,12 +514,40 @@ func GetLabels(deadline searchutils.Deadline) ([]string, error) { } } + // Merge labels obtained from Prometheus storage. + promLabels, err := promdb.GetLabelNames(deadline) + if err != nil { + return nil, fmt.Errorf("cannot obtain labels from Prometheus storage: %w", err) + } + labels = mergeStrings(labels, promLabels) + // Sort labels like Prometheus does sort.Strings(labels) return labels, nil } +func mergeStrings(a, b []string) []string { + if len(a) == 0 { + return b + } + if len(b) == 0 { + return a + } + m := make(map[string]struct{}, len(a)+len(b)) + for _, s := range a { + m[s] = struct{}{} + } + for _, s := range b { + m[s] = struct{}{} + } + result := make([]string, 0, len(m)) + for s := range m { + result = append(result, s) + } + return result +} + // GetLabelValues returns label values for the given labelName // until the given deadline. func GetLabelValues(labelName string, deadline searchutils.Deadline) ([]string, error) { @@ -536,6 +564,13 @@ func GetLabelValues(labelName string, deadline searchutils.Deadline) ([]string, return nil, fmt.Errorf("error during label values search for labelName=%q: %w", labelName, err) } + // Merge label values obtained from Prometheus storage. + promLabelValues, err := promdb.GetLabelValues(labelName, deadline) + if err != nil { + return nil, fmt.Errorf("cannot obtain label values for %q from Prometheus storage: %w", labelName, err) + } + labelValues = mergeStrings(labelValues, promLabelValues) + // Sort labelValues like Prometheus does sort.Strings(labelValues) diff --git a/app/vmselect/prometheus/prometheus.go b/app/vmselect/prometheus/prometheus.go index 681f9926be..ab074e9f1f 100644 --- a/app/vmselect/prometheus/prometheus.go +++ b/app/vmselect/prometheus/prometheus.go @@ -14,7 +14,6 @@ import ( "github.com/VictoriaMetrics/VictoriaMetrics/app/vmselect/netstorage" "github.com/VictoriaMetrics/VictoriaMetrics/app/vmselect/promql" "github.com/VictoriaMetrics/VictoriaMetrics/app/vmselect/searchutils" - "github.com/VictoriaMetrics/VictoriaMetrics/app/vmstorage/promdb" "github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime" "github.com/VictoriaMetrics/VictoriaMetrics/lib/flagutil" "github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver" @@ -286,10 +285,6 @@ func LabelValuesHandler(startTime time.Time, labelName string, w http.ResponseWr if err := r.ParseForm(); err != nil { return fmt.Errorf("cannot parse form values: %w", err) } - promTR := storage.TimeRange{ - MinTimestamp: 0, - MaxTimestamp: startTime.UnixNano() / 1e6, - } var labelValues []string if len(r.Form["match[]"]) == 0 && len(r.Form["start"]) == 0 && len(r.Form["end"]) == 0 { var err error @@ -319,17 +314,8 @@ func LabelValuesHandler(startTime time.Time, labelName string, w http.ResponseWr if err != nil { return fmt.Errorf("cannot obtain label values for %q, match[]=%q, start=%d, end=%d: %w", labelName, matches, start, end, err) } - promTR.MinTimestamp = start - promTR.MaxTimestamp = end } - // Merge label values obtained from Prometheus storage. - promLabelValues, err := promdb.GetLabelValues(promTR, labelName, deadline) - if err != nil { - return fmt.Errorf("cannot obtain label values for %q from Prometheus storage: %s", labelName, err) - } - labelValues = mergeAndSortStrings(labelValues, promLabelValues) - w.Header().Set("Content-Type", "application/json") WriteLabelValuesResponse(w, labelValues) labelValuesDuration.UpdateDuration(startTime) @@ -464,10 +450,6 @@ func LabelsHandler(startTime time.Time, w http.ResponseWriter, r *http.Request) if err := r.ParseForm(); err != nil { return fmt.Errorf("cannot parse form values: %w", err) } - promTR := storage.TimeRange{ - MinTimestamp: 0, - MaxTimestamp: startTime.UnixNano() / 1e6, - } var labels []string if len(r.Form["match[]"]) == 0 && len(r.Form["start"]) == 0 && len(r.Form["end"]) == 0 { var err error @@ -495,45 +477,14 @@ func LabelsHandler(startTime time.Time, w http.ResponseWriter, r *http.Request) if err != nil { return fmt.Errorf("cannot obtain labels for match[]=%q, start=%d, end=%d: %w", matches, start, end, err) } - promTR.MinTimestamp = start - promTR.MaxTimestamp = end } - // Merge labels obtained from Prometheus storage. - promLabels, err := promdb.GetLabelNames(promTR, deadline) - if err != nil { - return fmt.Errorf("cannot obtain labels from Prometheus storage: %s", err) - } - labels = mergeAndSortStrings(labels, promLabels) - w.Header().Set("Content-Type", "application/json") WriteLabelsResponse(w, labels) labelsDuration.UpdateDuration(startTime) return nil } -func mergeAndSortStrings(a, b []string) []string { - if len(a) == 0 { - return b - } - if len(b) == 0 { - return a - } - m := make(map[string]struct{}, len(a)+len(b)) - for _, s := range a { - m[s] = struct{}{} - } - for _, s := range b { - m[s] = struct{}{} - } - result := make([]string, 0, len(m)) - for s := range m { - result = append(result, s) - } - sort.Strings(result) - return result -} - func labelsWithMatches(matches []string, start, end int64, deadline searchutils.Deadline) ([]string, error) { if len(matches) == 0 { logger.Panicf("BUG: matches must be non-empty") diff --git a/app/vmstorage/promdb/promdb.go b/app/vmstorage/promdb/promdb.go index 9a026fc0d4..11824bc27b 100644 --- a/app/vmstorage/promdb/promdb.go +++ b/app/vmstorage/promdb/promdb.go @@ -60,12 +60,12 @@ func MustClose() { var promDB *tsdb.DB -// GetLabelNames returns label names on the given time range tr. -func GetLabelNames(tr storage.TimeRange, deadline searchutils.Deadline) ([]string, error) { +// GetLabelNames returns label names. +func GetLabelNames(deadline searchutils.Deadline) ([]string, error) { d := time.Unix(int64(deadline.Deadline()), 0) ctx, cancel := context.WithDeadline(context.Background(), d) defer cancel() - q, err := promDB.Querier(ctx, tr.MinTimestamp, tr.MaxTimestamp) + q, err := promDB.Querier(ctx, 0, d.UnixNano()/1e6) if err != nil { return nil, err } @@ -77,12 +77,12 @@ func GetLabelNames(tr storage.TimeRange, deadline searchutils.Deadline) ([]strin return names, err } -// GetLabelValues returns values for the given labelName on the given tr. -func GetLabelValues(tr storage.TimeRange, labelName string, deadline searchutils.Deadline) ([]string, error) { +// GetLabelValues returns values for the given labelName. +func GetLabelValues(labelName string, deadline searchutils.Deadline) ([]string, error) { d := time.Unix(int64(deadline.Deadline()), 0) ctx, cancel := context.WithDeadline(context.Background(), d) defer cancel() - q, err := promDB.Querier(ctx, tr.MinTimestamp, tr.MaxTimestamp) + q, err := promDB.Querier(ctx, 0, d.UnixNano()/1e6) if err != nil { return nil, err }