vendor: update cortex (#512)

Signed-off-by: Goutham Veeramachaneni <gouthamve@gmail.com>
pull/514/head
Goutham Veeramachaneni 6 years ago committed by GitHub
parent cfb4c60813
commit e54a1b21c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      Gopkg.lock
  2. 16
      pkg/ingester/flush.go
  3. 8
      pkg/ingester/stream.go
  4. 2
      pkg/logproto/dep.go
  5. 11
      pkg/util/conv.go
  6. 17
      vendor/github.com/cortexproject/cortex/pkg/chunk/chunk_store.go
  7. 3
      vendor/github.com/cortexproject/cortex/pkg/chunk/encoding/bigchunk.go
  8. 8
      vendor/github.com/cortexproject/cortex/pkg/chunk/gcp/bigtable_object_client.go
  9. 44
      vendor/github.com/cortexproject/cortex/pkg/chunk/series_store.go
  10. 2
      vendor/github.com/cortexproject/cortex/pkg/chunk/storage/bytes.go
  11. 15
      vendor/github.com/cortexproject/cortex/pkg/chunk/storage/caching_fixtures.go
  12. 41
      vendor/github.com/cortexproject/cortex/pkg/chunk/storage/caching_index_client.go
  13. 200
      vendor/github.com/cortexproject/cortex/pkg/chunk/storage/caching_index_client.pb.go
  14. 8
      vendor/github.com/cortexproject/cortex/pkg/chunk/storage/caching_index_client.proto
  15. 2
      vendor/github.com/cortexproject/cortex/pkg/chunk/storage/factory.go
  16. 111
      vendor/github.com/cortexproject/cortex/pkg/ingester/client/compat.go
  17. 919
      vendor/github.com/cortexproject/cortex/pkg/ingester/client/cortex.pb.go
  18. 10
      vendor/github.com/cortexproject/cortex/pkg/ingester/client/cortex.proto
  19. 20
      vendor/github.com/cortexproject/cortex/pkg/ingester/client/fnv.go
  20. 187
      vendor/github.com/cortexproject/cortex/pkg/ingester/client/timeseries.go
  21. 25
      vendor/github.com/cortexproject/cortex/pkg/ingester/index/index.go
  22. 209
      vendor/github.com/cortexproject/cortex/pkg/ring/ring.pb.go
  23. 10
      vendor/github.com/cortexproject/cortex/pkg/util/extract/extract.go
  24. 26
      vendor/github.com/cortexproject/cortex/pkg/util/flagext/deprecated.go
  25. 4
      vendor/github.com/cortexproject/cortex/pkg/util/hash_fp.go
  26. 14
      vendor/github.com/cortexproject/cortex/pkg/util/log.go
  27. 12
      vendor/github.com/cortexproject/cortex/pkg/util/validation/limits.go
  28. 26
      vendor/github.com/cortexproject/cortex/pkg/util/validation/override.go
  29. 13
      vendor/github.com/cortexproject/cortex/pkg/util/validation/validate.go

8
Gopkg.lock generated

@ -187,7 +187,7 @@
[[projects]] [[projects]]
branch = "lazy-load-chunks" branch = "lazy-load-chunks"
digest = "1:ec8e0308d1e557f50317a6437073a7a859d73e4cf8e4c20a60d7009e352353c6" digest = "1:bf1fa66c54722bc8664f1465e427cd6fe7df52f2b6fd5ab996baf37601687b70"
name = "github.com/cortexproject/cortex" name = "github.com/cortexproject/cortex"
packages = [ packages = [
"pkg/chunk", "pkg/chunk",
@ -211,10 +211,9 @@
"pkg/util/middleware", "pkg/util/middleware",
"pkg/util/spanlogger", "pkg/util/spanlogger",
"pkg/util/validation", "pkg/util/validation",
"pkg/util/wire",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "161f6716cba9a32f07f359c4f9f8578e0c5d5ae8" revision = "95a3f308e95617732b76e337874e83ccf173cf14"
source = "https://github.com/grafana/cortex" source = "https://github.com/grafana/cortex"
[[projects]] [[projects]]
@ -1367,7 +1366,6 @@
"github.com/cortexproject/cortex/pkg/util", "github.com/cortexproject/cortex/pkg/util",
"github.com/cortexproject/cortex/pkg/util/flagext", "github.com/cortexproject/cortex/pkg/util/flagext",
"github.com/cortexproject/cortex/pkg/util/validation", "github.com/cortexproject/cortex/pkg/util/validation",
"github.com/cortexproject/cortex/pkg/util/wire",
"github.com/fatih/color", "github.com/fatih/color",
"github.com/go-kit/kit/log", "github.com/go-kit/kit/log",
"github.com/go-kit/kit/log/level", "github.com/go-kit/kit/log/level",
@ -1391,10 +1389,12 @@
"github.com/prometheus/prometheus/discovery/targetgroup", "github.com/prometheus/prometheus/discovery/targetgroup",
"github.com/prometheus/prometheus/pkg/labels", "github.com/prometheus/prometheus/pkg/labels",
"github.com/prometheus/prometheus/pkg/relabel", "github.com/prometheus/prometheus/pkg/relabel",
"github.com/prometheus/prometheus/pkg/textparse",
"github.com/prometheus/prometheus/relabel", "github.com/prometheus/prometheus/relabel",
"github.com/stretchr/testify/assert", "github.com/stretchr/testify/assert",
"github.com/stretchr/testify/require", "github.com/stretchr/testify/require",
"github.com/weaveworks/common/httpgrpc", "github.com/weaveworks/common/httpgrpc",
"github.com/weaveworks/common/httpgrpc/server",
"github.com/weaveworks/common/middleware", "github.com/weaveworks/common/middleware",
"github.com/weaveworks/common/server", "github.com/weaveworks/common/server",
"github.com/weaveworks/common/tracing", "github.com/weaveworks/common/tracing",

@ -184,7 +184,7 @@ func (i *Ingester) flushUserSeries(userID string, fp model.Fingerprint, immediat
return nil return nil
} }
func (i *Ingester) collectChunksToFlush(instance *instance, fp model.Fingerprint, immediate bool) ([]*chunkDesc, []client.LabelPair) { func (i *Ingester) collectChunksToFlush(instance *instance, fp model.Fingerprint, immediate bool) ([]*chunkDesc, []client.LabelAdapter) {
instance.streamsMtx.Lock() instance.streamsMtx.Lock()
defer instance.streamsMtx.Unlock() defer instance.streamsMtx.Unlock()
@ -234,18 +234,18 @@ func (i *Ingester) removeFlushedChunks(instance *instance, stream *stream) {
if len(stream.chunks) == 0 { if len(stream.chunks) == 0 {
delete(instance.streams, stream.fp) delete(instance.streams, stream.fp)
instance.index.Delete(client.FromLabelPairsToLabels(stream.labels), stream.fp) instance.index.Delete(client.FromLabelAdaptersToLabels(stream.labels), stream.fp)
instance.streamsRemovedTotal.Inc() instance.streamsRemovedTotal.Inc()
} }
} }
func (i *Ingester) flushChunks(ctx context.Context, fp model.Fingerprint, labelPairs []client.LabelPair, cs []*chunkDesc) error { func (i *Ingester) flushChunks(ctx context.Context, fp model.Fingerprint, labelPairs []client.LabelAdapter, cs []*chunkDesc) error {
userID, err := user.ExtractOrgID(ctx) userID, err := user.ExtractOrgID(ctx)
if err != nil { if err != nil {
return err return err
} }
metric := fromLabelPairs(labelPairs) metric := client.FromLabelAdaptersToMetric(labelPairs)
metric[nameLabel] = logsValue metric[nameLabel] = logsValue
wireChunks := make([]chunk.Chunk, 0, len(cs)) wireChunks := make([]chunk.Chunk, 0, len(cs))
@ -288,11 +288,3 @@ func (i *Ingester) flushChunks(ctx context.Context, fp model.Fingerprint, labelP
return nil return nil
} }
func fromLabelPairs(ls []client.LabelPair) model.Metric {
m := make(model.Metric, len(ls))
for _, l := range ls {
m[model.LabelName(l.Name)] = model.LabelValue(l.Value)
}
return m
}

@ -47,7 +47,7 @@ type stream struct {
// Not thread-safe; assume accesses to this are locked by caller. // Not thread-safe; assume accesses to this are locked by caller.
chunks []chunkDesc chunks []chunkDesc
fp model.Fingerprint fp model.Fingerprint
labels []client.LabelPair labels []client.LabelAdapter
} }
type chunkDesc struct { type chunkDesc struct {
@ -58,7 +58,7 @@ type chunkDesc struct {
lastUpdated time.Time lastUpdated time.Time
} }
func newStream(fp model.Fingerprint, labels []client.LabelPair) *stream { func newStream(fp model.Fingerprint, labels []client.LabelAdapter) *stream {
return &stream{ return &stream{
fp: fp, fp: fp,
labels: labels, labels: labels,
@ -96,7 +96,7 @@ func (s *stream) Push(_ context.Context, entries []logproto.Entry) error {
} }
if appendErr == chunkenc.ErrOutOfOrder { if appendErr == chunkenc.ErrOutOfOrder {
return httpgrpc.Errorf(http.StatusBadRequest, "entry out of order for stream: %s", client.FromLabelPairsToLabels(s.labels).String()) return httpgrpc.Errorf(http.StatusBadRequest, "entry out of order for stream: %s", client.FromLabelAdaptersToLabels(s.labels).String())
} }
return appendErr return appendErr
@ -121,5 +121,5 @@ func (s *stream) Iterator(from, through time.Time, direction logproto.Direction)
} }
} }
return iter.NewNonOverlappingIterator(iterators, client.FromLabelPairsToLabels(s.labels).String()), nil return iter.NewNonOverlappingIterator(iterators, client.FromLabelAdaptersToLabels(s.labels).String()), nil
} }

@ -2,6 +2,6 @@ package logproto
import ( import (
// trick dep into including this, needed by the generated code. // trick dep into including this, needed by the generated code.
_ "github.com/cortexproject/cortex/pkg/util/wire" _ "github.com/cortexproject/cortex/pkg/chunk/storage"
_ "github.com/gogo/protobuf/types" _ "github.com/gogo/protobuf/types"
) )

@ -2,22 +2,21 @@ package util
import ( import (
"github.com/cortexproject/cortex/pkg/ingester/client" "github.com/cortexproject/cortex/pkg/ingester/client"
"github.com/cortexproject/cortex/pkg/util/wire"
"github.com/grafana/loki/pkg/parser" "github.com/grafana/loki/pkg/parser"
) )
// ToClientLabels parses the labels and converts them to the Cortex type. // ToClientLabels parses the labels and converts them to the Cortex type.
func ToClientLabels(labels string) ([]client.LabelPair, error) { func ToClientLabels(labels string) ([]client.LabelAdapter, error) {
ls, err := parser.Labels(labels) ls, err := parser.Labels(labels)
if err != nil { if err != nil {
return nil, err return nil, err
} }
pairs := make([]client.LabelPair, 0, len(ls)) pairs := make([]client.LabelAdapter, 0, len(ls))
for i := 0; i < len(ls); i++ { for i := 0; i < len(ls); i++ {
pairs = append(pairs, client.LabelPair{ pairs = append(pairs, client.LabelAdapter{
Name: wire.Bytes(ls[i].Name), Name: ls[i].Name,
Value: wire.Bytes(ls[i].Value), Value: ls[i].Value,
}) })
} }
return pairs, nil return pairs, nil

@ -20,6 +20,7 @@ import (
"github.com/cortexproject/cortex/pkg/chunk/cache" "github.com/cortexproject/cortex/pkg/chunk/cache"
"github.com/cortexproject/cortex/pkg/util" "github.com/cortexproject/cortex/pkg/util"
"github.com/cortexproject/cortex/pkg/util/extract" "github.com/cortexproject/cortex/pkg/util/extract"
"github.com/cortexproject/cortex/pkg/util/flagext"
"github.com/cortexproject/cortex/pkg/util/spanlogger" "github.com/cortexproject/cortex/pkg/util/spanlogger"
"github.com/cortexproject/cortex/pkg/util/validation" "github.com/cortexproject/cortex/pkg/util/validation"
"github.com/weaveworks/common/httpgrpc" "github.com/weaveworks/common/httpgrpc"
@ -58,25 +59,21 @@ type StoreConfig struct {
ChunkCacheConfig cache.Config ChunkCacheConfig cache.Config
WriteDedupeCacheConfig cache.Config WriteDedupeCacheConfig cache.Config
MinChunkAge time.Duration MinChunkAge time.Duration
CardinalityCacheSize int
CardinalityCacheValidity time.Duration
CardinalityLimit int
CacheLookupsOlderThan time.Duration CacheLookupsOlderThan time.Duration
} }
// RegisterFlags adds the flags required to config this to the given FlagSet // RegisterFlags adds the flags required to config this to the given FlagSet
func (cfg *StoreConfig) RegisterFlags(f *flag.FlagSet) { func (cfg *StoreConfig) RegisterFlags(f *flag.FlagSet) {
cfg.ChunkCacheConfig.RegisterFlagsWithPrefix("", "Cache config for chunks. ", f) cfg.ChunkCacheConfig.RegisterFlagsWithPrefix("", "Cache config for chunks. ", f)
cfg.WriteDedupeCacheConfig.RegisterFlagsWithPrefix("store.index-cache-write.", "Cache config for index entry writing. ", f) cfg.WriteDedupeCacheConfig.RegisterFlagsWithPrefix("store.index-cache-write.", "Cache config for index entry writing. ", f)
f.DurationVar(&cfg.MinChunkAge, "store.min-chunk-age", 0, "Minimum time between chunk update and being saved to the store.") f.DurationVar(&cfg.MinChunkAge, "store.min-chunk-age", 0, "Minimum time between chunk update and being saved to the store.")
f.IntVar(&cfg.CardinalityCacheSize, "store.cardinality-cache-size", 0, "Size of in-memory cardinality cache, 0 to disable.")
f.DurationVar(&cfg.CardinalityCacheValidity, "store.cardinality-cache-validity", 1*time.Hour, "Period for which entries in the cardinality cache are valid.")
f.IntVar(&cfg.CardinalityLimit, "store.cardinality-limit", 1e5, "Cardinality limit for index queries.")
f.DurationVar(&cfg.CacheLookupsOlderThan, "store.cache-lookups-older-than", 0, "Cache index entries older than this period. 0 to disable.") f.DurationVar(&cfg.CacheLookupsOlderThan, "store.cache-lookups-older-than", 0, "Cache index entries older than this period. 0 to disable.")
// Deprecated.
flagext.DeprecatedFlag(f, "store.cardinality-cache-size", "DEPRECATED. Use store.index-cache-size.enable-fifocache and store.cardinality-cache.fifocache.size instead.")
flagext.DeprecatedFlag(f, "store.cardinality-cache-validity", "DEPRECATED. Use store.index-cache-size.enable-fifocache and store.cardinality-cache.fifocache.duration instead.")
} }
// store implements Store // store implements Store
@ -211,7 +208,7 @@ func (c *store) validateQuery(ctx context.Context, from model.Time, through *mod
maxQueryLength := c.limits.MaxQueryLength(userID) maxQueryLength := c.limits.MaxQueryLength(userID)
if maxQueryLength > 0 && (*through).Sub(from) > maxQueryLength { if maxQueryLength > 0 && (*through).Sub(from) > maxQueryLength {
return "", nil, false, httpgrpc.Errorf(http.StatusBadRequest, "invalid query, length > limit (%s > %s)", (*through).Sub(from), maxQueryLength) return "", nil, false, httpgrpc.Errorf(http.StatusBadRequest, validation.ErrQueryTooLong, (*through).Sub(from), maxQueryLength)
} }
now := model.Now() now := model.Now()

@ -161,8 +161,9 @@ func (b *bigchunk) Len() int {
} }
func (b *bigchunk) Size() int { func (b *bigchunk) Size() int {
sum := 0 sum := 2 // For the number of sub chunks.
for _, c := range b.chunks { for _, c := range b.chunks {
sum += 2 // For the length of the sub chunk.
sum += len(c.Bytes()) sum += len(c.Bytes())
} }
return sum return sum

@ -114,7 +114,7 @@ func (s *bigtableObjectClient) GetChunks(ctx context.Context, input []chunk.Chun
decodeContext := chunk.NewDecodeContext() decodeContext := chunk.NewDecodeContext()
var processingErr error var processingErr error
var recievedChunks = 0 var receivedChunks = 0
// rows are returned in key order, not order in row list // rows are returned in key order, not order in row list
err := table.ReadRows(ctx, page, func(row bigtable.Row) bool { err := table.ReadRows(ctx, page, func(row bigtable.Row) bool {
@ -130,7 +130,7 @@ func (s *bigtableObjectClient) GetChunks(ctx context.Context, input []chunk.Chun
return false return false
} }
recievedChunks++ receivedChunks++
outs <- chunk outs <- chunk
return true return true
}) })
@ -139,8 +139,8 @@ func (s *bigtableObjectClient) GetChunks(ctx context.Context, input []chunk.Chun
errs <- processingErr errs <- processingErr
} else if err != nil { } else if err != nil {
errs <- errors.WithStack(err) errs <- errors.WithStack(err)
} else if recievedChunks < len(page) { } else if receivedChunks < len(page) {
errs <- errors.WithStack(fmt.Errorf("Asked for %d chunks for Bigtable, received %d", len(page), recievedChunks)) errs <- errors.WithStack(fmt.Errorf("Asked for %d chunks for Bigtable, received %d", len(page), receivedChunks))
} }
}(page) }(page)
} }

