@@ -16,6 +16,7 @@ import (
16
16
"github.com/grpc-ecosystem/go-grpc-middleware"
17
17
"github.com/grpc-ecosystem/go-grpc-prometheus"
18
18
"github.com/improbable-eng/thanos/pkg/cluster"
19
+ "github.com/improbable-eng/thanos/pkg/discovery/cache"
19
20
"github.com/improbable-eng/thanos/pkg/query"
20
21
"github.com/improbable-eng/thanos/pkg/query/api"
21
22
"github.com/improbable-eng/thanos/pkg/runutil"
@@ -28,6 +29,8 @@ import (
28
29
"github.com/pkg/errors"
29
30
"github.com/prometheus/client_golang/prometheus"
30
31
"github.com/prometheus/common/route"
32
+ "github.com/prometheus/prometheus/discovery/file"
33
+ "github.com/prometheus/prometheus/discovery/targetgroup"
31
34
"github.com/prometheus/prometheus/promql"
32
35
"github.com/prometheus/tsdb/labels"
33
36
"google.golang.org/grpc"
@@ -65,6 +68,12 @@ func registerQuery(m map[string]setupFunc, app *kingpin.Application, name string
65
68
stores := cmd .Flag ("store" , "Addresses of statically configured store API servers (repeatable)." ).
66
69
PlaceHolder ("<store>" ).Strings ()
67
70
71
+ fileSDFiles := cmd .Flag ("store.file-sd-config.files" , "Path to files that contain addresses of store API servers. The path can be a glob pattern (repeatable)." ).
72
+ PlaceHolder ("<path>" ).Strings ()
73
+
74
+ fileSDInterval := modelDuration (cmd .Flag ("store.file-sd-config.interval" , "Refresh interval to re-read file SD files. (used as a fallback)" ).
75
+ Default ("5m" ))
76
+
68
77
enableAutodownsampling := cmd .Flag ("query.auto-downsampling" , "Enable automatic adjustment (step / 5) to what source of data should be used in store gateways if no max_source_resolution param is specified. " ).
69
78
Default ("false" ).Bool ()
70
79
@@ -87,6 +96,15 @@ func registerQuery(m map[string]setupFunc, app *kingpin.Application, name string
87
96
lookupStores [s ] = struct {}{}
88
97
}
89
98
99
+ var fileSD * file.Discovery
100
+ if len (* fileSDFiles ) > 0 {
101
+ conf := & file.SDConfig {
102
+ Files : * fileSDFiles ,
103
+ RefreshInterval : * fileSDInterval ,
104
+ }
105
+ fileSD = file .NewDiscovery (conf , logger )
106
+ }
107
+
90
108
return runQuery (
91
109
g ,
92
110
logger ,
@@ -109,6 +127,7 @@ func registerQuery(m map[string]setupFunc, app *kingpin.Application, name string
109
127
selectorLset ,
110
128
* stores ,
111
129
* enableAutodownsampling ,
130
+ fileSD ,
112
131
)
113
132
}
114
133
}
@@ -218,7 +237,14 @@ func runQuery(
218
237
selectorLset labels.Labels ,
219
238
storeAddrs []string ,
220
239
enableAutodownsampling bool ,
240
+ fileSD * file.Discovery ,
221
241
) error {
242
+ duplicatedStores := prometheus .NewCounter (prometheus.CounterOpts {
243
+ Name : "thanos_query_duplicated_store_address" ,
244
+ Help : "The number of times a duplicated store addresses is detected from the different configs in query" ,
245
+ })
246
+ reg .MustRegister (duplicatedStores )
247
+
222
248
var staticSpecs []query.StoreSpec
223
249
for _ , addr := range storeAddrs {
224
250
if addr == "" {
@@ -233,13 +259,17 @@ func runQuery(
233
259
return errors .Wrap (err , "building gRPC client" )
234
260
}
235
261
262
+ fileSDCache := cache .New ()
263
+
236
264
var (
237
265
stores = query .NewStoreSet (
238
266
logger ,
239
267
reg ,
240
268
func () (specs []query.StoreSpec ) {
269
+ // Add store specs from static flags.
241
270
specs = append (staticSpecs )
242
271
272
+ // Add store specs from gossip.
243
273
for id , ps := range peer .PeerStates (cluster .PeerTypesStoreAPIs ()... ) {
244
274
if ps .StoreAPIAddr == "" {
245
275
level .Error (logger ).Log ("msg" , "Gossip found peer that propagates empty address, ignoring." , "lset" , fmt .Sprintf ("%v" , ps .Metadata .Labels ))
@@ -248,6 +278,14 @@ func runQuery(
248
278
249
279
specs = append (specs , & gossipSpec {id : id , addr : ps .StoreAPIAddr , peer : peer })
250
280
}
281
+
282
+ // Add store specs from file SD.
283
+ for _ , addr := range fileSDCache .Addresses () {
284
+ specs = append (specs , query .NewGRPCStoreSpec (addr ))
285
+ }
286
+
287
+ specs = removeDuplicateStoreSpecs (logger , duplicatedStores , specs )
288
+
251
289
return specs
252
290
},
253
291
dialOpts ,
@@ -271,6 +309,40 @@ func runQuery(
271
309
stores .Close ()
272
310
})
273
311
}
312
+ // Run File Service Discovery and update the store set when the files are modified.
313
+ if fileSD != nil {
314
+ var fileSDUpdates chan []* targetgroup.Group
315
+ ctxRun , cancelRun := context .WithCancel (context .Background ())
316
+
317
+ fileSDUpdates = make (chan []* targetgroup.Group )
318
+
319
+ g .Add (func () error {
320
+ fileSD .Run (ctxRun , fileSDUpdates )
321
+ return nil
322
+ }, func (error ) {
323
+ cancelRun ()
324
+ })
325
+
326
+ ctxUpdate , cancelUpdate := context .WithCancel (context .Background ())
327
+ g .Add (func () error {
328
+ for {
329
+ select {
330
+ case update := <- fileSDUpdates :
331
+ // Discoverers sometimes send nil updates so need to check for it to avoid panics.
332
+ if update == nil {
333
+ continue
334
+ }
335
+ fileSDCache .Update (update )
336
+ stores .Update (ctxUpdate )
337
+ case <- ctxUpdate .Done ():
338
+ return nil
339
+ }
340
+ }
341
+ }, func (error ) {
342
+ cancelUpdate ()
343
+ close (fileSDUpdates )
344
+ })
345
+ }
274
346
{
275
347
ctx , cancel := context .WithCancel (context .Background ())
276
348
g .Add (func () error {
@@ -340,6 +412,23 @@ func runQuery(
340
412
return nil
341
413
}
342
414
415
+ func removeDuplicateStoreSpecs (logger log.Logger , duplicatedStores prometheus.Counter , specs []query.StoreSpec ) []query.StoreSpec {
416
+ set := make (map [string ]query.StoreSpec )
417
+ for _ , spec := range specs {
418
+ addr := spec .Addr ()
419
+ if _ , ok := set [addr ]; ok {
420
+ level .Warn (logger ).Log ("msg" , "Duplicate store address is provided - %v" , addr )
421
+ duplicatedStores .Inc ()
422
+ }
423
+ set [addr ] = spec
424
+ }
425
+ deduplicated := make ([]query.StoreSpec , 0 , len (set ))
426
+ for _ , value := range set {
427
+ deduplicated = append (deduplicated , value )
428
+ }
429
+ return deduplicated
430
+ }
431
+
343
432
type gossipSpec struct {
344
433
id string
345
434
addr string
0 commit comments