|
|
|
@ -658,6 +658,10 @@ func (api *API) labelNames(r *http.Request) apiFuncResult {
|
|
|
|
|
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
hints := &storage.LabelHints{ |
|
|
|
|
Limit: toHintLimit(limit), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
q, err := api.Queryable.Querier(timestamp.FromTime(start), timestamp.FromTime(end)) |
|
|
|
|
if err != nil { |
|
|
|
|
return apiFuncResult{nil, returnAPIError(err), nil, nil} |
|
|
|
@ -672,7 +676,7 @@ func (api *API) labelNames(r *http.Request) apiFuncResult {
|
|
|
|
|
labelNamesSet := make(map[string]struct{}) |
|
|
|
|
|
|
|
|
|
for _, matchers := range matcherSets { |
|
|
|
|
vals, callWarnings, err := q.LabelNames(r.Context(), matchers...) |
|
|
|
|
vals, callWarnings, err := q.LabelNames(r.Context(), hints, matchers...) |
|
|
|
|
if err != nil { |
|
|
|
|
return apiFuncResult{nil, returnAPIError(err), warnings, nil} |
|
|
|
|
} |
|
|
|
@ -694,7 +698,7 @@ func (api *API) labelNames(r *http.Request) apiFuncResult {
|
|
|
|
|
if len(matcherSets) == 1 { |
|
|
|
|
matchers = matcherSets[0] |
|
|
|
|
} |
|
|
|
|
names, warnings, err = q.LabelNames(r.Context(), matchers...) |
|
|
|
|
names, warnings, err = q.LabelNames(r.Context(), hints, matchers...) |
|
|
|
|
if err != nil { |
|
|
|
|
return apiFuncResult{nil, &apiError{errorExec, err}, warnings, nil} |
|
|
|
|
} |
|
|
|
@ -704,7 +708,7 @@ func (api *API) labelNames(r *http.Request) apiFuncResult {
|
|
|
|
|
names = []string{} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if len(names) > limit { |
|
|
|
|
if limit > 0 && len(names) > limit { |
|
|
|
|
names = names[:limit] |
|
|
|
|
warnings = warnings.Add(errors.New("results truncated due to limit")) |
|
|
|
|
} |
|
|
|
@ -738,6 +742,10 @@ func (api *API) labelValues(r *http.Request) (result apiFuncResult) {
|
|
|
|
|
return apiFuncResult{nil, &apiError{errorBadData, err}, nil, nil} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
hints := &storage.LabelHints{ |
|
|
|
|
Limit: toHintLimit(limit), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
q, err := api.Queryable.Querier(timestamp.FromTime(start), timestamp.FromTime(end)) |
|
|
|
|
if err != nil { |
|
|
|
|
return apiFuncResult{nil, &apiError{errorExec, err}, nil, nil} |
|
|
|
@ -762,7 +770,7 @@ func (api *API) labelValues(r *http.Request) (result apiFuncResult) {
|
|
|
|
|
var callWarnings annotations.Annotations |
|
|
|
|
labelValuesSet := make(map[string]struct{}) |
|
|
|
|
for _, matchers := range matcherSets { |
|
|
|
|
vals, callWarnings, err = q.LabelValues(ctx, name, matchers...) |
|
|
|
|
vals, callWarnings, err = q.LabelValues(ctx, name, hints, matchers...) |
|
|
|
|
if err != nil { |
|
|
|
|
return apiFuncResult{nil, &apiError{errorExec, err}, warnings, closer} |
|
|
|
|
} |
|
|
|
@ -781,7 +789,7 @@ func (api *API) labelValues(r *http.Request) (result apiFuncResult) {
|
|
|
|
|
if len(matcherSets) == 1 { |
|
|
|
|
matchers = matcherSets[0] |
|
|
|
|
} |
|
|
|
|
vals, warnings, err = q.LabelValues(ctx, name, matchers...) |
|
|
|
|
vals, warnings, err = q.LabelValues(ctx, name, hints, matchers...) |
|
|
|
|
if err != nil { |
|
|
|
|
return apiFuncResult{nil, &apiError{errorExec, err}, warnings, closer} |
|
|
|
|
} |
|
|
|
@ -793,7 +801,7 @@ func (api *API) labelValues(r *http.Request) (result apiFuncResult) {
|
|
|
|
|
|
|
|
|
|
slices.Sort(vals) |
|
|
|
|
|
|
|
|
|
if len(vals) > limit { |
|
|
|
|
if limit > 0 && len(vals) > limit { |
|
|
|
|
vals = vals[:limit] |
|
|
|
|
warnings = warnings.Add(errors.New("results truncated due to limit")) |
|
|
|
|
} |
|
|
|
@ -863,6 +871,7 @@ func (api *API) series(r *http.Request) (result apiFuncResult) {
|
|
|
|
|
Start: timestamp.FromTime(start), |
|
|
|
|
End: timestamp.FromTime(end), |
|
|
|
|
Func: "series", // There is no series function, this token is used for lookups that don't need samples.
|
|
|
|
|
Limit: toHintLimit(limit), |
|
|
|
|
} |
|
|
|
|
var set storage.SeriesSet |
|
|
|
|
|
|
|
|
@ -889,7 +898,7 @@ func (api *API) series(r *http.Request) (result apiFuncResult) {
|
|
|
|
|
} |
|
|
|
|
metrics = append(metrics, set.At().Labels()) |
|
|
|
|
|
|
|
|
|
if len(metrics) > limit { |
|
|
|
|
if limit > 0 && len(metrics) > limit { |
|
|
|
|
metrics = metrics[:limit] |
|
|
|
|
warnings.Add(errors.New("results truncated due to limit")) |
|
|
|
|
return apiFuncResult{metrics, nil, warnings, closer} |
|
|
|
@ -1898,8 +1907,8 @@ OUTER:
|
|
|
|
|
return matcherSets, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// parseLimitParam returning 0 means no limit is to be applied.
|
|
|
|
|
func parseLimitParam(limitStr string) (limit int, err error) { |
|
|
|
|
limit = math.MaxInt |
|
|
|
|
if limitStr == "" { |
|
|
|
|
return limit, nil |
|
|
|
|
} |
|
|
|
@ -1908,9 +1917,19 @@ func parseLimitParam(limitStr string) (limit int, err error) {
|
|
|
|
|
if err != nil { |
|
|
|
|
return limit, err |
|
|
|
|
} |
|
|
|
|
if limit <= 0 { |
|
|
|
|
return limit, errors.New("limit must be positive") |
|
|
|
|
if limit < 0 { |
|
|
|
|
return limit, errors.New("limit must be non-negative") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return limit, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// toHintLimit increases the API limit, as returned by parseLimitParam, by 1.
|
|
|
|
|
// This allows for emitting warnings when the results are truncated.
|
|
|
|
|
func toHintLimit(limit int) int { |
|
|
|
|
// 0 means no limit and avoid int overflow
|
|
|
|
|
if limit > 0 && limit < math.MaxInt { |
|
|
|
|
return limit + 1 |
|
|
|
|
} |
|
|
|
|
return limit |
|
|
|
|
} |
|
|
|
|