github.com/sequix/cortex@v1.1.6/pkg/chunk/storage/factory.go (about) 1 package storage 2 3 import ( 4 "context" 5 "flag" 6 "fmt" 7 "strings" 8 "time" 9 10 "github.com/go-kit/kit/log/level" 11 "github.com/pkg/errors" 12 "github.com/sequix/cortex/pkg/chunk" 13 "github.com/sequix/cortex/pkg/chunk/aws" 14 "github.com/sequix/cortex/pkg/chunk/baidu" 15 "github.com/sequix/cortex/pkg/chunk/cache" 16 "github.com/sequix/cortex/pkg/chunk/cassandra" 17 "github.com/sequix/cortex/pkg/chunk/gcp" 18 "github.com/sequix/cortex/pkg/chunk/local" 19 "github.com/sequix/cortex/pkg/chunk/ts" 20 "github.com/sequix/cortex/pkg/util" 21 "github.com/sequix/cortex/pkg/util/validation" 22 ) 23 24 // Config chooses which storage client to use. 25 type Config struct { 26 AWSStorageConfig aws.StorageConfig `yaml:"aws"` 27 GCPStorageConfig gcp.Config `yaml:"bigtable"` 28 GCSConfig gcp.GCSConfig `yaml:"gcs"` 29 CassandraStorageConfig cassandra.Config `yaml:"cassandra"` 30 BoltDBConfig local.BoltDBConfig `yaml:"boltdb"` 31 FSConfig local.FSConfig `yaml:"filesystem"` 32 BOSConfig baidu.ObjectStorageConfig `yaml:"bos"` 33 TableStorageConfig ts.Config `yaml:"table_storage"` 34 35 IndexCacheValidity time.Duration 36 37 IndexQueriesCacheConfig cache.Config `yaml:"index_queries_cache_config,omitempty"` 38 } 39 40 // RegisterFlags adds the flags required to configure this flag set. 41 func (cfg *Config) RegisterFlags(f *flag.FlagSet) { 42 cfg.AWSStorageConfig.RegisterFlags(f) 43 cfg.GCPStorageConfig.RegisterFlags(f) 44 cfg.GCSConfig.RegisterFlags(f) 45 cfg.CassandraStorageConfig.RegisterFlags(f) 46 cfg.BoltDBConfig.RegisterFlags(f) 47 cfg.FSConfig.RegisterFlags(f) 48 49 cfg.IndexQueriesCacheConfig.RegisterFlagsWithPrefix("store.index-cache-read.", "Cache config for index entry reading. ", f) 50 f.DurationVar(&cfg.IndexCacheValidity, "store.index-cache-validity", 5*time.Minute, "Cache validity for active index entries. Should be no higher than -ingester.max-chunk-idle.") 51 } 52 53 // NewStore makes the storage clients based on the configuration. 54 func NewStore(cfg Config, storeCfg chunk.StoreConfig, schemaCfg chunk.SchemaConfig, limits *validation.Overrides) (chunk.Store, error) { 55 tieredCache, err := cache.New(cfg.IndexQueriesCacheConfig) 56 if err != nil { 57 return nil, err 58 } 59 60 // Cache is shared by multiple stores, which means they will try and Stop 61 // it more than once. Wrap in a StopOnce to prevent this. 62 tieredCache = cache.StopOnce(tieredCache) 63 64 err = schemaCfg.Load() 65 if err != nil { 66 return nil, errors.Wrap(err, "error loading schema config") 67 } 68 stores := chunk.NewCompositeStore() 69 70 for _, s := range schemaCfg.Configs { 71 index, err := NewIndexClient(s.IndexType, cfg, schemaCfg) 72 if err != nil { 73 return nil, errors.Wrap(err, "error creating index client") 74 } 75 index = newCachingIndexClient(index, tieredCache, cfg.IndexCacheValidity, limits) 76 77 objectStoreType := s.ObjectType 78 if objectStoreType == "" { 79 objectStoreType = s.IndexType 80 } 81 chunks, err := NewObjectClient(objectStoreType, cfg, schemaCfg) 82 if err != nil { 83 return nil, errors.Wrap(err, "error creating object client") 84 } 85 86 err = stores.AddPeriod(storeCfg, s, index, chunks, limits) 87 if err != nil { 88 return nil, err 89 } 90 } 91 92 return stores, nil 93 } 94 95 // NewIndexClient makes a new index client of the desired type. 96 func NewIndexClient(name string, cfg Config, schemaCfg chunk.SchemaConfig) (chunk.IndexClient, error) { 97 switch name { 98 case "inmemory": 99 store := chunk.NewMockStorage() 100 return store, nil 101 case "aws", "aws-dynamo", "dynamo": 102 if cfg.AWSStorageConfig.DynamoDB.URL == nil { 103 return nil, fmt.Errorf("Must set -dynamodb.url in aws mode") 104 } 105 path := strings.TrimPrefix(cfg.AWSStorageConfig.DynamoDB.URL.Path, "/") 106 if len(path) > 0 { 107 level.Warn(util.Logger).Log("msg", "ignoring DynamoDB URL path", "path", path) 108 } 109 return aws.NewDynamoDBIndexClient(cfg.AWSStorageConfig.DynamoDBConfig, schemaCfg) 110 case "gcp": 111 return gcp.NewStorageClientV1(context.Background(), cfg.GCPStorageConfig, schemaCfg) 112 case "gcp-columnkey", "bigtable": 113 return gcp.NewStorageClientColumnKey(context.Background(), cfg.GCPStorageConfig, schemaCfg) 114 case "bigtable-hashed": 115 cfg.GCPStorageConfig.DistributeKeys = true 116 return gcp.NewStorageClientColumnKey(context.Background(), cfg.GCPStorageConfig, schemaCfg) 117 case "cassandra": 118 return cassandra.NewStorageClient(cfg.CassandraStorageConfig, schemaCfg) 119 case "boltdb": 120 return local.NewBoltDBIndexClient(cfg.BoltDBConfig) 121 default: 122 return nil, fmt.Errorf("Unrecognized storage client %v, choose one of: aws, cassandra, inmemory, gcp, bigtable, bigtable-hashed", name) 123 } 124 } 125 126 // NewObjectClient makes a new ObjectClient of the desired types. 127 func NewObjectClient(name string, cfg Config, schemaCfg chunk.SchemaConfig) (chunk.ObjectClient, error) { 128 switch name { 129 case "inmemory": 130 store := chunk.NewMockStorage() 131 return store, nil 132 case "aws", "s3": 133 return aws.NewS3ObjectClient(cfg.AWSStorageConfig, schemaCfg) 134 case "aws-dynamo", "dynamo": 135 if cfg.AWSStorageConfig.DynamoDB.URL == nil { 136 return nil, fmt.Errorf("Must set -dynamodb.url in aws mode") 137 } 138 path := strings.TrimPrefix(cfg.AWSStorageConfig.DynamoDB.URL.Path, "/") 139 if len(path) > 0 { 140 level.Warn(util.Logger).Log("msg", "ignoring DynamoDB URL path", "path", path) 141 } 142 return aws.NewDynamoDBObjectClient(cfg.AWSStorageConfig.DynamoDBConfig, schemaCfg) 143 case "gcp": 144 return gcp.NewBigtableObjectClient(context.Background(), cfg.GCPStorageConfig, schemaCfg) 145 case "gcp-columnkey", "bigtable", "bigtable-hashed": 146 return gcp.NewBigtableObjectClient(context.Background(), cfg.GCPStorageConfig, schemaCfg) 147 case "gcs": 148 return gcp.NewGCSObjectClient(context.Background(), cfg.GCSConfig, schemaCfg) 149 case "cassandra": 150 return cassandra.NewStorageClient(cfg.CassandraStorageConfig, schemaCfg) 151 case "filesystem": 152 return local.NewFSObjectClient(cfg.FSConfig) 153 case "bos": 154 return baidu.New(cfg.BOSConfig) 155 case "table-storage": 156 return ts.New(cfg.TableStorageConfig) 157 default: 158 return nil, fmt.Errorf("Unrecognized storage client %v, choose one of: aws, cassandra, inmemory, gcp, bigtable, bigtable-hashed", name) 159 } 160 } 161 162 // NewTableClient makes a new table client based on the configuration. 163 func NewTableClient(name string, cfg Config) (chunk.TableClient, error) { 164 switch name { 165 case "inmemory": 166 return chunk.NewMockStorage(), nil 167 case "aws", "aws-dynamo": 168 if cfg.AWSStorageConfig.DynamoDB.URL == nil { 169 return nil, fmt.Errorf("Must set -dynamodb.url in aws mode") 170 } 171 path := strings.TrimPrefix(cfg.AWSStorageConfig.DynamoDB.URL.Path, "/") 172 if len(path) > 0 { 173 level.Warn(util.Logger).Log("msg", "ignoring DynamoDB URL path", "path", path) 174 } 175 return aws.NewDynamoDBTableClient(cfg.AWSStorageConfig.DynamoDBConfig) 176 case "gcp", "gcp-columnkey", "bigtable", "bigtable-hashed": 177 return gcp.NewTableClient(context.Background(), cfg.GCPStorageConfig) 178 case "cassandra": 179 return cassandra.NewTableClient(context.Background(), cfg.CassandraStorageConfig) 180 case "boltdb": 181 return local.NewTableClient(cfg.BoltDBConfig.Directory) 182 default: 183 return nil, fmt.Errorf("Unrecognized storage client %v, choose one of: aws, cassandra, inmemory, gcp, bigtable, bigtable-hashed", name) 184 } 185 } 186 187 // NewBucketClient makes a new bucket client based on the configuration. 188 func NewBucketClient(storageConfig Config) (chunk.BucketClient, error) { 189 if storageConfig.FSConfig.Directory != "" { 190 return local.NewFSObjectClient(storageConfig.FSConfig) 191 } 192 193 return nil, nil 194 }