@ -23,7 +23,9 @@ import (
) )
var ( var (
errCardinalityExceeded = errors.New("cardinality limit exceeded") // ErrCardinalityExceeded is returned when the user reads a row that
// is too large.
ErrCardinalityExceeded = errors.New("cardinality limit exceeded")
indexLookupsPerQuery = promauto.NewHistogram(prometheus.HistogramOpts{ indexLookupsPerQuery = promauto.NewHistogram(prometheus.HistogramOpts{
Namespace: "cortex", Namespace: "cortex",
@ -57,8 +59,6 @@ var (
// seriesStore implements Store // seriesStore implements Store
type seriesStore struct { type seriesStore struct {
store store
cardinalityCache *cache.FifoCache
writeDedupeCache cache.Cache writeDedupeCache cache.Cache
} }
@ -89,10 +89,6 @@ func newSeriesStore(cfg StoreConfig, schema Schema, index IndexClient, chunks Ob
limits: limits, limits: limits,
Fetcher: fetcher, Fetcher: fetcher,
}, },
cardinalityCache: cache.NewFifoCache("cardinality", cache.FifoCacheConfig{
Size: cfg.CardinalityCacheSize,
Validity: cfg.CardinalityCacheValidity,
}),
writeDedupeCache: writeDedupeCache, writeDedupeCache: writeDedupeCache,
}, nil }, nil
} }
@ -229,15 +225,21 @@ func (c *seriesStore) lookupSeriesByMetricNameMatchers(ctx context.Context, from
ids = intersectStrings(ids, incoming) ids = intersectStrings(ids, incoming)
} }
case err := <-incomingErrors: case err := <-incomingErrors:
if err == errCardinalityExceeded { // The idea is that if we have 2 matchers, and if one returns a lot of
// series and the other returns only 10 (a few), we don't lookup the first one at all.
// We just manually filter through the 10 series again using "filterChunksByMatchers",
// saving us from looking up and intersecting a lot of series.
if err == ErrCardinalityExceeded {
cardinalityExceededErrors++ cardinalityExceededErrors++
} else { } else {
lastErr = err lastErr = err
} }
} }
} }
// But if every single matcher returns a lot of series, then it makes sense to abort the query.
if cardinalityExceededErrors == len(matchers) { if cardinalityExceededErrors == len(matchers) {
return nil, errCardinalityExceeded return nil, ErrCardinalityExceeded
} else if lastErr != nil { } else if lastErr != nil {
return nil, lastErr return nil, lastErr
} }
@ -270,36 +272,12 @@ func (c *seriesStore) lookupSeriesByMetricNameMatcher(ctx context.Context, from,
} }
level.Debug(log).Log("queries", len(queries)) level.Debug(log).Log("queries", len(queries))
for _, query := range queries {
value, ok := c.cardinalityCache.Get(ctx, query.HashValue)
if !ok {
continue
}
cardinality := value.(int)
if cardinality > c.cfg.CardinalityLimit {
return nil, errCardinalityExceeded
}
}
entries, err := c.lookupEntriesByQueries(ctx, queries) entries, err := c.lookupEntriesByQueries(ctx, queries)
if err != nil { if err != nil {
return nil, err return nil, err
} }
level.Debug(log).Log("entries", len(entries)) level.Debug(log).Log("entries", len(entries))
// TODO This is not correct, will overcount for queries > 24hrs
keys := make([]string, 0, len(queries))
values := make([]interface{}, 0, len(queries))
for _, query := range queries {
keys = append(keys, query.HashValue)
values = append(values, len(entries))
}
c.cardinalityCache.Put(ctx, keys, values)
if len(entries) > c.cfg.CardinalityLimit {
return nil, errCardinalityExceeded
}
ids, err := c.parseIndexEntries(ctx, entries, matcher) ids, err := c.parseIndexEntries(ctx, entries, matcher)
if err != nil { if err != nil {
return nil, err return nil, err

@ -3,6 +3,9 @@ package storage
import ( import (
"time" "time"
"github.com/cortexproject/cortex/pkg/util/flagext"
"github.com/cortexproject/cortex/pkg/util/validation"
"github.com/cortexproject/cortex/pkg/chunk/cache" "github.com/cortexproject/cortex/pkg/chunk/cache"
"github.com/cortexproject/cortex/pkg/chunk/gcp" "github.com/cortexproject/cortex/pkg/chunk/gcp"
@ -16,11 +19,15 @@ type fixture struct {
func (f fixture) Name() string { return "caching-store" } func (f fixture) Name() string { return "caching-store" }
func (f fixture) Clients() (chunk.IndexClient, chunk.ObjectClient, chunk.TableClient, chunk.SchemaConfig, error) { func (f fixture) Clients() (chunk.IndexClient, chunk.ObjectClient, chunk.TableClient, chunk.SchemaConfig, error) {
limits, err := defaultLimits()
if err != nil {
return nil, nil, nil, chunk.SchemaConfig{}, err
}
indexClient, objectClient, tableClient, schemaConfig, err := f.fixture.Clients() indexClient, objectClient, tableClient, schemaConfig, err := f.fixture.Clients()
indexClient = newCachingIndexClient(indexClient, cache.NewFifoCache("index-fifo", cache.FifoCacheConfig{ indexClient = newCachingIndexClient(indexClient, cache.NewFifoCache("index-fifo", cache.FifoCacheConfig{
Size: 500, Size: 500,
Validity: 5 * time.Minute, Validity: 5 * time.Minute,
}), 5*time.Minute) }), 5*time.Minute, limits)
return indexClient, objectClient, tableClient, schemaConfig, err return indexClient, objectClient, tableClient, schemaConfig, err
} }
func (f fixture) Teardown() error { return f.fixture.Teardown() } func (f fixture) Teardown() error { return f.fixture.Teardown() }
@ -29,3 +36,9 @@ func (f fixture) Teardown() error { return f.fixture.Teardown() }
var Fixtures = []testutils.Fixture{ var Fixtures = []testutils.Fixture{
fixture{gcp.Fixtures[0]}, fixture{gcp.Fixtures[0]},
} }
func defaultLimits() (*validation.Overrides, error) {
var defaults validation.Limits
flagext.DefaultValues(&defaults)
return validation.NewOverrides(defaults)
}

@ -5,15 +5,18 @@ import (
"sync" "sync"
"time" "time"
"github.com/go-kit/kit/log/level"
proto "github.com/golang/protobuf/proto"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/weaveworks/common/user"
"github.com/cortexproject/cortex/pkg/chunk" "github.com/cortexproject/cortex/pkg/chunk"
"github.com/cortexproject/cortex/pkg/chunk/cache" "github.com/cortexproject/cortex/pkg/chunk/cache"
chunk_util "github.com/cortexproject/cortex/pkg/chunk/util" chunk_util "github.com/cortexproject/cortex/pkg/chunk/util"
"github.com/cortexproject/cortex/pkg/util" "github.com/cortexproject/cortex/pkg/util"
"github.com/cortexproject/cortex/pkg/util/spanlogger" "github.com/cortexproject/cortex/pkg/util/spanlogger"
"github.com/go-kit/kit/log/level" "github.com/cortexproject/cortex/pkg/util/validation"
proto "github.com/golang/protobuf/proto"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
) )
var ( var (
@ -43,9 +46,10 @@ type cachingIndexClient struct {
chunk.IndexClient chunk.IndexClient
cache cache.Cache cache cache.Cache
validity time.Duration validity time.Duration
limits *validation.Overrides
} }
func newCachingIndexClient(client chunk.IndexClient, c cache.Cache, validity time.Duration) chunk.IndexClient { func newCachingIndexClient(client chunk.IndexClient, c cache.Cache, validity time.Duration, limits *validation.Overrides) chunk.IndexClient {
if c == nil { if c == nil {
return client return client
} }
@ -54,6 +58,7 @@ func newCachingIndexClient(client chunk.IndexClient, c cache.Cache, validity tim
IndexClient: client, IndexClient: client,
cache: cache.NewSnappy(c), cache: cache.NewSnappy(c),
validity: validity, validity: validity,
limits: limits,
} }
} }
@ -65,6 +70,12 @@ func (s *cachingIndexClient) QueryPages(ctx context.Context, queries []chunk.Ind
// We cache the entire row, so filter client side. // We cache the entire row, so filter client side.
callback = chunk_util.QueryFilter(callback) callback = chunk_util.QueryFilter(callback)
userID, err := user.ExtractOrgID(ctx)
if err != nil {
return err
}
cardinalityLimit := int32(s.limits.CardinalityLimit(userID))
// Build list of keys to lookup in the cache. // Build list of keys to lookup in the cache.
keys := make([]string, 0, len(queries)) keys := make([]string, 0, len(queries))
queriesByKey := make(map[string][]chunk.IndexQuery, len(queries)) queriesByKey := make(map[string][]chunk.IndexQuery, len(queries))
@ -76,6 +87,10 @@ func (s *cachingIndexClient) QueryPages(ctx context.Context, queries []chunk.Ind
batches, misses := s.cacheFetch(ctx, keys) batches, misses := s.cacheFetch(ctx, keys)
for _, batch := range batches { for _, batch := range batches {
if cardinalityLimit > 0 && batch.Cardinality > cardinalityLimit {
return chunk.ErrCardinalityExceeded
}
queries := queriesByKey[batch.Key] queries := queriesByKey[batch.Key]
for _, query := range queries { for _, query := range queries {
callback(query, batch) callback(query, batch)
@ -115,7 +130,7 @@ func (s *cachingIndexClient) QueryPages(ctx context.Context, queries []chunk.Ind
results[key] = rb results[key] = rb
} }
err := s.IndexClient.QueryPages(ctx, cacheableMissed, func(cacheableQuery chunk.IndexQuery, r chunk.ReadBatch) bool { err = s.IndexClient.QueryPages(ctx, cacheableMissed, func(cacheableQuery chunk.IndexQuery, r chunk.ReadBatch) bool {
resultsMtx.Lock() resultsMtx.Lock()
defer resultsMtx.Unlock() defer resultsMtx.Unlock()
key := queryKey(cacheableQuery) key := queryKey(cacheableQuery)
@ -135,9 +150,20 @@ func (s *cachingIndexClient) QueryPages(ctx context.Context, queries []chunk.Ind
defer resultsMtx.Unlock() defer resultsMtx.Unlock()
keys := make([]string, 0, len(results)) keys := make([]string, 0, len(results))
batches := make([]ReadBatch, 0, len(results)) batches := make([]ReadBatch, 0, len(results))
var cardinalityErr error
for key, batch := range results { for key, batch := range results {
cardinality := int32(len(batch.Entries))
if cardinalityLimit > 0 && cardinality > cardinalityLimit {
batch.Cardinality = cardinality
batch.Entries = nil
cardinalityErr = chunk.ErrCardinalityExceeded
}
keys = append(keys, key) keys = append(keys, key)
batches = append(batches, batch) batches = append(batches, batch)
if cardinalityErr != nil {
continue
}
queries := queriesByKey[key] queries := queriesByKey[key]
for _, query := range queries { for _, query := range queries {
@ -145,8 +171,8 @@ func (s *cachingIndexClient) QueryPages(ctx context.Context, queries []chunk.Ind
} }
} }
s.cacheStore(ctx, keys, batches) s.cacheStore(ctx, keys, batches)
return cardinalityErr
} }
return nil
} }
// Iterator implements chunk.ReadBatch. // Iterator implements chunk.ReadBatch.
@ -250,7 +276,6 @@ func (s *cachingIndexClient) cacheFetch(ctx context.Context, keys []string) (bat
} }
if readBatch.Expiry != 0 && time.Now().After(time.Unix(0, readBatch.Expiry)) { if readBatch.Expiry != 0 && time.Now().After(time.Unix(0, readBatch.Expiry)) {
level.Debug(log).Log("msg", "dropping index cache entry due to expiration", "key", key, "readBatch.Key", readBatch.Key, "expiry", time.Unix(0, readBatch.Expiry))
continue continue
} }

@ -3,17 +3,15 @@
package storage package storage
import proto "github.com/gogo/protobuf/proto" import (
import fmt "fmt" fmt "fmt"
import math "math" _ "github.com/gogo/protobuf/gogoproto"
import _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto"
io "io"
import github_com_cortexproject_cortex_pkg_util_wire "github.com/cortexproject/cortex/pkg/util/wire" math "math"
reflect "reflect"
import strings "strings" strings "strings"
import reflect "reflect" )
import io "io"
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
@ -27,14 +25,14 @@ var _ = math.Inf
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type Entry struct { type Entry struct {
Column github_com_cortexproject_cortex_pkg_util_wire.Bytes `protobuf:"bytes,1,opt,name=Column,json=column,proto3,customtype=github.com/cortexproject/cortex/pkg/util/wire.Bytes" json:"Column"` Column Bytes `protobuf:"bytes,1,opt,name=Column,json=column,proto3,customtype=Bytes" json:"Column"`
Value github_com_cortexproject_cortex_pkg_util_wire.Bytes `protobuf:"bytes,2,opt,name=Value,json=value,proto3,customtype=github.com/cortexproject/cortex/pkg/util/wire.Bytes" json:"Value"` Value Bytes `protobuf:"bytes,2,opt,name=Value,json=value,proto3,customtype=Bytes" json:"Value"`
} }
func (m *Entry) Reset() { *m = Entry{} } func (m *Entry) Reset() { *m = Entry{} }
func (*Entry) ProtoMessage() {} func (*Entry) ProtoMessage() {}
func (*Entry) Descriptor() ([]byte, []int) { func (*Entry) Descriptor() ([]byte, []int) {
return fileDescriptor_caching_index_client_2f4bf220288f700f, []int{0} return fileDescriptor_a60039d4a2d816f6, []int{0}
} }
func (m *Entry) XXX_Unmarshal(b []byte) error { func (m *Entry) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -51,8 +49,8 @@ func (m *Entry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return b[:n], nil return b[:n], nil
} }
} }
func (dst *Entry) XXX_Merge(src proto.Message) { func (m *Entry) XXX_Merge(src proto.Message) {
xxx_messageInfo_Entry.Merge(dst, src) xxx_messageInfo_Entry.Merge(m, src)
} }
func (m *Entry) XXX_Size() int { func (m *Entry) XXX_Size() int {
return m.Size() return m.Size()
@ -64,16 +62,19 @@ func (m *Entry) XXX_DiscardUnknown() {
var xxx_messageInfo_Entry proto.InternalMessageInfo var xxx_messageInfo_Entry proto.InternalMessageInfo
type ReadBatch struct { type ReadBatch struct {
Entries []Entry `protobuf:"bytes,1,rep,name=entries" json:"entries"` Entries []Entry `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries"`
Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"` Key string `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
// The time at which the key expires. // The time at which the key expires.
Expiry int64 `protobuf:"varint,3,opt,name=expiry,proto3" json:"expiry,omitempty"` Expiry int64 `protobuf:"varint,3,opt,name=expiry,proto3" json:"expiry,omitempty"`
// The number of entries; used for cardinality limiting.
// entries will be empty when this is set.
Cardinality int32 `protobuf:"varint,4,opt,name=cardinality,proto3" json:"cardinality,omitempty"`
} }
func (m *ReadBatch) Reset() { *m = ReadBatch{} } func (m *ReadBatch) Reset() { *m = ReadBatch{} }
func (*ReadBatch) ProtoMessage() {} func (*ReadBatch) ProtoMessage() {}
func (*ReadBatch) Descriptor() ([]byte, []int) { func (*ReadBatch) Descriptor() ([]byte, []int) {
return fileDescriptor_caching_index_client_2f4bf220288f700f, []int{1} return fileDescriptor_a60039d4a2d816f6, []int{1}
} }
func (m *ReadBatch) XXX_Unmarshal(b []byte) error { func (m *ReadBatch) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -90,8 +91,8 @@ func (m *ReadBatch) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return b[:n], nil return b[:n], nil
} }
} }
func (dst *ReadBatch) XXX_Merge(src proto.Message) { func (m *ReadBatch) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReadBatch.Merge(dst, src) xxx_messageInfo_ReadBatch.Merge(m, src)
} }
func (m *ReadBatch) XXX_Size() int { func (m *ReadBatch) XXX_Size() int {
return m.Size() return m.Size()
@ -123,10 +124,47 @@ func (m *ReadBatch) GetExpiry() int64 {
return 0 return 0
} }
func (m *ReadBatch) GetCardinality() int32 {
if m != nil {
return m.Cardinality
}
return 0
}
func init() { func init() {
proto.RegisterType((*Entry)(nil), "storage.Entry") proto.RegisterType((*Entry)(nil), "storage.Entry")
proto.RegisterType((*ReadBatch)(nil), "storage.ReadBatch") proto.RegisterType((*ReadBatch)(nil), "storage.ReadBatch")
} }
func init() {
proto.RegisterFile("github.com/cortexproject/cortex/pkg/chunk/storage/caching_index_client.proto", fileDescriptor_a60039d4a2d816f6)
}
var fileDescriptor_a60039d4a2d816f6 = []byte{
// 335 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xb1, 0x4e, 0xc3, 0x30,
0x00, 0x44, 0x63, 0xd2, 0xa4, 0xaa, 0x0b, 0x08, 0x65, 0x40, 0x11, 0x83, 0x1b, 0x15, 0x21, 0x65,
0x21, 0x91, 0x80, 0x2f, 0x08, 0x62, 0x63, 0x0a, 0x12, 0x6b, 0xe5, 0xba, 0x26, 0x31, 0x4d, 0xed,
0xc8, 0x75, 0x50, 0xb3, 0xb1, 0xb1, 0xf2, 0x19, 0x7c, 0x4a, 0xc7, 0x8e, 0x15, 0x43, 0x45, 0xdd,
0x85, 0xb1, 0x9f, 0x80, 0x6a, 0x82, 0xd4, 0x81, 0xed, 0x9e, 0xef, 0x7c, 0x67, 0x19, 0xde, 0x67,
0x4c, 0xe5, 0xd5, 0x30, 0x22, 0x62, 0x12, 0x13, 0x21, 0x15, 0x9d, 0x95, 0x52, 0x3c, 0x53, 0xa2,
0x1a, 0x8a, 0xcb, 0x71, 0x16, 0x93, 0xbc, 0xe2, 0xe3, 0x78, 0xaa, 0x84, 0xc4, 0x19, 0x8d, 0x09,
0x26, 0x39, 0xe3, 0xd9, 0x80, 0xf1, 0x11, 0x9d, 0x0d, 0x48, 0xc1, 0x28, 0x57, 0x51, 0x29, 0x85,
0x12, 0x5e, 0xbb, 0xc9, 0x9c, 0x5d, 0xee, 0xd5, 0x66, 0x22, 0x13, 0xb1, 0xf1, 0x87, 0xd5, 0x93,
0x21, 0x03, 0x46, 0xfd, 0xde, 0xeb, 0x3f, 0x40, 0xe7, 0x8e, 0x2b, 0x59, 0x7b, 0x17, 0xd0, 0xbd,
0x15, 0x45, 0x35, 0xe1, 0x3e, 0x08, 0x40, 0x78, 0x98, 0x1c, 0xcd, 0x57, 0x3d, 0xeb, 0x73, 0xd5,
0x73, 0x92, 0x5a, 0xd1, 0x69, 0xea, 0x12, 0x63, 0x7a, 0xe7, 0xd0, 0x79, 0xc4, 0x45, 0x45, 0xfd,
0x83, 0xff, 0x52, 0xce, 0xcb, 0xce, 0xeb, 0xbf, 0x01, 0xd8, 0x49, 0x29, 0x1e, 0x25, 0x58, 0x91,
0xdc, 0x8b, 0x60, 0x9b, 0x72, 0x25, 0x19, 0x9d, 0xfa, 0x20, 0xb0, 0xc3, 0xee, 0xd5, 0x71, 0xd4,
0x3c, 0x36, 0x32, 0xd3, 0x49, 0x6b, 0x57, 0x92, 0xfe, 0x85, 0xbc, 0x13, 0x68, 0x8f, 0x69, 0x6d,
0x06, 0x3a, 0xe9, 0x4e, 0x7a, 0xa7, 0xd0, 0xa5, 0xb3, 0x92, 0xc9, 0xda, 0xb7, 0x03, 0x10, 0xda,
0x69, 0x43, 0x5e, 0x00, 0xbb, 0x04, 0xcb, 0x11, 0xe3, 0xb8, 0x60, 0xaa, 0xf6, 0x5b, 0x01, 0x08,
0x9d, 0x74, 0xff, 0x28, 0xb9, 0x59, 0xac, 0x91, 0xb5, 0x5c, 0x23, 0x6b, 0xbb, 0x46, 0xe0, 0x55,
0x23, 0xf0, 0xa1, 0x11, 0x98, 0x6b, 0x04, 0x16, 0x1a, 0x81, 0x2f, 0x8d, 0xc0, 0xb7, 0x46, 0xd6,
0x56, 0x23, 0xf0, 0xbe, 0x41, 0xd6, 0x62, 0x83, 0xac, 0xe5, 0x06, 0x59, 0x43, 0xd7, 0xfc, 0xcd,
0xf5, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4b, 0xd2, 0x5d, 0xd9, 0xa3, 0x01, 0x00, 0x00,
}
func (this *Entry) Equal(that interface{}) bool { func (this *Entry) Equal(that interface{}) bool {
if that == nil { if that == nil {
return this == nil return this == nil
@ -187,6 +225,9 @@ func (this *ReadBatch) Equal(that interface{}) bool {
if this.Expiry != that1.Expiry { if this.Expiry != that1.Expiry {
return false return false
} }
if this.Cardinality != that1.Cardinality {
return false
}
return true return true
} }
func (this *Entry) GoString() string { func (this *Entry) GoString() string {
@ -204,7 +245,7 @@ func (this *ReadBatch) GoString() string {
if this == nil { if this == nil {
return "nil" return "nil"
} }
s := make([]string, 0, 7) s := make([]string, 0, 8)
s = append(s, "&storage.ReadBatch{") s = append(s, "&storage.ReadBatch{")
if this.Entries != nil { if this.Entries != nil {
vs := make([]*Entry, len(this.Entries)) vs := make([]*Entry, len(this.Entries))
@ -215,6 +256,7 @@ func (this *ReadBatch) GoString() string {
} }
s = append(s, "Key: "+fmt.Sprintf("%#v", this.Key)+",\n") s = append(s, "Key: "+fmt.Sprintf("%#v", this.Key)+",\n")
s = append(s, "Expiry: "+fmt.Sprintf("%#v", this.Expiry)+",\n") s = append(s, "Expiry: "+fmt.Sprintf("%#v", this.Expiry)+",\n")
s = append(s, "Cardinality: "+fmt.Sprintf("%#v", this.Cardinality)+",\n")
s = append(s, "}") s = append(s, "}")
return strings.Join(s, "") return strings.Join(s, "")
} }
@ -244,17 +286,17 @@ func (m *Entry) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa dAtA[i] = 0xa
i++ i++
i = encodeVarintCachingIndexClient(dAtA, i, uint64(m.Column.Size())) i = encodeVarintCachingIndexClient(dAtA, i, uint64(m.Column.Size()))
n1, err := m.Column.MarshalTo(dAtA[i:]) n1, err1 := m.Column.MarshalTo(dAtA[i:])
if err != nil { if err1 != nil {
return 0, err return 0, err1
} }
i += n1 i += n1
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintCachingIndexClient(dAtA, i, uint64(m.Value.Size())) i = encodeVarintCachingIndexClient(dAtA, i, uint64(m.Value.Size()))
n2, err := m.Value.MarshalTo(dAtA[i:]) n2, err2 := m.Value.MarshalTo(dAtA[i:])
if err != nil { if err2 != nil {
return 0, err return 0, err2
} }
i += n2 i += n2
return i, nil return i, nil
@ -298,6 +340,11 @@ func (m *ReadBatch) MarshalTo(dAtA []byte) (int, error) {
i++ i++
i = encodeVarintCachingIndexClient(dAtA, i, uint64(m.Expiry)) i = encodeVarintCachingIndexClient(dAtA, i, uint64(m.Expiry))
} }
if m.Cardinality != 0 {
dAtA[i] = 0x20
i++
i = encodeVarintCachingIndexClient(dAtA, i, uint64(m.Cardinality))
}
return i, nil return i, nil
} }
@ -342,6 +389,9 @@ func (m *ReadBatch) Size() (n int) {
if m.Expiry != 0 { if m.Expiry != 0 {
n += 1 + sovCachingIndexClient(uint64(m.Expiry)) n += 1 + sovCachingIndexClient(uint64(m.Expiry))
} }
if m.Cardinality != 0 {
n += 1 + sovCachingIndexClient(uint64(m.Cardinality))
}
return n return n
} }
@ -373,10 +423,16 @@ func (this *ReadBatch) String() string {
if this == nil { if this == nil {
return "nil" return "nil"
} }
repeatedStringForEntries := "[]Entry{"
for _, f := range this.Entries {
repeatedStringForEntries += strings.Replace(strings.Replace(f.String(), "Entry", "Entry", 1), `&`, ``, 1) + ","
}
repeatedStringForEntries += "}"
s := strings.Join([]string{`&ReadBatch{`, s := strings.Join([]string{`&ReadBatch{`,
`Entries:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Entries), "Entry", "Entry", 1), `&`, ``, 1) + `,`, `Entries:` + repeatedStringForEntries + `,`,
`Key:` + fmt.Sprintf("%v", this.Key) + `,`, `Key:` + fmt.Sprintf("%v", this.Key) + `,`,
`Expiry:` + fmt.Sprintf("%v", this.Expiry) + `,`, `Expiry:` + fmt.Sprintf("%v", this.Expiry) + `,`,
`Cardinality:` + fmt.Sprintf("%v", this.Cardinality) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -404,7 +460,7 @@ func (m *Entry) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
wire |= (uint64(b) & 0x7F) << shift wire |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -432,7 +488,7 @@ func (m *Entry) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
byteLen |= (int(b) & 0x7F) << shift byteLen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -441,6 +497,9 @@ func (m *Entry) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthCachingIndexClient return ErrInvalidLengthCachingIndexClient
} }
postIndex := iNdEx + byteLen postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthCachingIndexClient
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -462,7 +521,7 @@ func (m *Entry) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
byteLen |= (int(b) & 0x7F) << shift byteLen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -471,6 +530,9 @@ func (m *Entry) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthCachingIndexClient return ErrInvalidLengthCachingIndexClient
} }
postIndex := iNdEx + byteLen postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthCachingIndexClient
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -487,6 +549,9 @@ func (m *Entry) Unmarshal(dAtA []byte) error {
if skippy < 0 { if skippy < 0 {
return ErrInvalidLengthCachingIndexClient return ErrInvalidLengthCachingIndexClient
} }
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthCachingIndexClient
}
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -514,7 +579,7 @@ func (m *ReadBatch) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
wire |= (uint64(b) & 0x7F) << shift wire |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -542,7 +607,7 @@ func (m *ReadBatch) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
msglen |= (int(b) & 0x7F) << shift msglen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -551,6 +616,9 @@ func (m *ReadBatch) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthCachingIndexClient return ErrInvalidLengthCachingIndexClient
} }
postIndex := iNdEx + msglen postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthCachingIndexClient
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -573,7 +641,7 @@ func (m *ReadBatch) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift stringLen |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -583,6 +651,9 @@ func (m *ReadBatch) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthCachingIndexClient return ErrInvalidLengthCachingIndexClient
} }
postIndex := iNdEx + intStringLen postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthCachingIndexClient
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -602,7 +673,26 @@ func (m *ReadBatch) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
m.Expiry |= (int64(b) & 0x7F) << shift m.Expiry |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Cardinality", wireType)
}
m.Cardinality = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCachingIndexClient
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Cardinality |= int32(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -616,6 +706,9 @@ func (m *ReadBatch) Unmarshal(dAtA []byte) error {
if skippy < 0 { if skippy < 0 {
return ErrInvalidLengthCachingIndexClient return ErrInvalidLengthCachingIndexClient
} }
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthCachingIndexClient
}
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -682,10 +775,13 @@ func skipCachingIndexClient(dAtA []byte) (n int, err error) {
break break
} }
} }
iNdEx += length
if length < 0 { if length < 0 {
return 0, ErrInvalidLengthCachingIndexClient return 0, ErrInvalidLengthCachingIndexClient
} }
iNdEx += length
if iNdEx < 0 {
return 0, ErrInvalidLengthCachingIndexClient
}
return iNdEx, nil return iNdEx, nil
case 3: case 3:
for { for {
@ -714,6 +810,9 @@ func skipCachingIndexClient(dAtA []byte) (n int, err error) {
return 0, err return 0, err
} }
iNdEx = start + next iNdEx = start + next
if iNdEx < 0 {
return 0, ErrInvalidLengthCachingIndexClient
}
} }
return iNdEx, nil return iNdEx, nil
case 4: case 4:
@ -732,32 +831,3 @@ var (
ErrInvalidLengthCachingIndexClient = fmt.Errorf("proto: negative length found during unmarshaling") ErrInvalidLengthCachingIndexClient = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowCachingIndexClient = fmt.Errorf("proto: integer overflow") ErrIntOverflowCachingIndexClient = fmt.Errorf("proto: integer overflow")
) )
func init() {
proto.RegisterFile("github.com/cortexproject/cortex/pkg/chunk/storage/caching_index_client.proto", fileDescriptor_caching_index_client_2f4bf220288f700f)
}
var fileDescriptor_caching_index_client_2f4bf220288f700f = []byte{
// 331 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x90, 0xb1, 0x4e, 0xeb, 0x30,
0x14, 0x86, 0xe3, 0x9b, 0xdb, 0x54, 0x35, 0x08, 0xa1, 0x0c, 0x28, 0x62, 0x70, 0xab, 0x4e, 0x5d,
0x88, 0x25, 0xca, 0xc6, 0x16, 0xc4, 0xc6, 0x42, 0x90, 0x58, 0xab, 0xd4, 0x3d, 0x24, 0xa6, 0xa9,
0x1d, 0xb9, 0x0e, 0x34, 0x1b, 0x8f, 0xc0, 0x63, 0xb0, 0xf1, 0x1a, 0x1d, 0x3b, 0x56, 0x0c, 0x15,
0x75, 0x17, 0xc6, 0x3e, 0x02, 0xaa, 0x09, 0x12, 0x23, 0x12, 0xdb, 0xf9, 0xe4, 0xe3, 0xcf, 0xbf,
0x7f, 0x7c, 0x95, 0x72, 0x9d, 0x95, 0xc3, 0x90, 0xc9, 0x09, 0x65, 0x52, 0x69, 0x98, 0x15, 0x4a,
0xde, 0x03, 0xd3, 0x35, 0xd1, 0x62, 0x9c, 0x52, 0x96, 0x95, 0x62, 0x4c, 0xa7, 0x5a, 0xaa, 0x24,
0x05, 0xca, 0x12, 0x96, 0x71, 0x91, 0x0e, 0xb8, 0x18, 0xc1, 0x6c, 0xc0, 0x72, 0x0e, 0x42, 0x87,
0x85, 0x92, 0x5a, 0xfa, 0xcd, 0x7a, 0xe7, 0xf8, 0xe4, 0x87, 0x36, 0x95, 0xa9, 0xa4, 0xf6, 0x7c,
0x58, 0xde, 0x59, 0xb2, 0x60, 0xa7, 0xaf, 0x7b, 0xdd, 0x57, 0x84, 0x1b, 0x97, 0x42, 0xab, 0xca,
0xbf, 0xc1, 0xde, 0x85, 0xcc, 0xcb, 0x89, 0x08, 0x50, 0x07, 0xf5, 0xf6, 0xa3, 0xf3, 0xf9, 0xaa,
0xed, 0xbc, 0xad, 0xda, 0xfd, 0xdf, 0xe4, 0x2c, 0x35, 0xcf, 0xe9, 0x23, 0x57, 0x10, 0x46, 0x95,
0x86, 0x69, 0xec, 0x31, 0xab, 0xf2, 0xaf, 0x71, 0xe3, 0x36, 0xc9, 0x4b, 0x08, 0xfe, 0xfd, 0xdd,
0xd9, 0x78, 0xd8, 0x99, 0xba, 0x80, 0x5b, 0x31, 0x24, 0xa3, 0x28, 0xd1, 0x2c, 0xf3, 0x43, 0xdc,
0x04, 0xa1, 0x15, 0x87, 0x69, 0x80, 0x3a, 0x6e, 0x6f, 0xef, 0xf4, 0x20, 0xac, 0x8b, 0x08, 0xed,
0xaf, 0xa2, 0xff, 0xbb, 0x17, 0xe3, 0xef, 0x25, 0xff, 0x10, 0xbb, 0x63, 0xa8, 0x6c, 0x9a, 0x56,
0xbc, 0x1b, 0xfd, 0x23, 0xec, 0xc1, 0xac, 0xe0, 0xaa, 0x0a, 0xdc, 0x0e, 0xea, 0xb9, 0x71, 0x4d,
0xd1, 0xd9, 0x62, 0x4d, 0x9c, 0xe5, 0x9a, 0x38, 0xdb, 0x35, 0x41, 0x4f, 0x86, 0xa0, 0x17, 0x43,
0xd0, 0xdc, 0x10, 0xb4, 0x30, 0x04, 0xbd, 0x1b, 0x82, 0x3e, 0x0c, 0x71, 0xb6, 0x86, 0xa0, 0xe7,
0x0d, 0x71, 0x16, 0x1b, 0xe2, 0x2c, 0x37, 0xc4, 0x19, 0x7a, 0xb6, 0xd5, 0xfe, 0x67, 0x00, 0x00,
0x00, 0xff, 0xff, 0x95, 0x6d, 0x6d, 0xd0, 0xdd, 0x01, 0x00, 0x00,
}

@ -8,8 +8,8 @@ option (gogoproto.marshaler_all) = true;
option (gogoproto.unmarshaler_all) = true; option (gogoproto.unmarshaler_all) = true;
message Entry { message Entry {
bytes Column = 1 [(gogoproto.customtype) = "github.com/cortexproject/cortex/pkg/util/wire.Bytes", (gogoproto.nullable) = false]; bytes Column = 1 [(gogoproto.customtype) = "Bytes", (gogoproto.nullable) = false];
bytes Value = 2 [(gogoproto.customtype) = "github.com/cortexproject/cortex/pkg/util/wire.Bytes", (gogoproto.nullable) = false]; bytes Value = 2 [(gogoproto.customtype) = "Bytes", (gogoproto.nullable) = false];
} }
message ReadBatch { message ReadBatch {
@ -18,4 +18,8 @@ message ReadBatch {
// The time at which the key expires. // The time at which the key expires.
int64 expiry = 3; int64 expiry = 3;
// The number of entries; used for cardinality limiting.
// entries will be empty when this is set.
int32 cardinality = 4;
} }

@ -98,7 +98,7 @@ func NewStore(cfg Config, storeCfg chunk.StoreConfig, schemaCfg chunk.SchemaConf
if err != nil { if err != nil {
return nil, errors.Wrap(err, "error creating index client") return nil, errors.Wrap(err, "error creating index client")
} }
index = newCachingIndexClient(index, tieredCache, cfg.IndexCacheValidity) index = newCachingIndexClient(index, tieredCache, cfg.IndexCacheValidity, limits)
objectStoreType := s.ObjectType objectStoreType := s.ObjectType
if objectStoreType == "" { if objectStoreType == "" {

@ -1,11 +1,11 @@
package client package client
import ( import (
"bytes"
stdjson "encoding/json" stdjson "encoding/json"
"fmt" "fmt"
"sort" "sort"
"strconv" "strconv"
"strings"
"time" "time"
"unsafe" "unsafe"
@ -16,22 +16,6 @@ import (
var json = jsoniter.ConfigCompatibleWithStandardLibrary var json = jsoniter.ConfigCompatibleWithStandardLibrary
// FromWriteRequest converts a WriteRequest proto into an array of samples.
func FromWriteRequest(req *WriteRequest) []model.Sample {
// Just guess that there is one sample per timeseries
samples := make([]model.Sample, 0, len(req.Timeseries))
for _, ts := range req.Timeseries {
for _, s := range ts.Samples {
samples = append(samples, model.Sample{
Metric: FromLabelPairs(ts.Labels),
Value: model.SampleValue(s.Value),
Timestamp: model.Time(s.TimestampMs),
})
}
}
return samples
}
// ToWriteRequest converts an array of samples into a WriteRequest proto. // ToWriteRequest converts an array of samples into a WriteRequest proto.
func ToWriteRequest(samples []model.Sample, source WriteRequest_SourceEnum) *WriteRequest { func ToWriteRequest(samples []model.Sample, source WriteRequest_SourceEnum) *WriteRequest {
req := &WriteRequest{ req := &WriteRequest{
@ -42,7 +26,7 @@ func ToWriteRequest(samples []model.Sample, source WriteRequest_SourceEnum) *Wri
for _, s := range samples { for _, s := range samples {
ts := PreallocTimeseries{ ts := PreallocTimeseries{
TimeSeries: TimeSeries{ TimeSeries: TimeSeries{
Labels: ToLabelPairs(s.Metric), Labels: FromMetricsToLabelAdapters(s.Metric),
Samples: []Sample{ Samples: []Sample{
{ {
Value: float64(s.Value), Value: float64(s.Value),
@ -87,7 +71,7 @@ func ToQueryResponse(matrix model.Matrix) *QueryResponse {
resp := &QueryResponse{} resp := &QueryResponse{}
for _, ss := range matrix { for _, ss := range matrix {
ts := TimeSeries{ ts := TimeSeries{
Labels: ToLabelPairs(ss.Metric), Labels: FromMetricsToLabelAdapters(ss.Metric),
Samples: make([]Sample, 0, len(ss.Values)), Samples: make([]Sample, 0, len(ss.Values)),
} }
for _, s := range ss.Values { for _, s := range ss.Values {
@ -106,7 +90,7 @@ func FromQueryResponse(resp *QueryResponse) model.Matrix {
m := make(model.Matrix, 0, len(resp.Timeseries)) m := make(model.Matrix, 0, len(resp.Timeseries))
for _, ts := range resp.Timeseries { for _, ts := range resp.Timeseries {
var ss model.SampleStream var ss model.SampleStream
ss.Metric = FromLabelPairs(ts.Labels) ss.Metric = FromLabelAdaptersToMetric(ts.Labels)
ss.Values = make([]model.SamplePair, 0, len(ts.Samples)) ss.Values = make([]model.SamplePair, 0, len(ts.Samples))
for _, s := range ts.Samples { for _, s := range ts.Samples {
ss.Values = append(ss.Values, model.SamplePair{ ss.Values = append(ss.Values, model.SamplePair{
@ -153,7 +137,7 @@ func FromMetricsForLabelMatchersRequest(req *MetricsForLabelMatchersRequest) (mo
func FromMetricsForLabelMatchersResponse(resp *MetricsForLabelMatchersResponse) []model.Metric { func FromMetricsForLabelMatchersResponse(resp *MetricsForLabelMatchersResponse) []model.Metric {
metrics := []model.Metric{} metrics := []model.Metric{}
for _, m := range resp.Metric { for _, m := range resp.Metric {
metrics = append(metrics, FromLabelPairs(m.Labels)) metrics = append(metrics, FromLabelAdaptersToMetric(m.Labels))
} }
return metrics return metrics
} }
@ -208,70 +192,63 @@ func fromLabelMatchers(matchers []*LabelMatcher) ([]*labels.Matcher, error) {
return result, nil return result, nil
} }
// ToLabelPairs builds a []LabelPair from a model.Metric // FromLabelAdaptersToLabels casts []LabelAdapter to labels.Labels.
func ToLabelPairs(metric model.Metric) []LabelPair { // It uses unsafe, but as LabelAdapter == labels.Label this should be safe.
labelPairs := make([]LabelPair, 0, len(metric)) // This allows us to use labels.Labels directly in protos.
for k, v := range metric { func FromLabelAdaptersToLabels(ls []LabelAdapter) labels.Labels {
labelPairs = append(labelPairs, LabelPair{ return *(*labels.Labels)(unsafe.Pointer(&ls))
Name: []byte(k),
Value: []byte(v),
})
}
sort.Sort(byLabel(labelPairs)) // The labels should be sorted upon initialisation.
return labelPairs
} }
type byLabel []LabelPair // FromLabelsToLabelAdapaters casts labels.Labels to []LabelAdapter.
// It uses unsafe, but as LabelAdapter == labels.Label this should be safe.
func (s byLabel) Len() int { return len(s) } // This allows us to use labels.Labels directly in protos.
func (s byLabel) Less(i, j int) bool { return bytes.Compare(s[i].Name, s[j].Name) < 0 } func FromLabelsToLabelAdapaters(ls labels.Labels) []LabelAdapter {
func (s byLabel) Swap(i, j int) { s[i], s[j] = s[j], s[i] } return *(*[]LabelAdapter)(unsafe.Pointer(&ls))
// FromLabelPairs unpack a []LabelPair to a model.Metric
func FromLabelPairs(labelPairs []LabelPair) model.Metric {
metric := make(model.Metric, len(labelPairs))
for _, l := range labelPairs {
metric[model.LabelName(l.Name)] = model.LabelValue(l.Value)
}
return metric
} }
// FromLabelPairsToLabels unpack a []LabelPair to a labels.Labels // FromLabelAdaptersToMetric converts []LabelAdapter to a model.Metric.
func FromLabelPairsToLabels(labelPairs []LabelPair) labels.Labels { // Don't do this on any performance sensitive paths.
ls := make(labels.Labels, 0, len(labelPairs)) func FromLabelAdaptersToMetric(ls []LabelAdapter) model.Metric {
for _, l := range labelPairs { result := make(model.Metric, len(ls))
ls = append(ls, labels.Label{ for _, l := range ls {
Name: string(l.Name), result[model.LabelName(l.Name)] = model.LabelValue(l.Value)
Value: string(l.Value),
})
} }
return ls return result
} }
// FromLabelsToLabelPairs converts labels.Labels to []LabelPair // FromMetricsToLabelAdapters converts model.Metric to []LabelAdapter.
func FromLabelsToLabelPairs(s labels.Labels) []LabelPair { // Don't do this on any performance sensitive paths.
labelPairs := make([]LabelPair, 0, len(s)) // The result is sorted.
for _, v := range s { func FromMetricsToLabelAdapters(metric model.Metric) []LabelAdapter {
labelPairs = append(labelPairs, LabelPair{ result := make([]LabelAdapter, 0, len(metric))
Name: []byte(v.Name), for k, v := range metric {
Value: []byte(v.Value), result = append(result, LabelAdapter{
Name: string(k),
Value: string(v),
}) })
} }
return labelPairs // note already sorted sort.Sort(byLabel(result)) // The labels should be sorted upon initialisation.
return result
} }
type byLabel []LabelAdapter
func (s byLabel) Len() int { return len(s) }
func (s byLabel) Less(i, j int) bool { return strings.Compare(s[i].Name, s[j].Name) < 0 }
func (s byLabel) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// FastFingerprint runs the same algorithm as Prometheus labelSetToFastFingerprint() // FastFingerprint runs the same algorithm as Prometheus labelSetToFastFingerprint()
func FastFingerprint(labelPairs []LabelPair) model.Fingerprint { func FastFingerprint(ls []LabelAdapter) model.Fingerprint {
if len(labelPairs) == 0 { if len(ls) == 0 {
return model.Metric(nil).FastFingerprint() return model.Metric(nil).FastFingerprint()
} }
var result uint64 var result uint64
for _, pair := range labelPairs { for _, l := range ls {
sum := hashNew() sum := hashNew()
sum = hashAdd(sum, pair.Name) sum = hashAdd(sum, l.Name)
sum = hashAddByte(sum, model.SeparatorByte) sum = hashAddByte(sum, model.SeparatorByte)
sum = hashAdd(sum, pair.Value) sum = hashAdd(sum, l.Value)
result ^= sum result ^= sum
} }
return model.Fingerprint(result) return model.Fingerprint(result)

File diff suppressed because it is too large Load Diff

@ -104,7 +104,7 @@ message MetricsForLabelMatchersResponse {
message TimeSeriesChunk { message TimeSeriesChunk {
string from_ingester_id = 1; string from_ingester_id = 1;
string user_id = 2; string user_id = 2;
repeated LabelPair labels = 3 [(gogoproto.nullable) = false]; repeated LabelPair labels = 3 [(gogoproto.nullable) = false, (gogoproto.customtype) = "LabelAdapter"];
repeated Chunk chunks = 4 [(gogoproto.nullable) = false]; repeated Chunk chunks = 4 [(gogoproto.nullable) = false];
} }
@ -119,14 +119,14 @@ message TransferChunksResponse {
} }
message TimeSeries { message TimeSeries {
repeated LabelPair labels = 1 [(gogoproto.nullable) = false]; repeated LabelPair labels = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "LabelAdapter"];
// Sorted by time, oldest sample first. // Sorted by time, oldest sample first.
repeated Sample samples = 2 [(gogoproto.nullable) = false]; repeated Sample samples = 2 [(gogoproto.nullable) = false];
} }
message LabelPair { message LabelPair {
bytes name = 1 [(gogoproto.customtype) = "github.com/cortexproject/cortex/pkg/util/wire.Bytes", (gogoproto.nullable) = false]; bytes name = 1;
bytes value = 2 [(gogoproto.customtype) = "github.com/cortexproject/cortex/pkg/util/wire.Bytes", (gogoproto.nullable) = false]; bytes value = 2;
} }
message Sample { message Sample {
@ -139,7 +139,7 @@ message LabelMatchers {
} }
message Metric { message Metric {
repeated LabelPair labels = 1 [(gogoproto.nullable) = false]; repeated LabelPair labels = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "LabelAdapter"];
} }
enum MatchType { enum MatchType {

@ -19,6 +19,8 @@ package client
const ( const (
offset64 = 14695981039346656037 offset64 = 14695981039346656037
prime64 = 1099511628211 prime64 = 1099511628211
offset32 = 2166136261
prime32 = 16777619
) )
// hashNew initializies a new fnv64a hash value. // hashNew initializies a new fnv64a hash value.
@ -27,7 +29,8 @@ func hashNew() uint64 {
} }
// hashAdd adds a string to a fnv64a hash value, returning the updated hash. // hashAdd adds a string to a fnv64a hash value, returning the updated hash.
func hashAdd(h uint64, s []byte) uint64 { // Note this is the same algorithm as Go stdlib `sum64a.Write()`
func hashAdd(h uint64, s string) uint64 {
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
h ^= uint64(s[i]) h ^= uint64(s[i])
h *= prime64 h *= prime64
@ -41,3 +44,18 @@ func hashAddByte(h uint64, b byte) uint64 {
h *= prime64 h *= prime64
return h return h
} }
// HashNew32 initializies a new fnv32 hash value.
func HashNew32() uint32 {
return offset32
}
// HashAdd32 adds a string to a fnv32 hash value, returning the updated hash.
// Note this is the same algorithm as Go stdlib `sum32.Write()`
func HashAdd32(h uint32, s string) uint32 {
for i := 0; i < len(s); i++ {
h *= prime32
h ^= uint32(s[i])
}
return h
}

@ -1,6 +1,14 @@
package client package client
import "flag" import (
"flag"
"fmt"
"io"
"strings"
"unsafe"
"github.com/prometheus/prometheus/pkg/labels"
)
var ( var (
expectedTimeseries = 100 expectedTimeseries = 100
@ -37,7 +45,182 @@ type PreallocTimeseries struct {
// Unmarshal implements proto.Message. // Unmarshal implements proto.Message.
func (p *PreallocTimeseries) Unmarshal(dAtA []byte) error { func (p *PreallocTimeseries) Unmarshal(dAtA []byte) error {
p.Labels = make([]LabelPair, 0, expectedLabels) p.Labels = make([]LabelAdapter, 0, expectedLabels)
p.Samples = make([]Sample, 0, expectedSamplesPerSeries) p.Samples = make([]Sample, 0, expectedSamplesPerSeries)
return p.TimeSeries.Unmarshal(dAtA) return p.TimeSeries.Unmarshal(dAtA)
} }
// LabelAdapter is a labels.Label that can be marshalled to/from protos.
type LabelAdapter labels.Label
// Marshal implements proto.Marshaller.
func (bs *LabelAdapter) Marshal() ([]byte, error) {
buf := make([]byte, bs.Size())
_, err := bs.MarshalTo(buf)
return buf, err
}
// MarshalTo implements proto.Marshaller.
func (bs *LabelAdapter) MarshalTo(buf []byte) (n int, err error) {
var i int
ls := (*labels.Label)(bs)
buf[i] = 0xa
i++
i = encodeVarintCortex(buf, i, uint64(len(ls.Name)))
i += copy(buf[i:], ls.Name)
buf[i] = 0x12
i++
i = encodeVarintCortex(buf, i, uint64(len(ls.Value)))
i += copy(buf[i:], ls.Value)
return i, nil
}
// Unmarshal a LabelAdapater, implements proto.Unmarshaller.
// NB this is a copy of the autogenerated code to unmarshal a LabelPair,
// with the byte copying replaced with a yoloString.
func (bs *LabelAdapter) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCortex
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: LabelPair: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: LabelPair: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCortex
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthCortex
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthCortex
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
bs.Name = yoloString(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCortex
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthCortex
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthCortex
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
bs.Value = yoloString(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipCortex(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthCortex
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthCortex
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func yoloString(buf []byte) string {
return *((*string)(unsafe.Pointer(&buf)))
}
// Size implements proto.Sizer.
func (bs *LabelAdapter) Size() int {
ls := (*labels.Label)(bs)
var n int
l := len(ls.Name)
n += 1 + l + sovCortex(uint64(l))
l = len(ls.Value)
n += 1 + l + sovCortex(uint64(l))
return n
}
// Equal implements proto.Equaler.
func (bs *LabelAdapter) Equal(other LabelAdapter) bool {
return bs.Name == other.Name && bs.Value == other.Value
}
// Compare implements proto.Comparer.
func (bs *LabelAdapter) Compare(other LabelAdapter) int {
if c := strings.Compare(bs.Name, other.Name); c != 0 {
return c
}
return strings.Compare(bs.Value, other.Value)
}

@ -32,7 +32,7 @@ func New() *InvertedIndex {
} }
// Add a fingerprint under the specified labels. // Add a fingerprint under the specified labels.
func (ii *InvertedIndex) Add(labels []client.LabelPair, fp model.Fingerprint) labels.Labels { func (ii *InvertedIndex) Add(labels []client.LabelAdapter, fp model.Fingerprint) labels.Labels {
shard := &ii.shards[util.HashFP(fp)%indexShards] shard := &ii.shards[util.HashFP(fp)%indexShards]
return shard.add(labels, fp) return shard.add(labels, fp)
} }
@ -49,7 +49,6 @@ func (ii *InvertedIndex) Lookup(matchers []*labels.Matcher) []model.Fingerprint
result = append(result, fps...) result = append(result, fps...)
} }
sort.Sort(fingerprints(result))
return result return result
} }
@ -105,25 +104,31 @@ type indexShard struct {
pad [cacheLineSize - unsafe.Sizeof(sync.Mutex{}) - unsafe.Sizeof(unlockIndex{})]byte pad [cacheLineSize - unsafe.Sizeof(sync.Mutex{}) - unsafe.Sizeof(unlockIndex{})]byte
} }
func copyString(s string) string {
return string([]byte(s))
}
// add metric to the index; return all the name/value pairs as strings from the index, sorted // add metric to the index; return all the name/value pairs as strings from the index, sorted
func (shard *indexShard) add(metric []client.LabelPair, fp model.Fingerprint) labels.Labels { func (shard *indexShard) add(metric []client.LabelAdapter, fp model.Fingerprint) labels.Labels {
shard.mtx.Lock() shard.mtx.Lock()
defer shard.mtx.Unlock() defer shard.mtx.Unlock()
internedLabels := make(labels.Labels, len(metric)) internedLabels := make(labels.Labels, len(metric))
for i, pair := range metric { for i, pair := range metric {
values, ok := shard.idx[string(pair.Name)] values, ok := shard.idx[pair.Name]
if !ok { if !ok {
values = indexEntry{ values = indexEntry{
name: string(pair.Name), name: copyString(pair.Name),
fps: map[string]indexValueEntry{}, fps: map[string]indexValueEntry{},
} }
shard.idx[values.name] = values shard.idx[values.name] = values
} }
fingerprints, ok := values.fps[string(pair.Value)] fingerprints, ok := values.fps[pair.Value]
if !ok { if !ok {
fingerprints = indexValueEntry{value: string(pair.Value)} fingerprints = indexValueEntry{
value: copyString(pair.Value),
}
} }
// Insert into the right position to keep fingerprints sorted // Insert into the right position to keep fingerprints sorted
j := sort.Search(len(fingerprints.fps), func(i int) bool { j := sort.Search(len(fingerprints.fps), func(i int) bool {
@ -133,7 +138,7 @@ func (shard *indexShard) add(metric []client.LabelPair, fp model.Fingerprint) la
copy(fingerprints.fps[j+1:], fingerprints.fps[j:]) copy(fingerprints.fps[j+1:], fingerprints.fps[j:])
fingerprints.fps[j] = fp fingerprints.fps[j] = fp
values.fps[fingerprints.value] = fingerprints values.fps[fingerprints.value] = fingerprints
internedLabels[i] = labels.Label{Name: string(values.name), Value: string(fingerprints.value)} internedLabels[i] = labels.Label{Name: values.name, Value: fingerprints.value}
} }
sort.Sort(internedLabels) sort.Sort(internedLabels)
return internedLabels return internedLabels
@ -162,7 +167,7 @@ func (shard *indexShard) lookup(matchers []*labels.Matcher) []model.Fingerprint
// accumulate the matching fingerprints (which are all distinct) // accumulate the matching fingerprints (which are all distinct)
// then sort to maintain the invariant // then sort to maintain the invariant
for value, fps := range values.fps { for value, fps := range values.fps {
if matcher.Matches(string(value)) { if matcher.Matches(value) {
toIntersect = append(toIntersect, fps.fps...) toIntersect = append(toIntersect, fps.fps...)
} }
} }
@ -213,7 +218,7 @@ func (shard *indexShard) delete(labels labels.Labels, fp model.Fingerprint) {
defer shard.mtx.Unlock() defer shard.mtx.Unlock()
for _, pair := range labels { for _, pair := range labels {
name, value := string(pair.Name), string(pair.Value) name, value := pair.Name, pair.Value
values, ok := shard.idx[name] values, ok := shard.idx[name]
if !ok { if !ok {
continue continue

@ -3,18 +3,17 @@
package ring package ring
import proto "github.com/gogo/protobuf/proto" import (
import fmt "fmt" fmt "fmt"
import math "math" _ "github.com/gogo/protobuf/gogoproto"
import _ "github.com/gogo/protobuf/gogoproto" proto "github.com/gogo/protobuf/proto"
github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys"
import strconv "strconv" io "io"
math "math"
import strings "strings" reflect "reflect"
import reflect "reflect" strconv "strconv"
import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" strings "strings"
)
import io "io"
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
@ -42,6 +41,7 @@ var IngesterState_name = map[int32]string{
2: "PENDING", 2: "PENDING",
3: "JOINING", 3: "JOINING",
} }
var IngesterState_value = map[string]int32{ var IngesterState_value = map[string]int32{
"ACTIVE": 0, "ACTIVE": 0,
"LEAVING": 1, "LEAVING": 1,
@ -50,18 +50,18 @@ var IngesterState_value = map[string]int32{
} }
func (IngesterState) EnumDescriptor() ([]byte, []int) { func (IngesterState) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_ring_35bba6cb303d16e3, []int{0} return fileDescriptor_7ebe6ffe1686e76b, []int{0}
} }
type Desc struct { type Desc struct {
Ingesters map[string]IngesterDesc `protobuf:"bytes,1,rep,name=ingesters" json:"ingesters" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"` Ingesters map[string]IngesterDesc `protobuf:"bytes,1,rep,name=ingesters,proto3" json:"ingesters" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Tokens []TokenDesc `protobuf:"bytes,2,rep,name=tokens" json:"tokens"` Tokens []TokenDesc `protobuf:"bytes,2,rep,name=tokens,proto3" json:"tokens"`
} }
func (m *Desc) Reset() { *m = Desc{} } func (m *Desc) Reset() { *m = Desc{} }
func (*Desc) ProtoMessage() {} func (*Desc) ProtoMessage() {}
func (*Desc) Descriptor() ([]byte, []int) { func (*Desc) Descriptor() ([]byte, []int) {
return fileDescriptor_ring_35bba6cb303d16e3, []int{0} return fileDescriptor_7ebe6ffe1686e76b, []int{0}
} }
func (m *Desc) XXX_Unmarshal(b []byte) error { func (m *Desc) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -78,8 +78,8 @@ func (m *Desc) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return b[:n], nil return b[:n], nil
} }
} }
func (dst *Desc) XXX_Merge(src proto.Message) { func (m *Desc) XXX_Merge(src proto.Message) {
xxx_messageInfo_Desc.Merge(dst, src) xxx_messageInfo_Desc.Merge(m, src)
} }
func (m *Desc) XXX_Size() int { func (m *Desc) XXX_Size() int {
return m.Size() return m.Size()
@ -108,13 +108,13 @@ type IngesterDesc struct {
Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"` Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"`
Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
State IngesterState `protobuf:"varint,3,opt,name=state,proto3,enum=ring.IngesterState" json:"state,omitempty"` State IngesterState `protobuf:"varint,3,opt,name=state,proto3,enum=ring.IngesterState" json:"state,omitempty"`
Tokens []uint32 `protobuf:"varint,6,rep,packed,name=tokens" json:"tokens,omitempty"` Tokens []uint32 `protobuf:"varint,6,rep,packed,name=tokens,proto3" json:"tokens,omitempty"`
} }
func (m *IngesterDesc) Reset() { *m = IngesterDesc{} } func (m *IngesterDesc) Reset() { *m = IngesterDesc{} }
func (*IngesterDesc) ProtoMessage() {} func (*IngesterDesc) ProtoMessage() {}
func (*IngesterDesc) Descriptor() ([]byte, []int) { func (*IngesterDesc) Descriptor() ([]byte, []int) {
return fileDescriptor_ring_35bba6cb303d16e3, []int{1} return fileDescriptor_7ebe6ffe1686e76b, []int{1}
} }
func (m *IngesterDesc) XXX_Unmarshal(b []byte) error { func (m *IngesterDesc) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -131,8 +131,8 @@ func (m *IngesterDesc) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
return b[:n], nil return b[:n], nil
} }
} }
func (dst *IngesterDesc) XXX_Merge(src proto.Message) { func (m *IngesterDesc) XXX_Merge(src proto.Message) {
xxx_messageInfo_IngesterDesc.Merge(dst, src) xxx_messageInfo_IngesterDesc.Merge(m, src)
} }
func (m *IngesterDesc) XXX_Size() int { func (m *IngesterDesc) XXX_Size() int {
return m.Size() return m.Size()
@ -179,7 +179,7 @@ type TokenDesc struct {
func (m *TokenDesc) Reset() { *m = TokenDesc{} } func (m *TokenDesc) Reset() { *m = TokenDesc{} }
func (*TokenDesc) ProtoMessage() {} func (*TokenDesc) ProtoMessage() {}
func (*TokenDesc) Descriptor() ([]byte, []int) { func (*TokenDesc) Descriptor() ([]byte, []int) {
return fileDescriptor_ring_35bba6cb303d16e3, []int{2} return fileDescriptor_7ebe6ffe1686e76b, []int{2}
} }
func (m *TokenDesc) XXX_Unmarshal(b []byte) error { func (m *TokenDesc) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b) return m.Unmarshal(b)
@ -196,8 +196,8 @@ func (m *TokenDesc) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return b[:n], nil return b[:n], nil
} }
} }
func (dst *TokenDesc) XXX_Merge(src proto.Message) { func (m *TokenDesc) XXX_Merge(src proto.Message) {
xxx_messageInfo_TokenDesc.Merge(dst, src) xxx_messageInfo_TokenDesc.Merge(m, src)
} }
func (m *TokenDesc) XXX_Size() int { func (m *TokenDesc) XXX_Size() int {
return m.Size() return m.Size()
@ -223,12 +223,49 @@ func (m *TokenDesc) GetIngester() string {
} }
func init() { func init() {
proto.RegisterEnum("ring.IngesterState", IngesterState_name, IngesterState_value)
proto.RegisterType((*Desc)(nil), "ring.Desc") proto.RegisterType((*Desc)(nil), "ring.Desc")
proto.RegisterMapType((map[string]IngesterDesc)(nil), "ring.Desc.IngestersEntry") proto.RegisterMapType((map[string]IngesterDesc)(nil), "ring.Desc.IngestersEntry")
proto.RegisterType((*IngesterDesc)(nil), "ring.IngesterDesc") proto.RegisterType((*IngesterDesc)(nil), "ring.IngesterDesc")
proto.RegisterType((*TokenDesc)(nil), "ring.TokenDesc") proto.RegisterType((*TokenDesc)(nil), "ring.TokenDesc")
proto.RegisterEnum("ring.IngesterState", IngesterState_name, IngesterState_value)
} }
func init() {
proto.RegisterFile("github.com/cortexproject/cortex/pkg/ring/ring.proto", fileDescriptor_7ebe6ffe1686e76b)
}
var fileDescriptor_7ebe6ffe1686e76b = []byte{
// 440 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x92, 0xcf, 0x6e, 0xd3, 0x40,
0x10, 0xc6, 0x77, 0xe2, 0x3f, 0xc4, 0x13, 0x52, 0xac, 0x05, 0x21, 0x13, 0xa1, 0xc5, 0xca, 0xc9,
0x20, 0x35, 0x91, 0x52, 0x0e, 0x08, 0xa9, 0x87, 0x86, 0x46, 0x28, 0x11, 0x0a, 0x95, 0xa9, 0x7a,
0x4f, 0xd2, 0xc5, 0x84, 0x90, 0xac, 0x65, 0x6f, 0x10, 0xbd, 0xf1, 0x06, 0xf0, 0x18, 0x3c, 0x09,
0xea, 0x31, 0xc7, 0x9e, 0x10, 0x71, 0x2e, 0x1c, 0xfb, 0x08, 0x68, 0xd7, 0x76, 0x9a, 0x5c, 0xac,
0xf9, 0xed, 0x37, 0xdf, 0xb7, 0x33, 0xd6, 0xe2, 0x51, 0x34, 0x95, 0x9f, 0x96, 0xe3, 0xd6, 0x44,
0xcc, 0xdb, 0x13, 0x91, 0x48, 0xfe, 0x2d, 0x4e, 0xc4, 0x67, 0x3e, 0x91, 0x05, 0xb5, 0xe3, 0x59,
0xd4, 0x4e, 0xa6, 0x8b, 0xfc, 0xd3, 0x8a, 0x13, 0x21, 0x05, 0x35, 0x55, 0xdd, 0x38, 0xdc, 0xb1,
0x46, 0x22, 0x12, 0x6d, 0x2d, 0x8e, 0x97, 0x1f, 0x35, 0x69, 0xd0, 0x55, 0x6e, 0x6a, 0xfe, 0x06,
0x34, 0x4f, 0x79, 0x3a, 0xa1, 0xc7, 0xe8, 0x4c, 0x17, 0x11, 0x4f, 0x25, 0x4f, 0x52, 0x0f, 0x7c,
0x23, 0xa8, 0x75, 0x9e, 0xb4, 0x74, 0xba, 0x92, 0x5b, 0xfd, 0x52, 0xeb, 0x2d, 0x64, 0x72, 0xd5,
0x35, 0xaf, 0xff, 0x3c, 0x23, 0xe1, 0x9d, 0x83, 0x1e, 0xa2, 0x2d, 0xc5, 0x8c, 0x2f, 0x52, 0xaf,
0xa2, 0xbd, 0x0f, 0x72, 0xef, 0xb9, 0x3a, 0x53, 0x01, 0x85, 0xa3, 0x68, 0x6a, 0x9c, 0xe1, 0xc1,
0x7e, 0x22, 0x75, 0xd1, 0x98, 0xf1, 0x2b, 0x0f, 0x7c, 0x08, 0x9c, 0x50, 0x95, 0x34, 0x40, 0xeb,
0xeb, 0xe8, 0xcb, 0x92, 0x7b, 0x15, 0x1f, 0x82, 0x5a, 0x87, 0xe6, 0x89, 0xa5, 0x4d, 0x85, 0x86,
0x79, 0xc3, 0xeb, 0xca, 0x2b, 0x68, 0xfe, 0x00, 0xbc, 0xbf, 0xab, 0x51, 0x8a, 0xe6, 0xe8, 0xf2,
0x32, 0x29, 0x12, 0x75, 0x4d, 0x9f, 0xa2, 0x23, 0xa7, 0x73, 0x9e, 0xca, 0xd1, 0x3c, 0xd6, 0xb1,
0x46, 0x78, 0x77, 0x40, 0x9f, 0xa3, 0x95, 0xca, 0x91, 0xe4, 0x9e, 0xe1, 0x43, 0x70, 0xd0, 0x79,
0xb8, 0x7f, 0xe1, 0x07, 0x25, 0x85, 0x79, 0x07, 0x7d, 0xbc, 0x5d, 0xd7, 0xf6, 0x8d, 0xa0, 0x5e,
0xee, 0x35, 0x30, 0xab, 0xa6, 0x6b, 0x0d, 0xcc, 0xaa, 0xe5, 0xda, 0xcd, 0x63, 0x74, 0xb6, 0xeb,
0xd3, 0x47, 0x68, 0xe9, 0x16, 0x3d, 0x4e, 0x3d, 0xcc, 0x81, 0x36, 0xb0, 0x5a, 0xfe, 0x42, 0x3d,
0x8e, 0x13, 0x6e, 0xf9, 0x45, 0x17, 0xeb, 0x7b, 0x57, 0x53, 0x44, 0xfb, 0xe4, 0xcd, 0x79, 0xff,
0xa2, 0xe7, 0x12, 0x5a, 0xc3, 0x7b, 0xef, 0x7a, 0x27, 0x17, 0xfd, 0xe1, 0x5b, 0x17, 0x14, 0x9c,
0xf5, 0x86, 0xa7, 0x0a, 0x2a, 0x0a, 0x06, 0xef, 0xfb, 0x43, 0x05, 0x46, 0xf7, 0xe5, 0x6a, 0xcd,
0xc8, 0xcd, 0x9a, 0x91, 0xdb, 0x35, 0x83, 0xef, 0x19, 0x83, 0x5f, 0x19, 0x83, 0xeb, 0x8c, 0xc1,
0x2a, 0x63, 0xf0, 0x37, 0x63, 0xf0, 0x2f, 0x63, 0xe4, 0x36, 0x63, 0xf0, 0x73, 0xc3, 0xc8, 0x6a,
0xc3, 0xc8, 0xcd, 0x86, 0x91, 0xb1, 0xad, 0x9f, 0xc6, 0xd1, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff,
0xab, 0x96, 0x85, 0x85, 0x86, 0x02, 0x00, 0x00,
}
func (x IngesterState) String() string { func (x IngesterState) String() string {
s, ok := IngesterState_name[int32(x)] s, ok := IngesterState_name[int32(x)]
if ok { if ok {
@ -435,9 +472,9 @@ func (m *Desc) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x12 dAtA[i] = 0x12
i++ i++
i = encodeVarintRing(dAtA, i, uint64((&v).Size())) i = encodeVarintRing(dAtA, i, uint64((&v).Size()))
n1, err := (&v).MarshalTo(dAtA[i:]) n1, err1 := (&v).MarshalTo(dAtA[i:])
if err != nil { if err1 != nil {
return 0, err return 0, err1
} }
i += n1 i += n1
} }
@ -629,6 +666,11 @@ func (this *Desc) String() string {
if this == nil { if this == nil {
return "nil" return "nil"
} }
repeatedStringForTokens := "[]TokenDesc{"
for _, f := range this.Tokens {
repeatedStringForTokens += strings.Replace(strings.Replace(f.String(), "TokenDesc", "TokenDesc", 1), `&`, ``, 1) + ","
}
repeatedStringForTokens += "}"
keysForIngesters := make([]string, 0, len(this.Ingesters)) keysForIngesters := make([]string, 0, len(this.Ingesters))
for k, _ := range this.Ingesters { for k, _ := range this.Ingesters {
keysForIngesters = append(keysForIngesters, k) keysForIngesters = append(keysForIngesters, k)
@ -641,7 +683,7 @@ func (this *Desc) String() string {
mapStringForIngesters += "}" mapStringForIngesters += "}"
s := strings.Join([]string{`&Desc{`, s := strings.Join([]string{`&Desc{`,
`Ingesters:` + mapStringForIngesters + `,`, `Ingesters:` + mapStringForIngesters + `,`,
`Tokens:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Tokens), "TokenDesc", "TokenDesc", 1), `&`, ``, 1) + `,`, `Tokens:` + repeatedStringForTokens + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -693,7 +735,7 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
wire |= (uint64(b) & 0x7F) << shift wire |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -721,7 +763,7 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
msglen |= (int(b) & 0x7F) << shift msglen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -730,6 +772,9 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
postIndex := iNdEx + msglen postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthRing
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -750,7 +795,7 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
wire |= (uint64(b) & 0x7F) << shift wire |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -767,7 +812,7 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
stringLenmapkey |= (uint64(b) & 0x7F) << shift stringLenmapkey |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -777,6 +822,9 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
postStringIndexmapkey := iNdEx + intStringLenmapkey postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey < 0 {
return ErrInvalidLengthRing
}
if postStringIndexmapkey > l { if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -793,7 +841,7 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
mapmsglen |= (int(b) & 0x7F) << shift mapmsglen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -802,7 +850,7 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
postmsgIndex := iNdEx + mapmsglen postmsgIndex := iNdEx + mapmsglen
if mapmsglen < 0 { if postmsgIndex < 0 {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
if postmsgIndex > l { if postmsgIndex > l {
@ -844,7 +892,7 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
msglen |= (int(b) & 0x7F) << shift msglen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -853,6 +901,9 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
postIndex := iNdEx + msglen postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthRing
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -870,6 +921,9 @@ func (m *Desc) Unmarshal(dAtA []byte) error {
if skippy < 0 { if skippy < 0 {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthRing
}
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -897,7 +951,7 @@ func (m *IngesterDesc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
wire |= (uint64(b) & 0x7F) << shift wire |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -925,7 +979,7 @@ func (m *IngesterDesc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift stringLen |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -935,6 +989,9 @@ func (m *IngesterDesc) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
postIndex := iNdEx + intStringLen postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthRing
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -954,7 +1011,7 @@ func (m *IngesterDesc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
m.Timestamp |= (int64(b) & 0x7F) << shift m.Timestamp |= int64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -973,7 +1030,7 @@ func (m *IngesterDesc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
m.State |= (IngesterState(b) & 0x7F) << shift m.State |= IngesterState(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -990,7 +1047,7 @@ func (m *IngesterDesc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
v |= (uint32(b) & 0x7F) << shift v |= uint32(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -1007,7 +1064,7 @@ func (m *IngesterDesc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
packedLen |= (int(b) & 0x7F) << shift packedLen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -1016,12 +1073,15 @@ func (m *IngesterDesc) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
postIndex := iNdEx + packedLen postIndex := iNdEx + packedLen
if postIndex < 0 {
return ErrInvalidLengthRing
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
var elementCount int var elementCount int
var count int var count int
for _, integer := range dAtA { for _, integer := range dAtA[iNdEx:postIndex] {
if integer < 128 { if integer < 128 {
count++ count++
} }
@ -1041,7 +1101,7 @@ func (m *IngesterDesc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
v |= (uint32(b) & 0x7F) << shift v |= uint32(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -1060,6 +1120,9 @@ func (m *IngesterDesc) Unmarshal(dAtA []byte) error {
if skippy < 0 { if skippy < 0 {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthRing
}
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -1087,7 +1150,7 @@ func (m *TokenDesc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
wire |= (uint64(b) & 0x7F) << shift wire |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -1115,7 +1178,7 @@ func (m *TokenDesc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
m.Token |= (uint32(b) & 0x7F) << shift m.Token |= uint32(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -1134,7 +1197,7 @@ func (m *TokenDesc) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift stringLen |= uint64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
@ -1144,6 +1207,9 @@ func (m *TokenDesc) Unmarshal(dAtA []byte) error {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
postIndex := iNdEx + intStringLen postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthRing
}
if postIndex > l { if postIndex > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -1158,6 +1224,9 @@ func (m *TokenDesc) Unmarshal(dAtA []byte) error {
if skippy < 0 { if skippy < 0 {
return ErrInvalidLengthRing return ErrInvalidLengthRing
} }
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthRing
}
if (iNdEx + skippy) > l { if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF return io.ErrUnexpectedEOF
} }
@ -1224,10 +1293,13 @@ func skipRing(dAtA []byte) (n int, err error) {
break break
} }
} }
iNdEx += length
if length < 0 { if length < 0 {
return 0, ErrInvalidLengthRing return 0, ErrInvalidLengthRing
} }
iNdEx += length
if iNdEx < 0 {
return 0, ErrInvalidLengthRing
}
return iNdEx, nil return iNdEx, nil
case 3: case 3:
for { for {
@ -1256,6 +1328,9 @@ func skipRing(dAtA []byte) (n int, err error) {
return 0, err return 0, err
} }
iNdEx = start + next iNdEx = start + next
if iNdEx < 0 {
return 0, ErrInvalidLengthRing
}
} }
return iNdEx, nil return iNdEx, nil
case 4: case 4:
@ -1274,39 +1349,3 @@ var (
ErrInvalidLengthRing = fmt.Errorf("proto: negative length found during unmarshaling") ErrInvalidLengthRing = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowRing = fmt.Errorf("proto: integer overflow") ErrIntOverflowRing = fmt.Errorf("proto: integer overflow")
) )
func init() {
proto.RegisterFile("github.com/cortexproject/cortex/pkg/ring/ring.proto", fileDescriptor_ring_35bba6cb303d16e3)
}
var fileDescriptor_ring_35bba6cb303d16e3 = []byte{
// 440 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x54, 0x92, 0xcf, 0x6e, 0xd3, 0x40,
0x10, 0xc6, 0x77, 0xe2, 0x3f, 0xc4, 0x13, 0x52, 0xac, 0x05, 0x21, 0x13, 0xa1, 0xc5, 0xca, 0xc9,
0x20, 0x35, 0x91, 0x52, 0x0e, 0x08, 0xa9, 0x87, 0x86, 0x46, 0x28, 0x11, 0x0a, 0x95, 0xa9, 0x7a,
0x4f, 0xd2, 0xc5, 0x84, 0x90, 0xac, 0x65, 0x6f, 0x10, 0xbd, 0xf1, 0x06, 0xf0, 0x18, 0x3c, 0x09,
0xea, 0x31, 0xc7, 0x9e, 0x10, 0x71, 0x2e, 0x1c, 0xfb, 0x08, 0x68, 0xd7, 0x76, 0x9a, 0x5c, 0xac,
0xf9, 0xed, 0x37, 0xdf, 0xb7, 0x33, 0xd6, 0xe2, 0x51, 0x34, 0x95, 0x9f, 0x96, 0xe3, 0xd6, 0x44,
0xcc, 0xdb, 0x13, 0x91, 0x48, 0xfe, 0x2d, 0x4e, 0xc4, 0x67, 0x3e, 0x91, 0x05, 0xb5, 0xe3, 0x59,
0xd4, 0x4e, 0xa6, 0x8b, 0xfc, 0xd3, 0x8a, 0x13, 0x21, 0x05, 0x35, 0x55, 0xdd, 0x38, 0xdc, 0xb1,
0x46, 0x22, 0x12, 0x6d, 0x2d, 0x8e, 0x97, 0x1f, 0x35, 0x69, 0xd0, 0x55, 0x6e, 0x6a, 0xfe, 0x06,
0x34, 0x4f, 0x79, 0x3a, 0xa1, 0xc7, 0xe8, 0x4c, 0x17, 0x11, 0x4f, 0x25, 0x4f, 0x52, 0x0f, 0x7c,
0x23, 0xa8, 0x75, 0x9e, 0xb4, 0x74, 0xba, 0x92, 0x5b, 0xfd, 0x52, 0xeb, 0x2d, 0x64, 0x72, 0xd5,
0x35, 0xaf, 0xff, 0x3c, 0x23, 0xe1, 0x9d, 0x83, 0x1e, 0xa2, 0x2d, 0xc5, 0x8c, 0x2f, 0x52, 0xaf,
0xa2, 0xbd, 0x0f, 0x72, 0xef, 0xb9, 0x3a, 0x53, 0x01, 0x85, 0xa3, 0x68, 0x6a, 0x9c, 0xe1, 0xc1,
0x7e, 0x22, 0x75, 0xd1, 0x98, 0xf1, 0x2b, 0x0f, 0x7c, 0x08, 0x9c, 0x50, 0x95, 0x34, 0x40, 0xeb,
0xeb, 0xe8, 0xcb, 0x92, 0x7b, 0x15, 0x1f, 0x82, 0x5a, 0x87, 0xe6, 0x89, 0xa5, 0x4d, 0x85, 0x86,
0x79, 0xc3, 0xeb, 0xca, 0x2b, 0x68, 0xfe, 0x00, 0xbc, 0xbf, 0xab, 0x51, 0x8a, 0xe6, 0xe8, 0xf2,
0x32, 0x29, 0x12, 0x75, 0x4d, 0x9f, 0xa2, 0x23, 0xa7, 0x73, 0x9e, 0xca, 0xd1, 0x3c, 0xd6, 0xb1,
0x46, 0x78, 0x77, 0x40, 0x9f, 0xa3, 0x95, 0xca, 0x91, 0xe4, 0x9e, 0xe1, 0x43, 0x70, 0xd0, 0x79,
0xb8, 0x7f, 0xe1, 0x07, 0x25, 0x85, 0x79, 0x07, 0x7d, 0xbc, 0x5d, 0xd7, 0xf6, 0x8d, 0xa0, 0x5e,
0xee, 0x35, 0x30, 0xab, 0xa6, 0x6b, 0x0d, 0xcc, 0xaa, 0xe5, 0xda, 0xcd, 0x63, 0x74, 0xb6, 0xeb,
0xd3, 0x47, 0x68, 0xe9, 0x16, 0x3d, 0x4e, 0x3d, 0xcc, 0x81, 0x36, 0xb0, 0x5a, 0xfe, 0x42, 0x3d,
0x8e, 0x13, 0x6e, 0xf9, 0x45, 0x17, 0xeb, 0x7b, 0x57, 0x53, 0x44, 0xfb, 0xe4, 0xcd, 0x79, 0xff,
0xa2, 0xe7, 0x12, 0x5a, 0xc3, 0x7b, 0xef, 0x7a, 0x27, 0x17, 0xfd, 0xe1, 0x5b, 0x17, 0x14, 0x9c,
0xf5, 0x86, 0xa7, 0x0a, 0x2a, 0x0a, 0x06, 0xef, 0xfb, 0x43, 0x05, 0x46, 0xf7, 0xe5, 0x6a, 0xcd,
0xc8, 0xcd, 0x9a, 0x91, 0xdb, 0x35, 0x83, 0xef, 0x19, 0x83, 0x5f, 0x19, 0x83, 0xeb, 0x8c, 0xc1,
0x2a, 0x63, 0xf0, 0x37, 0x63, 0xf0, 0x2f, 0x63, 0xe4, 0x36, 0x63, 0xf0, 0x73, 0xc3, 0xc8, 0x6a,
0xc3, 0xc8, 0xcd, 0x86, 0x91, 0xb1, 0xad, 0x9f, 0xc6, 0xd1, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff,
0xab, 0x96, 0x85, 0x85, 0x86, 0x02, 0x00, 0x00,
}

@ -8,16 +8,14 @@ import (
"github.com/prometheus/prometheus/pkg/labels" "github.com/prometheus/prometheus/pkg/labels"
) )
var labelNameBytes = []byte(model.MetricNameLabel) // MetricNameFromLabelAdapters extracts the metric name from a list of LabelPairs.
func MetricNameFromLabelAdapters(labels []client.LabelAdapter) (string, error) {
// MetricNameFromLabelPairs extracts the metric name from a list of LabelPairs.
func MetricNameFromLabelPairs(labels []client.LabelPair) ([]byte, error) {
for _, label := range labels { for _, label := range labels {
if label.Name.Equal(labelNameBytes) { if label.Name == model.MetricNameLabel {
return label.Value, nil return label.Value, nil
} }
} }
return nil, fmt.Errorf("No metric name label") return "", fmt.Errorf("No metric name label")
} }
// MetricNameFromMetric extract the metric name from a model.Metric // MetricNameFromMetric extract the metric name from a model.Metric

@ -0,0 +1,26 @@
package flagext
import (
"flag"
"github.com/cortexproject/cortex/pkg/util"
"github.com/go-kit/kit/log/level"
)
type deprecatedFlag struct {
name string
}
func (deprecatedFlag) String() string {
return "deprecated"
}
func (d deprecatedFlag) Set(string) error {
level.Warn(util.Logger).Log("msg", "flag disabled", "flag", d.name)
return nil
}
// DeprecatedFlag logs a warning when you try to use it.
func DeprecatedFlag(f *flag.FlagSet, name, message string) {
f.Var(deprecatedFlag{name}, name, message)
}

@ -9,6 +9,6 @@ import "github.com/prometheus/common/model"
// function we use is prone to only change a few bits for similar metrics. We // function we use is prone to only change a few bits for similar metrics. We
// really want to make use of every change in the fingerprint to vary mutex // really want to make use of every change in the fingerprint to vary mutex
// selection.) // selection.)
func HashFP(fp model.Fingerprint) uint { func HashFP(fp model.Fingerprint) uint32 {
return uint(fp ^ (fp >> 32) ^ (fp >> 16)) return uint32(fp ^ (fp >> 32) ^ (fp >> 16))
} }

@ -44,8 +44,14 @@ func InitLogger(cfg *server.Config) {
panic(err) panic(err)
} }
Logger = l // when use util.Logger, skip 3 stack frames.
cfg.Log = logging.GoKit(l) Logger = log.With(l, "caller", log.Caller(3))
// cfg.Log wraps log function, skip 4 stack frames to get caller information.
// this works in go 1.12, but doesn't work in versions earlier.
// it will always shows the wrapper function generated by compiler
// marked <autogenerated> in old versions.
cfg.Log = logging.GoKit(log.With(l, "caller", log.Caller(4)))
} }
// PrometheusLogger exposes Prometheus counters for each of go-kit's log levels. // PrometheusLogger exposes Prometheus counters for each of go-kit's log levels.
@ -68,8 +74,8 @@ func NewPrometheusLogger(l logging.Level) (log.Logger, error) {
logger: logger, logger: logger,
} }
// DefaultCaller must be the last wrapper // return a Logger without caller information, shouldn't use directly
logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller) logger = log.With(logger, "ts", log.DefaultTimestampUTC)
return logger, nil return logger, nil
} }

@ -3,8 +3,6 @@ package validation
import ( import (
"flag" "flag"
"time" "time"
"github.com/cortexproject/cortex/pkg/util/flagext"
) )
// Limits describe all the limits for users; can be used to describe global default // Limits describe all the limits for users; can be used to describe global default
@ -28,8 +26,10 @@ type Limits struct {
MaxSeriesPerMetric int `yaml:"max_series_per_metric"` MaxSeriesPerMetric int `yaml:"max_series_per_metric"`
// Querier enforced limits. // Querier enforced limits.
MaxChunksPerQuery int `yaml:"max_chunks_per_query"` MaxChunksPerQuery int `yaml:"max_chunks_per_query"`
MaxQueryLength time.Duration `yaml:"max_query_length"` MaxQueryLength time.Duration `yaml:"max_query_length"`
MaxQueryParallelism int `yaml:"max_query_parallelism"`
CardinalityLimit int `yaml:"cardinality_limit"`
// Config for overrides, convenient if it goes here. // Config for overrides, convenient if it goes here.
PerTenantOverrideConfig string PerTenantOverrideConfig string
@ -55,6 +55,8 @@ func (l *Limits) RegisterFlags(f *flag.FlagSet) {
f.IntVar(&l.MaxChunksPerQuery, "store.query-chunk-limit", 2e6, "Maximum number of chunks that can be fetched in a single query.") f.IntVar(&l.MaxChunksPerQuery, "store.query-chunk-limit", 2e6, "Maximum number of chunks that can be fetched in a single query.")
f.DurationVar(&l.MaxQueryLength, "store.max-query-length", 0, "Limit to length of chunk store queries, 0 to disable.") f.DurationVar(&l.MaxQueryLength, "store.max-query-length", 0, "Limit to length of chunk store queries, 0 to disable.")
f.IntVar(&l.MaxQueryParallelism, "querier.max-query-parallelism", 14, "Maximum number of queries will be scheduled in parallel by the frontend.")
f.IntVar(&l.CardinalityLimit, "store.cardinality-limit", 1e5, "Cardinality limit for index queries.")
f.StringVar(&l.PerTenantOverrideConfig, "limits.per-user-override-config", "", "File name of per-user overrides.") f.StringVar(&l.PerTenantOverrideConfig, "limits.per-user-override-config", "", "File name of per-user overrides.")
f.DurationVar(&l.PerTenantOverridePeriod, "limits.per-user-override-period", 10*time.Second, "Period with this to reload the overrides.") f.DurationVar(&l.PerTenantOverridePeriod, "limits.per-user-override-period", 10*time.Second, "Period with this to reload the overrides.")
@ -65,7 +67,7 @@ func (l *Limits) UnmarshalYAML(unmarshal func(interface{}) error) error {
// We want to set c to the defaults and then overwrite it with the input. // We want to set c to the defaults and then overwrite it with the input.
// To make unmarshal fill the plain data struct rather than calling UnmarshalYAML // To make unmarshal fill the plain data struct rather than calling UnmarshalYAML
// again, we have to hide it using a type indirection. See prometheus/config. // again, we have to hide it using a type indirection. See prometheus/config.
flagext.DefaultValues(l) *l = defaultLimits
type plain Limits type plain Limits
return unmarshal((*plain)(l)) return unmarshal((*plain)(l))
} }

@ -18,6 +18,12 @@ var overridesReloadSuccess = promauto.NewGauge(prometheus.GaugeOpts{
Help: "Whether the last overrides reload attempt was successful.", Help: "Whether the last overrides reload attempt was successful.",
}) })
// When we load YAML from disk, we want the various per-customer limits
// to default to any values specified on the command line, not default
// command line values. This global contains those values. I (Tom) cannot
// find a nicer way I'm afraid.
var defaultLimits Limits
// Overrides periodically fetch a set of per-user overrides, and provides convenience // Overrides periodically fetch a set of per-user overrides, and provides convenience
// functions for fetching the correct value. // functions for fetching the correct value.
type Overrides struct { type Overrides struct {
@ -28,7 +34,12 @@ type Overrides struct {
} }
// NewOverrides makes a new Overrides. // NewOverrides makes a new Overrides.
// We store the supplied limits in a global variable to ensure per-tenant limits
// are defaulted to those values. As such, the last call to NewOverrides will
// become the new global defaults.
func NewOverrides(defaults Limits) (*Overrides, error) { func NewOverrides(defaults Limits) (*Overrides, error) {
defaultLimits = defaults
if defaults.PerTenantOverrideConfig == "" { if defaults.PerTenantOverrideConfig == "" {
level.Info(util.Logger).Log("msg", "per-tenant overides disabled") level.Info(util.Logger).Log("msg", "per-tenant overides disabled")
return &Overrides{ return &Overrides{
@ -242,9 +253,24 @@ func (o *Overrides) MaxQueryLength(userID string) time.Duration {
}) })
} }
// MaxQueryParallelism returns the limit to the number of sub-queries the
// frontend will process in parallel.
func (o *Overrides) MaxQueryParallelism(userID string) int {
return o.getInt(userID, func(l *Limits) int {
return l.MaxQueryParallelism
})
}
// EnforceMetricName whether to enforce the presence of a metric name. // EnforceMetricName whether to enforce the presence of a metric name.
func (o *Overrides) EnforceMetricName(userID string) bool { func (o *Overrides) EnforceMetricName(userID string) bool {
return o.getBool(userID, func(l *Limits) bool { return o.getBool(userID, func(l *Limits) bool {
return l.EnforceMetricName return l.EnforceMetricName
}) })
} }
// CardinalityLimit whether to enforce the presence of a metric name.
func (o *Overrides) CardinalityLimit(userID string) int {
return o.getInt(userID, func(l *Limits) int {
return l.CardinalityLimit
})
}

@ -22,6 +22,9 @@ const (
errTooOld = "sample for '%s' has timestamp too old: %d" errTooOld = "sample for '%s' has timestamp too old: %d"
errTooNew = "sample for '%s' has timestamp too new: %d" errTooNew = "sample for '%s' has timestamp too new: %d"
// ErrQueryTooLong is used in chunk store and query frontend.
ErrQueryTooLong = "invalid query, length > limit (%s > %s)"
greaterThanMaxSampleAge = "greater_than_max_sample_age" greaterThanMaxSampleAge = "greater_than_max_sample_age"
maxLabelNamesPerSeries = "max_label_names_per_series" maxLabelNamesPerSeries = "max_label_names_per_series"
tooFarInFuture = "too_far_in_future" tooFarInFuture = "too_far_in_future"
@ -48,7 +51,7 @@ func init() {
} }
// ValidateSample returns an err if the sample is invalid. // ValidateSample returns an err if the sample is invalid.
func (cfg *Overrides) ValidateSample(userID string, metricName []byte, s client.Sample) error { func (cfg *Overrides) ValidateSample(userID string, metricName string, s client.Sample) error {
if cfg.RejectOldSamples(userID) && model.Time(s.TimestampMs) < model.Now().Add(-cfg.RejectOldSamplesMaxAge(userID)) { if cfg.RejectOldSamples(userID) && model.Time(s.TimestampMs) < model.Now().Add(-cfg.RejectOldSamplesMaxAge(userID)) {
DiscardedSamples.WithLabelValues(greaterThanMaxSampleAge, userID).Inc() DiscardedSamples.WithLabelValues(greaterThanMaxSampleAge, userID).Inc()
return httpgrpc.Errorf(http.StatusBadRequest, errTooOld, metricName, model.Time(s.TimestampMs)) return httpgrpc.Errorf(http.StatusBadRequest, errTooOld, metricName, model.Time(s.TimestampMs))
@ -63,8 +66,8 @@ func (cfg *Overrides) ValidateSample(userID string, metricName []byte, s client.
} }
// ValidateLabels returns an err if the labels are invalid. // ValidateLabels returns an err if the labels are invalid.
func (cfg *Overrides) ValidateLabels(userID string, ls []client.LabelPair) error { func (cfg *Overrides) ValidateLabels(userID string, ls []client.LabelAdapter) error {
metricName, err := extract.MetricNameFromLabelPairs(ls) metricName, err := extract.MetricNameFromLabelAdapters(ls)
if cfg.EnforceMetricName(userID) { if cfg.EnforceMetricName(userID) {
if err != nil { if err != nil {
return httpgrpc.Errorf(http.StatusBadRequest, errMissingMetricName) return httpgrpc.Errorf(http.StatusBadRequest, errMissingMetricName)
@ -78,7 +81,7 @@ func (cfg *Overrides) ValidateLabels(userID string, ls []client.LabelPair) error
numLabelNames := len(ls) numLabelNames := len(ls)
if numLabelNames > cfg.MaxLabelNamesPerSeries(userID) { if numLabelNames > cfg.MaxLabelNamesPerSeries(userID) {
DiscardedSamples.WithLabelValues(maxLabelNamesPerSeries, userID).Inc() DiscardedSamples.WithLabelValues(maxLabelNamesPerSeries, userID).Inc()
return httpgrpc.Errorf(http.StatusBadRequest, errTooManyLabels, client.FromLabelPairs(ls).String(), numLabelNames, cfg.MaxLabelNamesPerSeries(userID)) return httpgrpc.Errorf(http.StatusBadRequest, errTooManyLabels, client.FromLabelAdaptersToMetric(ls).String(), numLabelNames, cfg.MaxLabelNamesPerSeries(userID))
} }
maxLabelNameLength := cfg.MaxLabelNameLength(userID) maxLabelNameLength := cfg.MaxLabelNameLength(userID)
@ -102,7 +105,7 @@ func (cfg *Overrides) ValidateLabels(userID string, ls []client.LabelPair) error
} }
if errTemplate != "" { if errTemplate != "" {
DiscardedSamples.WithLabelValues(reason, userID).Inc() DiscardedSamples.WithLabelValues(reason, userID).Inc()
return httpgrpc.Errorf(http.StatusBadRequest, errTemplate, cause, client.FromLabelPairs(ls).String()) return httpgrpc.Errorf(http.StatusBadRequest, errTemplate, cause, client.FromLabelAdaptersToMetric(ls).String())
} }
} }
return nil return nil

Loading…
Cancel
Save