66 "math/rand"
77 "net/url"
88 "sort"
9+ "strconv"
910 "strings"
1011 "sync"
1112 "sync/atomic"
@@ -139,9 +140,10 @@ type Store interface {
139140
140141// StoreConfig specifies config for a ChunkStore
141142type StoreConfig struct {
142- S3URL string
143- DynamoDBURL string
144- ChunkCache * Cache
143+ S3URL string
144+ DynamoDBURL string
145+ ChunkCache * Cache
146+ DailyBucketsFrom model.Time
145147
146148 // Not exported as only used by tests to inject mocks
147149 dynamodb dynamodbClient
@@ -206,6 +208,10 @@ type AWSStore struct {
206208 tableName string
207209 bucketName string
208210
211+ // Around which time to start bucketing indexes by day instead of by hour.
212+ // Only the day matters, not the time within the day.
213+ dailyBucketsFrom model.Time
214+
209215 dynamoRequests chan dynamoOp
210216 dynamoRequestsDone sync.WaitGroup
211217}
@@ -332,25 +338,45 @@ func (c *AWSStore) CreateTables() error {
332338 return err
333339}
334340
335- func bigBuckets (from , through model.Time ) []int64 {
341+ func bigBuckets (from , through model.Time , dailyBucketsFrom model. Time ) []string {
336342 var (
337343 secondsInHour = int64 (time .Hour / time .Second )
338344 fromHour = from .Unix () / secondsInHour
339345 throughHour = through .Unix () / secondsInHour
340- result []int64
346+
347+ secondsInDay = int64 (24 * time .Hour / time .Second )
348+ fromDay = from .Unix () / secondsInDay
349+ throughDay = through .Unix () / secondsInDay
350+
351+ firstDailyBucket = dailyBucketsFrom .Unix () / secondsInDay
352+ lastHourlyBucket = firstDailyBucket * 24
353+
354+ result []string
341355 )
356+
342357 for i := fromHour ; i <= throughHour ; i ++ {
343- result = append (result , i )
358+ if i > lastHourlyBucket {
359+ break
360+ }
361+ result = append (result , strconv .Itoa (int (i )))
344362 }
363+
364+ for i := fromDay ; i <= throughDay ; i ++ {
365+ if i < firstDailyBucket {
366+ continue
367+ }
368+ result = append (result , fmt .Sprintf ("d%d" , int (i )))
369+ }
370+
345371 return result
346372}
347373
348374func chunkName (userID , chunkID string ) string {
349375 return fmt .Sprintf ("%s/%s" , userID , chunkID )
350376}
351377
352- func hashValue (userID string , hour int64 , metricName model.LabelValue ) string {
353- return fmt .Sprintf ("%s:%d :%s" , userID , hour , metricName )
378+ func hashValue (userID string , bucket string , metricName model.LabelValue ) string {
379+ return fmt .Sprintf ("%s:%s :%s" , userID , bucket , metricName )
354380}
355381
356382func rangeValue (label model.LabelName , value model.LabelValue , chunkID string ) []byte {
@@ -456,8 +482,8 @@ func (c *AWSStore) calculateDynamoWrites(userID string, chunks []Chunk) ([]*dyna
456482 }
457483
458484 entries := 0
459- for _ , hour := range bigBuckets (chunk .From , chunk .Through ) {
460- hashValue := hashValue (userID , hour , metricName )
485+ for _ , bucket := range bigBuckets (chunk .From , chunk .Through , c . dailyBucketsFrom ) {
486+ hashValue := hashValue (userID , bucket , metricName )
461487 for label , value := range chunk .Metric {
462488 if label == model .MetricNameLabel {
463489 continue
@@ -556,18 +582,18 @@ func (c *AWSStore) lookupChunks(ctx context.Context, userID string, from, throug
556582
557583 incomingChunkSets := make (chan ByID )
558584 incomingErrors := make (chan error )
559- buckets := bigBuckets (from , through )
585+ buckets := bigBuckets (from , through , c . dailyBucketsFrom )
560586 totalLookups := int32 (0 )
561- for _ , hour := range buckets {
562- go func (hour int64 ) {
563- incoming , lookups , err := c .lookupChunksFor (ctx , userID , hour , metricName , matchers )
587+ for _ , b := range buckets {
588+ go func (bucket string ) {
589+ incoming , lookups , err := c .lookupChunksFor (ctx , userID , bucket , metricName , matchers )
564590 atomic .AddInt32 (& totalLookups , lookups )
565591 if err != nil {
566592 incomingErrors <- err
567593 } else {
568594 incomingChunkSets <- incoming
569595 }
570- }(hour )
596+ }(b )
571597 }
572598
573599 var chunks ByID
@@ -592,17 +618,17 @@ func next(s string) string {
592618 return result
593619}
594620
595- func (c * AWSStore ) lookupChunksFor (ctx context.Context , userID string , hour int64 , metricName model.LabelValue , matchers []* metric.LabelMatcher ) (ByID , int32 , error ) {
621+ func (c * AWSStore ) lookupChunksFor (ctx context.Context , userID string , bucket string , metricName model.LabelValue , matchers []* metric.LabelMatcher ) (ByID , int32 , error ) {
596622 if len (matchers ) == 0 {
597- return c .lookupChunksForMetricName (ctx , userID , hour , metricName )
623+ return c .lookupChunksForMetricName (ctx , userID , bucket , metricName )
598624 }
599625
600626 incomingChunkSets := make (chan ByID )
601627 incomingErrors := make (chan error )
602628
603629 for _ , matcher := range matchers {
604630 go func (matcher * metric.LabelMatcher ) {
605- incoming , err := c .lookupChunksForMatcher (ctx , userID , hour , metricName , matcher )
631+ incoming , err := c .lookupChunksForMatcher (ctx , userID , bucket , metricName , matcher )
606632 if err != nil {
607633 incomingErrors <- err
608634 } else {
@@ -624,8 +650,8 @@ func (c *AWSStore) lookupChunksFor(ctx context.Context, userID string, hour int6
624650 return nWayIntersect (chunkSets ), int32 (len (matchers )), lastErr
625651}
626652
627- func (c * AWSStore ) lookupChunksForMetricName (ctx context.Context , userID string , hour int64 , metricName model.LabelValue ) (ByID , int32 , error ) {
628- hashValue := hashValue (userID , hour , metricName )
653+ func (c * AWSStore ) lookupChunksForMetricName (ctx context.Context , userID string , bucket string , metricName model.LabelValue ) (ByID , int32 , error ) {
654+ hashValue := hashValue (userID , bucket , metricName )
629655 input := & dynamodb.QueryInput {
630656 TableName : aws .String (c .tableName ),
631657 KeyConditions : map [string ]* dynamodb.Condition {
@@ -665,8 +691,8 @@ func (c *AWSStore) lookupChunksForMetricName(ctx context.Context, userID string,
665691 return chunkSet , 1 , nil
666692}
667693
668- func (c * AWSStore ) lookupChunksForMatcher (ctx context.Context , userID string , hour int64 , metricName model.LabelValue , matcher * metric.LabelMatcher ) (ByID , error ) {
669- hashValue := hashValue (userID , hour , metricName )
694+ func (c * AWSStore ) lookupChunksForMatcher (ctx context.Context , userID string , bucket string , metricName model.LabelValue , matcher * metric.LabelMatcher ) (ByID , error ) {
695+ hashValue := hashValue (userID , bucket , metricName )
670696 var rangeMinValue , rangeMaxValue []byte
671697 if matcher .Type == metric .Equal {
672698 nextValue := model .LabelValue (next (string (matcher .Value )))
0 commit comments