From 4c1bf91117b14b90ed17bc39b91ec49d721d716a Mon Sep 17 00:00:00 2001 From: beorn7 Date: Tue, 4 Dec 2018 19:42:26 +0100 Subject: [PATCH] Remove legacy HTTP API Signed-off-by: beorn7 --- handler/delete.go | 39 ---------------- handler/handler_test.go | 81 ---------------------------------- handler/push.go | 98 ----------------------------------------- main.go | 8 ---- 4 files changed, 226 deletions(-) diff --git a/handler/delete.go b/handler/delete.go index e4513a64..c6b9821a 100644 --- a/handler/delete.go +++ b/handler/delete.go @@ -66,42 +66,3 @@ func Delete(ms storage.MetricStore) func(http.ResponseWriter, *http.Request, htt instrumentedHandler.ServeHTTP(w, r) } } - -// LegacyDelete returns a handler that accepts delete requests. It deals with -// the deprecated API. -// -// The returned handler is already instrumented for Prometheus. -func LegacyDelete(ms storage.MetricStore) func(http.ResponseWriter, *http.Request, httprouter.Params) { - var ps httprouter.Params - var mtx sync.Mutex // Protects ps. - - instrumentedHandler := promhttp.InstrumentHandlerCounter( - httpCnt.MustCurryWith(prometheus.Labels{"handler": "legacy_delete"}), - http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { - job := ps.ByName("job") - instance := ps.ByName("instance") - mtx.Unlock() - - if job == "" { - http.Error(w, "job name is required", http.StatusBadRequest) - log.Debug("job name is required") - return - } - labels := map[string]string{"job": job} - if instance != "" { - labels["instance"] = instance - } - ms.SubmitWriteRequest(storage.WriteRequest{ - Labels: labels, - Timestamp: time.Now(), - }) - w.WriteHeader(http.StatusAccepted) - }), - ) - - return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) { - mtx.Lock() - ps = params - instrumentedHandler.ServeHTTP(w, r) - } -} diff --git a/handler/handler_test.go b/handler/handler_test.go index c74c0443..3bacffa1 100644 --- a/handler/handler_test.go +++ b/handler/handler_test.go @@ -80,7 +80,6 @@ func TestHealthyReady(t *testing.T) { func TestPush(t *testing.T) { mms := MockMetricStore{} handler := Push(&mms, false) - legacyHandler := LegacyPush(&mms, false) req, err := http.NewRequest("POST", "http://example.org/", &bytes.Buffer{}) if err != nil { t.Fatal(err) @@ -113,23 +112,6 @@ func TestPush(t *testing.T) { t.Errorf("Wanted instance %v, got %v.", expected, got) } - // With job name, but no instance name and no content, legacy handler. - mms.lastWriteRequest = storage.WriteRequest{} - w = httptest.NewRecorder() - legacyHandler(w, req, httprouter.Params{httprouter.Param{Key: "job", Value: "testjob"}}) - if expected, got := http.StatusAccepted, w.Code; expected != got { - t.Errorf("Wanted status code %v, got %v.", expected, got) - } - if mms.lastWriteRequest.Timestamp.IsZero() { - t.Errorf("Write request timestamp not set: %#v", mms.lastWriteRequest) - } - if expected, got := "testjob", mms.lastWriteRequest.Labels["job"]; expected != got { - t.Errorf("Wanted job %v, got %v.", expected, got) - } - if expected, got := "localhost", mms.lastWriteRequest.Labels["instance"]; expected != got { - t.Errorf("Wanted instance %v, got %v.", expected, got) - } - // With job name and instance name and invalid text content. mms.lastWriteRequest = storage.WriteRequest{} req, err = http.NewRequest( @@ -252,69 +234,6 @@ func TestPush(t *testing.T) { t.Errorf("Write request timestamp unexpectedly set: %#v", mms.lastWriteRequest) } - // With job name and instance name and text content, legacy handler. - mms.lastWriteRequest = storage.WriteRequest{} - req, err = http.NewRequest( - "POST", "http://example.org/", - bytes.NewBufferString("some_metric 3.14\nanother_metric 42\n"), - ) - if err != nil { - t.Fatal(err) - } - w = httptest.NewRecorder() - legacyHandler( - w, req, - httprouter.Params{ - httprouter.Param{Key: "job", Value: "testjob"}, - httprouter.Param{Key: "instance", Value: "testinstance"}, - }, - ) - if expected, got := http.StatusAccepted, w.Code; expected != got { - t.Errorf("Wanted status code %v, got %v.", expected, got) - } - if mms.lastWriteRequest.Timestamp.IsZero() { - t.Errorf("Write request timestamp not set: %#v", mms.lastWriteRequest) - } - if expected, got := "testjob", mms.lastWriteRequest.Labels["job"]; expected != got { - t.Errorf("Wanted job %v, got %v.", expected, got) - } - if expected, got := "testinstance", mms.lastWriteRequest.Labels["instance"]; expected != got { - t.Errorf("Wanted instance %v, got %v.", expected, got) - } - if expected, got := `name:"some_metric" type:UNTYPED metric: label: untyped: > `, mms.lastWriteRequest.MetricFamilies["some_metric"].String(); expected != got { - t.Errorf("Wanted metric family %v, got %v.", expected, got) - } - if expected, got := `name:"another_metric" type:UNTYPED metric: label: untyped: > `, mms.lastWriteRequest.MetricFamilies["another_metric"].String(); expected != got { - t.Errorf("Wanted metric family %v, got %v.", expected, got) - } - if _, ok := mms.lastWriteRequest.MetricFamilies["push_time_seconds"]; !ok { - t.Errorf("Wanted metric family push_time_seconds missing.") - } - - // With job name and instance name and timestamp, legacy handler. - mms.lastWriteRequest = storage.WriteRequest{} - req, err = http.NewRequest( - "POST", "http://example.org/", - bytes.NewBufferString("a 1\nb 1 1000\n"), - ) - if err != nil { - t.Fatal(err) - } - w = httptest.NewRecorder() - legacyHandler( - w, req, - httprouter.Params{ - httprouter.Param{Key: "job", Value: "testjob"}, - httprouter.Param{Key: "instance", Value: "testinstance"}, - }, - ) - if expected, got := http.StatusBadRequest, w.Code; expected != got { - t.Errorf("Wanted status code %v, got %v.", expected, got) - } - if !mms.lastWriteRequest.Timestamp.IsZero() { - t.Errorf("Write request timestamp unexpectedly set: %#v", mms.lastWriteRequest) - } - // With job name and instance name and text content and job and instance labels. mms.lastWriteRequest = storage.WriteRequest{} req, err = http.NewRequest( diff --git a/handler/push.go b/handler/push.go index 458dea89..ba0bb3b5 100644 --- a/handler/push.go +++ b/handler/push.go @@ -17,7 +17,6 @@ import ( "fmt" "io" "mime" - "net" "net/http" "sort" "strings" @@ -137,103 +136,6 @@ func Push( } } -// LegacyPush returns an http.Handler which accepts samples over HTTP and stores -// them in the MetricStore. It uses the deprecated API (expecting a 'job' -// parameter and an optional 'instance' parameter). If replace is true, all -// metrics for the job and instance given by the request are deleted before new -// ones are stored. -// -// The returned handler is already instrumented for Prometheus. -func LegacyPush( - ms storage.MetricStore, replace bool, -) func(http.ResponseWriter, *http.Request, httprouter.Params) { - var ps httprouter.Params - var mtx sync.Mutex // Protects ps. - - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - job := ps.ByName("job") - instance := ps.ByName("instance") - mtx.Unlock() - - var err error - if job == "" { - http.Error(w, "job name is required", http.StatusBadRequest) - log.Debug("job name is required") - return - } - if instance == "" { - // Remote IP number (without port). - instance, _, err = net.SplitHostPort(r.RemoteAddr) - if err != nil || instance == "" { - instance = "localhost" - } - } - labels := map[string]string{"job": job, "instance": instance} - if replace { - ms.SubmitWriteRequest(storage.WriteRequest{ - Labels: labels, - Timestamp: time.Now(), - }) - } - - var metricFamilies map[string]*dto.MetricFamily - ctMediatype, ctParams, ctErr := mime.ParseMediaType(r.Header.Get("Content-Type")) - if ctErr == nil && ctMediatype == "application/vnd.google.protobuf" && - ctParams["encoding"] == "delimited" && - ctParams["proto"] == "io.prometheus.client.MetricFamily" { - metricFamilies = map[string]*dto.MetricFamily{} - for { - mf := &dto.MetricFamily{} - if _, err = pbutil.ReadDelimited(r.Body, mf); err != nil { - if err == io.EOF { - err = nil - } - break - } - metricFamilies[mf.GetName()] = mf - } - } else { - // We could do further content-type checks here, but the - // fallback for now will anyway be the text format - // version 0.0.4, so just go for it and see if it works. - var parser expfmt.TextParser - metricFamilies, err = parser.TextToMetricFamilies(r.Body) - } - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - log.Debugf("Error parsing request body, %v", err.Error()) - return - } - if timestampsPresent(metricFamilies) { - http.Error(w, "pushed metrics must not have timestamps", http.StatusBadRequest) - log.Debug("pushed metrics must not have timestamps") - return - } - now := time.Now() - addPushTimestamp(metricFamilies, now) - sanitizeLabels(metricFamilies, labels) - ms.SubmitWriteRequest(storage.WriteRequest{ - Labels: labels, - Timestamp: now, - MetricFamilies: metricFamilies, - }) - w.WriteHeader(http.StatusAccepted) - }) - - instrumentedHandler := promhttp.InstrumentHandlerRequestSize( - httpPushSize, promhttp.InstrumentHandlerDuration( - httpPushDuration, promhttp.InstrumentHandlerCounter( - httpCnt.MustCurryWith(prometheus.Labels{"handler": "legacy_push"}), - handler, - ))) - - return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) { - mtx.Lock() - ps = params - instrumentedHandler.ServeHTTP(w, r) - } -} - // sanitizeLabels ensures that all the labels in groupingLabels and the // `instance` label are present in each MetricFamily in metricFamilies. The // label values from groupingLabels are set in each MetricFamily, no matter diff --git a/main.go b/main.go index 27ed4095..c42a1fde 100644 --- a/main.go +++ b/main.go @@ -96,14 +96,6 @@ func main() { r.POST(pushAPIPath+"/job/:job", handler.Push(ms, false)) r.DELETE(pushAPIPath+"/job/:job", handler.Delete(ms)) - // Handlers for the deprecated API. - r.PUT(pushAPIPath+"/jobs/:job/instances/:instance", handler.LegacyPush(ms, true)) - r.POST(pushAPIPath+"/jobs/:job/instances/:instance", handler.LegacyPush(ms, false)) - r.DELETE(pushAPIPath+"/jobs/:job/instances/:instance", handler.LegacyDelete(ms)) - r.PUT(pushAPIPath+"/jobs/:job", handler.LegacyPush(ms, true)) - r.POST(pushAPIPath+"/jobs/:job", handler.LegacyPush(ms, false)) - r.DELETE(pushAPIPath+"/jobs/:job", handler.LegacyDelete(ms)) - r.Handler("GET", *routePrefix+"/static/*filepath", handler.Static(asset.Assets)) statusHandler := handler.Status(ms, asset.Assets, flags)