web/api: enable running API legacy and v1 in parallel
This commit is contained in:
parent
ab9c98acac
commit
5b713911e3
13
main.go
13
main.go
|
@ -41,7 +41,8 @@ import (
|
|||
"github.com/prometheus/prometheus/storage/remote/influxdb"
|
||||
"github.com/prometheus/prometheus/storage/remote/opentsdb"
|
||||
"github.com/prometheus/prometheus/web"
|
||||
"github.com/prometheus/prometheus/web/api"
|
||||
"github.com/prometheus/prometheus/web/api/legacy"
|
||||
"github.com/prometheus/prometheus/web/api/v1"
|
||||
)
|
||||
|
||||
const deletionBatchSize = 100
|
||||
|
@ -184,16 +185,22 @@ func NewPrometheus() *prometheus {
|
|||
PathPrefix: *pathPrefix,
|
||||
}
|
||||
|
||||
metricsService := &api.MetricsService{
|
||||
apiLegacy := &legacy.API{
|
||||
Now: clientmodel.Now,
|
||||
Storage: memStorage,
|
||||
QueryEngine: queryEngine,
|
||||
}
|
||||
|
||||
apiv1 := &v1.API{
|
||||
Storage: memStorage,
|
||||
QueryEngine: queryEngine,
|
||||
}
|
||||
|
||||
webService := web.NewWebService(&web.WebServiceOptions{
|
||||
PathPrefix: *pathPrefix,
|
||||
StatusHandler: prometheusStatus,
|
||||
MetricsHandler: metricsService,
|
||||
APILegacy: apiLegacy,
|
||||
APIv1: apiv1,
|
||||
ConsolesHandler: consolesHandler,
|
||||
AlertsHandler: alertsHandler,
|
||||
GraphsHandler: graphsHandler,
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package api
|
||||
package legacy
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
@ -26,18 +26,18 @@ import (
|
|||
"github.com/prometheus/prometheus/util/route"
|
||||
)
|
||||
|
||||
// MetricsService manages the /api HTTP endpoint.
|
||||
type MetricsService struct {
|
||||
// API manages the /api HTTP endpoint.
|
||||
type API struct {
|
||||
Now func() clientmodel.Timestamp
|
||||
Storage local.Storage
|
||||
QueryEngine *promql.Engine
|
||||
}
|
||||
|
||||
// RegisterHandler registers the handler for the various endpoints below /api.
|
||||
func (msrv *MetricsService) RegisterHandler(router *route.Router) {
|
||||
router.Get("/query", handle("query", msrv.Query))
|
||||
router.Get("/query_range", handle("query_range", msrv.QueryRange))
|
||||
router.Get("/metrics", handle("metrics", msrv.Metrics))
|
||||
func (api *API) Register(router *route.Router) {
|
||||
router.Get("/query", handle("query", api.Query))
|
||||
router.Get("/query_range", handle("query_range", api.QueryRange))
|
||||
router.Get("/metrics", handle("metrics", api.Metrics))
|
||||
}
|
||||
|
||||
func handle(name string, f http.HandlerFunc) http.HandlerFunc {
|
|
@ -11,7 +11,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package api
|
||||
package legacy
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
@ -93,13 +93,13 @@ func TestQuery(t *testing.T) {
|
|||
})
|
||||
storage.WaitForIndexing()
|
||||
|
||||
api := MetricsService{
|
||||
api := &API{
|
||||
Now: testNow,
|
||||
Storage: storage,
|
||||
QueryEngine: promql.NewEngine(storage),
|
||||
}
|
||||
rtr := route.New()
|
||||
api.RegisterHandler(rtr.WithPrefix("/api"))
|
||||
api.Register(rtr.WithPrefix("/api"))
|
||||
|
||||
server := httptest.NewServer(rtr)
|
||||
defer server.Close()
|
|
@ -11,7 +11,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package api
|
||||
package legacy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -63,20 +63,20 @@ func parseDuration(d string) (time.Duration, error) {
|
|||
}
|
||||
|
||||
// Query handles the /api/query endpoint.
|
||||
func (serv MetricsService) Query(w http.ResponseWriter, r *http.Request) {
|
||||
func (api *API) Query(w http.ResponseWriter, r *http.Request) {
|
||||
setAccessControlHeaders(w)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
params := httputil.GetQueryParams(r)
|
||||
expr := params.Get("expr")
|
||||
|
||||
timestamp, err := parseTimestampOrNow(params.Get("timestamp"), serv.Now())
|
||||
timestamp, err := parseTimestampOrNow(params.Get("timestamp"), api.Now())
|
||||
if err != nil {
|
||||
httpJSONError(w, fmt.Errorf("invalid query timestamp %s", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
query, err := serv.QueryEngine.NewInstantQuery(expr, timestamp)
|
||||
query, err := api.QueryEngine.NewInstantQuery(expr, timestamp)
|
||||
if err != nil {
|
||||
httpJSONError(w, err, http.StatusOK)
|
||||
return
|
||||
|
@ -92,7 +92,7 @@ func (serv MetricsService) Query(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// QueryRange handles the /api/query_range endpoint.
|
||||
func (serv MetricsService) QueryRange(w http.ResponseWriter, r *http.Request) {
|
||||
func (api *API) QueryRange(w http.ResponseWriter, r *http.Request) {
|
||||
setAccessControlHeaders(w)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
|
@ -111,7 +111,7 @@ func (serv MetricsService) QueryRange(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
end, err := parseTimestampOrNow(params.Get("end"), serv.Now())
|
||||
end, err := parseTimestampOrNow(params.Get("end"), api.Now())
|
||||
if err != nil {
|
||||
httpJSONError(w, fmt.Errorf("invalid query timestamp: %s", err), http.StatusBadRequest)
|
||||
return
|
||||
|
@ -121,7 +121,7 @@ func (serv MetricsService) QueryRange(w http.ResponseWriter, r *http.Request) {
|
|||
// the current time as the end time. Instead, the "end" parameter should
|
||||
// simply be omitted or set to an empty string for that case.
|
||||
if end == 0 {
|
||||
end = serv.Now()
|
||||
end = api.Now()
|
||||
}
|
||||
|
||||
// For safety, limit the number of returned points per timeseries.
|
||||
|
@ -136,7 +136,7 @@ func (serv MetricsService) QueryRange(w http.ResponseWriter, r *http.Request) {
|
|||
end = end.Add(-time.Duration(end.UnixNano() % int64(step)))
|
||||
start := end.Add(-duration)
|
||||
|
||||
query, err := serv.QueryEngine.NewRangeQuery(expr, start, end, step)
|
||||
query, err := api.QueryEngine.NewRangeQuery(expr, start, end, step)
|
||||
if err != nil {
|
||||
httpJSONError(w, err, http.StatusOK)
|
||||
return
|
||||
|
@ -152,11 +152,11 @@ func (serv MetricsService) QueryRange(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// Metrics handles the /api/metrics endpoint.
|
||||
func (serv MetricsService) Metrics(w http.ResponseWriter, r *http.Request) {
|
||||
func (api *API) Metrics(w http.ResponseWriter, r *http.Request) {
|
||||
setAccessControlHeaders(w)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
metricNames := serv.Storage.LabelValuesForLabelName(clientmodel.MetricNameLabel)
|
||||
metricNames := api.Storage.LabelValuesForLabelName(clientmodel.MetricNameLabel)
|
||||
sort.Sort(metricNames)
|
||||
resultBytes, err := json.Marshal(metricNames)
|
||||
if err != nil {
|
|
@ -11,7 +11,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package api
|
||||
package legacy
|
||||
|
||||
import (
|
||||
"testing"
|
18
web/web.go
18
web/web.go
|
@ -26,13 +26,14 @@ import (
|
|||
|
||||
pprof_runtime "runtime/pprof"
|
||||
|
||||
clientmodel "github.com/prometheus/client_golang/model"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/log"
|
||||
|
||||
"github.com/prometheus/prometheus/web/api/legacy"
|
||||
"github.com/prometheus/prometheus/web/api/v1"
|
||||
|
||||
"github.com/prometheus/prometheus/util/route"
|
||||
|
||||
clientmodel "github.com/prometheus/client_golang/model"
|
||||
|
||||
"github.com/prometheus/prometheus/web/api"
|
||||
"github.com/prometheus/prometheus/web/blob"
|
||||
)
|
||||
|
||||
|
@ -57,7 +58,8 @@ type WebService struct {
|
|||
type WebServiceOptions struct {
|
||||
PathPrefix string
|
||||
StatusHandler *PrometheusStatusHandler
|
||||
MetricsHandler *api.MetricsService
|
||||
APILegacy *legacy.API
|
||||
APIv1 *v1.API
|
||||
AlertsHandler *AlertsHandler
|
||||
ConsolesHandler *ConsolesHandler
|
||||
GraphsHandler *GraphsHandler
|
||||
|
@ -75,7 +77,7 @@ func NewWebService(o *WebServiceOptions) *WebService {
|
|||
if o.PathPrefix != "" {
|
||||
// If the prefix is missing for the root path, append it.
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, o.PathPrefix, 301)
|
||||
http.Redirect(w, r, o.PathPrefix, 302)
|
||||
})
|
||||
router = router.WithPrefix(o.PathPrefix)
|
||||
}
|
||||
|
@ -89,7 +91,9 @@ func NewWebService(o *WebServiceOptions) *WebService {
|
|||
|
||||
router.Get(*metricsPath, prometheus.Handler().ServeHTTP)
|
||||
|
||||
o.MetricsHandler.RegisterHandler(router.WithPrefix("/api"))
|
||||
o.APILegacy.Register(router.WithPrefix("/api"))
|
||||
|
||||
o.APIv1.Register(router.WithPrefix("/api/v1"))
|
||||
|
||||
router.Get("/consoles/*filepath", instr("consoles", o.ConsolesHandler))
|
||||
|
||||
|
|
Loading…
Reference in New Issue