github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/querier/chunks_handler.go (about) 1 package querier 2 3 import ( 4 "archive/tar" 5 "compress/gzip" 6 "net/http" 7 8 "github.com/prometheus/common/model" 9 "github.com/prometheus/prometheus/promql/parser" 10 "github.com/prometheus/prometheus/storage" 11 12 "github.com/cortexproject/cortex/pkg/querier/chunkstore" 13 "github.com/cortexproject/cortex/pkg/tenant" 14 "github.com/cortexproject/cortex/pkg/util" 15 ) 16 17 // ChunksHandler allows you to fetch a compressed tar of all the chunks for a 18 // given time range and set of matchers. 19 // Only works with the new unified chunk querier, which is enabled when you turn 20 // on ingester chunk query streaming. 21 func ChunksHandler(queryable storage.Queryable) http.Handler { 22 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 23 userID, err := tenant.TenantID(r.Context()) 24 if err != nil { 25 http.Error(w, err.Error(), http.StatusBadRequest) 26 return 27 } 28 mint, err := util.ParseTime(r.FormValue("start")) 29 if err != nil { 30 http.Error(w, err.Error(), http.StatusBadRequest) 31 return 32 } 33 34 maxt, err := util.ParseTime(r.FormValue("end")) 35 if err != nil { 36 http.Error(w, err.Error(), http.StatusBadRequest) 37 return 38 } 39 40 matchers, err := parser.ParseMetricSelector(r.FormValue("matcher")) 41 if err != nil { 42 http.Error(w, err.Error(), http.StatusBadRequest) 43 return 44 } 45 46 querier, err := queryable.Querier(r.Context(), mint, maxt) 47 if err != nil { 48 http.Error(w, err.Error(), http.StatusInternalServerError) 49 return 50 } 51 52 store, ok := querier.(chunkstore.ChunkStore) 53 if !ok { 54 http.Error(w, "not supported", http.StatusServiceUnavailable) 55 return 56 } 57 58 chunks, err := store.Get(r.Context(), userID, model.Time(mint), model.Time(maxt), matchers...) 59 if err != nil { 60 http.Error(w, err.Error(), http.StatusInternalServerError) 61 return 62 } 63 64 w.Header().Add("Content-Type", "application/tar+gzip") 65 gw := gzip.NewWriter(w) 66 defer gw.Close() 67 68 writer := tar.NewWriter(gw) 69 defer writer.Close() 70 71 for _, chunk := range chunks { 72 buf, err := chunk.Encoded() 73 if err != nil { 74 http.Error(w, err.Error(), http.StatusInternalServerError) 75 return 76 } 77 78 if err := writer.WriteHeader(&tar.Header{ 79 Name: chunk.ExternalKey(), 80 Size: int64(len(buf)), 81 Mode: 0600, 82 }); err != nil { 83 http.Error(w, err.Error(), http.StatusInternalServerError) 84 return 85 } 86 87 if _, err := writer.Write(buf); err != nil { 88 http.Error(w, err.Error(), http.StatusInternalServerError) 89 return 90 } 91 } 92 }) 93 }