7
7
"net/http"
8
8
9
9
"github.com/go-kit/kit/log/level"
10
- "github.com/pkg/errors"
11
10
"github.com/prometheus/client_golang/prometheus"
12
11
"github.com/prometheus/client_golang/prometheus/promauto"
13
12
"github.com/prometheus/common/model"
@@ -22,11 +21,19 @@ import (
22
21
"github.com/cortexproject/cortex/pkg/util/validation"
23
22
)
24
23
25
- var (
26
- // ErrCardinalityExceeded is returned when the user reads a row that
27
- // is too large.
28
- ErrCardinalityExceeded = errors .New ("cardinality limit exceeded" )
24
+ // CardinalityExceededError is returned when the user reads a row that
25
+ // is too large.
26
+ type CardinalityExceededError struct {
27
+ MetricName , LabelName string
28
+ Size , Limit int32
29
+ }
30
+
31
+ func (e CardinalityExceededError ) Error () string {
32
+ return fmt .Sprintf ("cardinality limit exceeded for %s{%s}; %d entries, more than limit of %d" ,
33
+ e .MetricName , e .LabelName , e .Size , e .Limit )
34
+ }
29
35
36
+ var (
30
37
indexLookupsPerQuery = promauto .NewHistogram (prometheus.HistogramOpts {
31
38
Namespace : "cortex" ,
32
39
Name : "chunk_store_index_lookups_per_query" ,
@@ -196,6 +203,7 @@ func (c *seriesStore) lookupSeriesByMetricNameMatchers(ctx context.Context, from
196
203
var preIntersectionCount int
197
204
var lastErr error
198
205
var cardinalityExceededErrors int
206
+ var cardinalityExceededError CardinalityExceededError
199
207
for i := 0 ; i < len (matchers ); i ++ {
200
208
select {
201
209
case incoming := <- incomingIDs :
@@ -210,8 +218,9 @@ func (c *seriesStore) lookupSeriesByMetricNameMatchers(ctx context.Context, from
210
218
// series and the other returns only 10 (a few), we don't lookup the first one at all.
211
219
// We just manually filter through the 10 series again using "filterChunksByMatchers",
212
220
// saving us from looking up and intersecting a lot of series.
213
- if err == ErrCardinalityExceeded {
221
+ if e , ok := err .( CardinalityExceededError ); ok {
214
222
cardinalityExceededErrors ++
223
+ cardinalityExceededError = e
215
224
} else {
216
225
lastErr = err
217
226
}
@@ -220,7 +229,7 @@ func (c *seriesStore) lookupSeriesByMetricNameMatchers(ctx context.Context, from
220
229
221
230
// But if every single matcher returns a lot of series, then it makes sense to abort the query.
222
231
if cardinalityExceededErrors == len (matchers ) {
223
- return nil , ErrCardinalityExceeded
232
+ return nil , cardinalityExceededError
224
233
} else if lastErr != nil {
225
234
return nil , lastErr
226
235
}
@@ -241,11 +250,14 @@ func (c *seriesStore) lookupSeriesByMetricNameMatcher(ctx context.Context, from,
241
250
}
242
251
243
252
var queries []IndexQuery
253
+ var labelName string
244
254
if matcher == nil {
245
255
queries , err = c .schema .GetReadQueriesForMetric (from , through , userID , model .LabelValue (metricName ))
246
256
} else if matcher .Type != labels .MatchEqual {
257
+ labelName = matcher .Name
247
258
queries , err = c .schema .GetReadQueriesForMetricLabel (from , through , userID , model .LabelValue (metricName ), model .LabelName (matcher .Name ))
248
259
} else {
260
+ labelName = matcher .Name
249
261
queries , err = c .schema .GetReadQueriesForMetricLabelValue (from , through , userID , model .LabelValue (metricName ), model .LabelName (matcher .Name ), model .LabelValue (matcher .Value ))
250
262
}
251
263
if err != nil {
@@ -254,7 +266,11 @@ func (c *seriesStore) lookupSeriesByMetricNameMatcher(ctx context.Context, from,
254
266
level .Debug (log ).Log ("queries" , len (queries ))
255
267
256
268
entries , err := c .lookupEntriesByQueries (ctx , queries )
257
- if err != nil {
269
+ if e , ok := err .(CardinalityExceededError ); ok {
270
+ e .MetricName = metricName
271
+ e .LabelName = labelName
272
+ return nil , e
273
+ } else if err != nil {
258
274
return nil , err
259
275
}
260
276
level .Debug (log ).Log ("entries" , len (entries ))
0 commit comments