@ -2,9 +2,12 @@ package storage
import (
"context"
"io/ioutil"
"log"
"net/http"
_ "net/http/pprof"
"os"
"path"
"runtime"
"testing"
"time"
@ -14,13 +17,15 @@ import (
"github.com/weaveworks/common/user"
"github.com/cortexproject/cortex/pkg/chunk"
"github.com/cortexproject/cortex/pkg/chunk/local"
cortex_local "github.com/cortexproject/cortex/pkg/chunk/local"
"github.com/cortexproject/cortex/pkg/chunk/storage"
"github.com/cortexproject/cortex/pkg/util/flagext"
"github.com/grafana/loki/pkg/iter"
"github.com/grafana/loki/pkg/logproto"
"github.com/grafana/loki/pkg/logql"
"github.com/grafana/loki/pkg/logql/marshal"
"github.com/grafana/loki/pkg/storage/stores/local"
"github.com/grafana/loki/pkg/util/validation"
)
@ -149,8 +154,8 @@ func getLocalStore() Store {
}
store , err := NewStore ( Config {
Config : storage . Config {
BoltDBConfig : local . BoltDBConfig { Directory : "/tmp/benchmark/index" } ,
FSConfig : local . FSConfig { Directory : "/tmp/benchmark/chunks" } ,
BoltDBConfig : cortex_ local. BoltDBConfig { Directory : "/tmp/benchmark/index" } ,
FSConfig : cortex_ local. FSConfig { Directory : "/tmp/benchmark/chunks" } ,
} ,
MaxChunkBatchSize : 10 ,
} , chunk . StoreConfig { } , chunk . SchemaConfig {
@ -166,7 +171,7 @@ func getLocalStore() Store {
} ,
} ,
} ,
} , limits )
} , limits , nil )
if err != nil {
panic ( err )
}
@ -422,6 +427,108 @@ func Test_store_GetSeries(t *testing.T) {
}
}
type timeRange struct {
from , to time . Time
}
func TestStore_MultipleBoltDBShippersInConfig ( t * testing . T ) {
tempDir , err := ioutil . TempDir ( "" , "multiple-boltdb-shippers" )
require . NoError ( t , err )
defer func ( ) {
require . NoError ( t , os . RemoveAll ( tempDir ) )
} ( )
limits , err := validation . NewOverrides ( validation . Limits { } , nil )
require . NoError ( t , err )
// config for BoltDB Shipper
boltdbShipperConfig := local . ShipperConfig { }
flagext . DefaultValues ( & boltdbShipperConfig )
boltdbShipperConfig . ActiveIndexDirectory = path . Join ( tempDir , "index" )
boltdbShipperConfig . SharedStoreType = "filesystem"
boltdbShipperConfig . CacheLocation = path . Join ( tempDir , "boltdb-shipper-cache" )
// dates for activation of boltdb shippers
firstStoreDate := parseDate ( "2019-01-01" )
secondStoreDate := parseDate ( "2019-01-02" )
store , err := NewStore ( Config {
Config : storage . Config {
FSConfig : cortex_local . FSConfig { Directory : path . Join ( tempDir , "chunks" ) } ,
} ,
BoltDBShipperConfig : boltdbShipperConfig ,
} , chunk . StoreConfig { } , chunk . SchemaConfig {
Configs : [ ] chunk . PeriodConfig {
{
From : chunk . DayTime { Time : timeToModelTime ( firstStoreDate ) } ,
IndexType : "boltdb-shipper" ,
ObjectType : "filesystem" ,
Schema : "v9" ,
IndexTables : chunk . PeriodicTableConfig {
Prefix : "index_" ,
Period : time . Hour * 168 ,
} ,
} ,
{
From : chunk . DayTime { Time : timeToModelTime ( secondStoreDate ) } ,
IndexType : "boltdb-shipper" ,
ObjectType : "filesystem" ,
Schema : "v11" ,
IndexTables : chunk . PeriodicTableConfig {
Prefix : "index_" ,
Period : time . Hour * 168 ,
} ,
RowShards : 2 ,
} ,
} ,
} , limits , nil )
require . NoError ( t , err )
// time ranges adding a chunk for each store and a chunk which overlaps both the stores
chunksToBuildForTimeRanges := [ ] timeRange {
{
// chunk just for first store
secondStoreDate . Add ( - 3 * time . Hour ) ,
secondStoreDate . Add ( - 2 * time . Hour ) ,
} ,
{
// chunk overlapping both the stores
secondStoreDate . Add ( - time . Hour ) ,
secondStoreDate . Add ( time . Hour ) ,
} ,
{
// chunk just for second store
secondStoreDate . Add ( 2 * time . Hour ) ,
secondStoreDate . Add ( 3 * time . Hour ) ,
} ,
}
// build and add chunks to the store
addedChunkIDs := map [ string ] struct { } { }
for _ , tr := range chunksToBuildForTimeRanges {
chk := newChunk ( buildTestStreams ( fooLabelsWithName , tr ) )
err := store . PutOne ( ctx , chk . From , chk . Through , chk )
require . NoError ( t , err )
addedChunkIDs [ chk . ExternalKey ( ) ] = struct { } { }
}
// get all the chunks from both the stores
chunks , err := store . Get ( ctx , "fake" , timeToModelTime ( firstStoreDate ) , timeToModelTime ( secondStoreDate . Add ( 24 * time . Hour ) ) , newMatchers ( fooLabelsWithName ) ... )
require . NoError ( t , err )
// we get common chunk twice because it is indexed in both the stores
require . Len ( t , chunks , len ( addedChunkIDs ) + 1 )
// check whether we got back all the chunks which were added
for i := range chunks {
_ , ok := addedChunkIDs [ chunks [ i ] . ExternalKey ( ) ]
require . True ( t , ok )
}
}
func mustParseLabels ( s string ) map [ string ] string {
l , err := marshal . NewLabelSet ( s )
@ -431,3 +538,31 @@ func mustParseLabels(s string) map[string]string {
return l
}
func parseDate ( in string ) time . Time {
t , err := time . Parse ( "2006-01-02" , in )
if err != nil {
panic ( err )
}
return t
}
func buildTestStreams ( labels string , tr timeRange ) logproto . Stream {
stream := logproto . Stream {
Labels : labels ,
Entries : [ ] logproto . Entry { } ,
}
for from := tr . from ; from . Before ( tr . to ) ; from = from . Add ( time . Second ) {
stream . Entries = append ( stream . Entries , logproto . Entry {
Timestamp : from ,
Line : from . String ( ) ,
} )
}
return stream
}
func timeToModelTime ( t time . Time ) model . Time {
return model . TimeFromUnixNano ( t . UnixNano ( ) )
}