Beispiel #1
0
func (s *Server) route() {
	s.r = mux.NewRouter().StrictSlash(true)
	s.r.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		s.serveErrorPage("page not found", http.StatusNotFound, w, r)
	})

	s.r.Path("/").Methods("OPTIONS").HandlerFunc(s.handleProbe)
	s.r.Path("/robots.txt").HandlerFunc(s.handleRobotsTxt)
	s.r.Path("/metrics").Handler(
		prometheus.InstrumentHandler("metrics", prometheus.UninstrumentedHandler()))

	s.r.PathPrefix("/static/").Handler(
		prometheus.InstrumentHandler("static", http.HandlerFunc(s.handleStatic)))

	s.r.Handle("/", prometheus.InstrumentHandlerFunc("home", s.handleHomeStatic))

	s.r.PathPrefix("/about").Handler(
		prometheus.InstrumentHandler("about", http.HandlerFunc(s.handleAboutStatic)))

	s.r.HandleFunc("/room/{prefix:(pm:)?}{room:[a-z0-9]+}/ws", instrumentSocketHandlerFunc("ws", s.handleRoom))
	s.r.Handle(
		"/room/{prefix:(pm:)?}{room:[a-z0-9]+}/", prometheus.InstrumentHandlerFunc("room_static", s.handleRoomStatic))

	s.r.Handle(
		"/prefs/reset-password",
		prometheus.InstrumentHandlerFunc("prefsResetPassword", s.handlePrefsResetPassword))
	s.r.Handle(
		"/prefs/verify", prometheus.InstrumentHandlerFunc("prefsVerify", s.handlePrefsVerify))
}
Beispiel #2
0
func (s *Server) route() {
	s.r = mux.NewRouter().StrictSlash(true)
	s.r.Path("/").Methods("OPTIONS").HandlerFunc(s.handleProbe)
	s.r.Path("/robots.txt").HandlerFunc(s.handleRobotsTxt)
	s.r.Path("/metrics").Handler(
		prometheus.InstrumentHandler("metrics", prometheus.UninstrumentedHandler()))

	s.r.PathPrefix("/static/").Handler(
		prometheus.InstrumentHandler("static", http.StripPrefix("/static", http.HandlerFunc(s.handleStatic))))

	s.r.Handle("/", prometheus.InstrumentHandlerFunc("home", s.handleHomeStatic))

	s.r.PathPrefix("/about").Handler(
		prometheus.InstrumentHandler("about", http.HandlerFunc(s.handleAboutStatic)))

	s.r.HandleFunc("/room/{room:[a-z0-9]+}/ws", instrumentSocketHandlerFunc("ws", s.handleRoom))
	s.r.Handle(
		"/room/{room:[a-z0-9]+}/", prometheus.InstrumentHandlerFunc("room_static", s.handleRoomStatic))

	s.r.Handle(
		"/prefs/reset-password",
		prometheus.InstrumentHandlerFunc("prefsResetPassword", s.handleResetPassword))
	s.r.Handle(
		"/prefs/verify", prometheus.InstrumentHandlerFunc("prefsVerify", s.handlePrefsVerify))
}
// 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.

	instrumentedHandlerFunc := prometheus.InstrumentHandlerFunc(
		"delete",
		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)
				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
		instrumentedHandlerFunc(w, r)
	}
}
// Delete returns a handler that accepts delete requests.
//
// The returned handler is already instrumented for Prometheus.
func Delete(ms storage.MetricStore) func(http.ResponseWriter, *http.Request, httprouter.Params) {
	var ps httprouter.Params
	var mtx sync.Mutex // Protects ps.

	instrumentedHandlerFunc := prometheus.InstrumentHandlerFunc(
		"delete",
		func(w http.ResponseWriter, _ *http.Request) {
			job := ps.ByName("job")
			labelsString := ps.ByName("labels")
			mtx.Unlock()

			labels, err := splitLabels(labelsString)
			if err != nil {
				http.Error(w, err.Error(), http.StatusBadRequest)
				return
			}
			if job == "" {
				http.Error(w, "job name is required", http.StatusBadRequest)
				return
			}
			labels["job"] = job
			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
		instrumentedHandlerFunc(w, r)
	}
}
Beispiel #5
0
// Register registers the API handlers under their correct routes
// in the given router.
func (api *API) Register(r *route.Router) {
	ihf := func(name string, f http.HandlerFunc) http.HandlerFunc {
		return prometheus.InstrumentHandlerFunc(name, func(w http.ResponseWriter, r *http.Request) {
			setCORS(w)
			f(w, r)
		})
	}

	r.Options("/*path", ihf("options", func(w http.ResponseWriter, r *http.Request) {}))

	// Register legacy forwarder for alert pushing.
	r.Post("/alerts", ihf("legacy_add_alerts", api.legacyAddAlerts))

	// Register actual API.
	r = r.WithPrefix("/v1")

	r.Get("/status", ihf("status", api.status))
	r.Get("/alerts/groups", ihf("alert_groups", api.alertGroups))

	r.Get("/alerts", ihf("list_alerts", api.listAlerts))
	r.Post("/alerts", ihf("add_alerts", api.addAlerts))

	r.Get("/silences", ihf("list_silences", api.listSilences))
	r.Post("/silences", ihf("add_silence", api.addSilence))
	r.Get("/silence/:sid", ihf("get_silence", api.getSilence))
	r.Del("/silence/:sid", ihf("del_silence", api.delSilence))
}
Beispiel #6
0
// Endpoints is a listing of all endpoints available in the svc.
func (s *svc) Endpoints() map[string]map[string]http.HandlerFunc {
	dirs := s.conf.GetDirectives()
	authenticator := lib.NewAuthenticator(dirs.Server.JWTSecret, dirs.Server.JWTSigningMethod)
	return map[string]map[string]http.HandlerFunc{
		"/metrics": {
			"GET": func(w http.ResponseWriter, r *http.Request) {
				prometheus.Handler().ServeHTTP(w, r)
			},
		},
		"/upload/{path:.*}": {
			"PUT": prometheus.InstrumentHandlerFunc("/upload", authenticator.JWTHandlerFunc(s.Upload)),
		},
		"/download/{path:.*}": {
			"GET": prometheus.InstrumentHandlerFunc("/download", authenticator.JWTHandlerFunc(s.Download)),
		},
	}
}
Beispiel #7
0
// Endpoints is a listing of all endpoints available in the Mixedsvc.
func (s *svc) Endpoints() map[string]map[string]http.HandlerFunc {
	dirs := s.conf.GetDirectives()
	authenticator := lib.NewAuthenticator(dirs.Server.JWTSecret, dirs.Server.JWTSigningMethod)

	return map[string]map[string]http.HandlerFunc{
		"/metrics": {
			"GET": func(w http.ResponseWriter, r *http.Request) {
				prometheus.Handler().ServeHTTP(w, r)
			},
		},
		"/token": {
			"POST": prometheus.InstrumentHandlerFunc("/token", s.Token),
		},
		"/ping": {
			"GET": prometheus.InstrumentHandlerFunc("/ping", authenticator.JWTHandlerFunc(s.Ping)),
		},
	}
}
func (s *ServerContext) ServeHTTP(w http.ResponseWriter, req *http.Request) {

	log.Printf("Request: %s  %s", req.Method, req.URL.Path)

	switch req.URL.Path {
	case *metricsEndpoint:
		prometheus.Handler().ServeHTTP(w, req)
	case *annoEndpoint:
		prometheus.InstrumentHandlerFunc(*annoEndpoint, s.annotations)(w, req)
	default:
		http.Error(w, "Not found", 404)
	}
}
Beispiel #9
0
func instrumentSocketHandlerFunc(name string, handler http.HandlerFunc) http.HandlerFunc {
	type hijackerKey int
	var k hijackerKey

	loadHijacker := func(w http.ResponseWriter, r *http.Request) {
		if hj, ok := gorillactx.GetOk(r, k); ok {
			w = &hijackResponseWriter{ResponseWriter: w, Hijacker: hj.(http.Hijacker)}
		}
		handler(w, r)
	}

	promHandler := prometheus.InstrumentHandlerFunc(name, loadHijacker)

	saveHijacker := func(w http.ResponseWriter, r *http.Request) {
		if hj, ok := w.(http.Hijacker); ok {
			gorillactx.Set(r, k, hj)
		}
		promHandler(w, r)
	}

	return saveHijacker
}
Beispiel #10
0
func (w WebService) ServeForever(pathPrefix string) error {

	http.Handle(pathPrefix+"favicon.ico", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "", 404)
	}))

	http.HandleFunc("/", prometheus.InstrumentHandlerFunc("index", func(rw http.ResponseWriter, req *http.Request) {
		// The "/" pattern matches everything, so we need to check
		// that we're at the root here.
		if req.URL.Path == pathPrefix {
			w.AlertsHandler.ServeHTTP(rw, req)
		} else if req.URL.Path == strings.TrimRight(pathPrefix, "/") {
			http.Redirect(rw, req, pathPrefix, http.StatusFound)
		} else if !strings.HasPrefix(req.URL.Path, pathPrefix) {
			// We're running under a prefix but the user requested something
			// outside of it. Let's see if this page exists under the prefix.
			http.Redirect(rw, req, pathPrefix+strings.TrimLeft(req.URL.Path, "/"), http.StatusFound)
		} else {
			http.NotFound(rw, req)
		}
	}))

	http.Handle(pathPrefix+"alerts", prometheus.InstrumentHandler("alerts", w.AlertsHandler))
	http.Handle(pathPrefix+"silences", prometheus.InstrumentHandler("silences", w.SilencesHandler))
	http.Handle(pathPrefix+"status", prometheus.InstrumentHandler("status", w.StatusHandler))

	http.Handle(pathPrefix+"metrics", prometheus.Handler())
	if *useLocalAssets {
		http.Handle(pathPrefix+"static/", http.StripPrefix(pathPrefix+"static/", http.FileServer(http.Dir("web/static"))))
	} else {
		http.Handle(pathPrefix+"static/", http.StripPrefix(pathPrefix+"static/", new(blob.Handler)))
	}
	http.Handle(pathPrefix+"api/", w.AlertManagerService.Handler())

	log.Info("listening on ", *listenAddress)

	return http.ListenAndServe(*listenAddress, nil)
}
Beispiel #11
0
// Register the API's endpoints in the given router.
func (api *API) Register(r *route.Router) {
	if api.context == nil {
		api.context = route.Context
	}

	instr := func(name string, f apiFunc) http.HandlerFunc {
		return prometheus.InstrumentHandlerFunc(name, func(w http.ResponseWriter, r *http.Request) {
			setCORS(w)
			if data, err := f(r); err != nil {
				respondError(w, err, data)
			} else {
				respond(w, data)
			}
		})
	}

	r.Get("/query", instr("query", api.query))
	r.Get("/query_range", instr("query_range", api.queryRange))

	r.Get("/label/:name/values", instr("label_values", api.labelValues))

	r.Get("/series", instr("series", api.series))
	r.Del("/series", instr("drop_series", api.dropSeries))
}
Beispiel #12
0
// Push returns an http.Handler which accepts samples over HTTP and stores them
// in the MetricStore. 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 Push(
	ms storage.MetricStore, replace bool,
) func(http.ResponseWriter, *http.Request, httprouter.Params) {
	var ps httprouter.Params
	var mtx sync.Mutex // Protects ps.

	instrumentedHandlerFunc := prometheus.InstrumentHandlerFunc(
		"push",
		func(w http.ResponseWriter, r *http.Request) {
			job := ps.ByName("job")
			labelsString := ps.ByName("labels")
			mtx.Unlock()

			labels, err := splitLabels(labelsString)
			if err != nil {
				http.Error(w, err.Error(), http.StatusBadRequest)
				return
			}
			if job == "" {
				http.Error(w, "job name is required", http.StatusBadRequest)
				return
			}
			labels["job"] = job

			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 text.Parser
				metricFamilies, err = parser.TextToMetricFamilies(r.Body)
			}
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			sanitizeLabels(metricFamilies, labels)
			ms.SubmitWriteRequest(storage.WriteRequest{
				Labels:         labels,
				Timestamp:      time.Now(),
				MetricFamilies: metricFamilies,
			})
			w.WriteHeader(http.StatusAccepted)
		},
	)

	return func(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
		mtx.Lock()
		ps = params
		instrumentedHandlerFunc(w, r)
	}
}
Beispiel #13
0
// Endpoints is a listing of all endpoints available in the svc.
func (s *svc) Endpoints() map[string]map[string]http.HandlerFunc {

	return map[string]map[string]http.HandlerFunc{
		"/metrics": {
			"GET": func(w http.ResponseWriter, r *http.Request) {
				prometheus.Handler().ServeHTTP(w, r)
			},
		},
		"/home/{path:.*}": {
			"GET":       prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Get)),
			"PUT":       prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Put)),
			"OPTIONS":   prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Options)),
			"LOCK":      prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Lock)),
			"UNLOCK":    prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Unlock)),
			"HEAD":      prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Head)),
			"MKCOL":     prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Mkcol)),
			"PROPPATCH": prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Proppatch)),
			"PROPFIND":  prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Propfind)),
			"DELETE":    prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Delete)),
			"MOVE":      prometheus.InstrumentHandlerFunc("/home", s.basicAuthHandlerFunc(s.Move)),
		},
	}
}
Beispiel #14
0
func main() {
	flag.Parse()

	if *showVersion {
		fmt.Fprintln(os.Stdout, version.Print("pushgateway"))
		os.Exit(0)
	}

	log.Infoln("Starting pushgateway", version.Info())
	log.Infoln("Build context", version.BuildContext())

	flags := map[string]string{}
	flag.VisitAll(func(f *flag.Flag) {
		flags[f.Name] = f.Value.String()
	})

	ms := storage.NewDiskMetricStore(*persistenceFile, *persistenceInterval)
	prometheus.SetMetricFamilyInjectionHook(ms.GetMetricFamilies)
	// Enable collect checks for debugging.
	// prometheus.EnableCollectChecks(true)

	r := httprouter.New()
	r.Handler("GET", *metricsPath, prometheus.Handler())

	// Handlers for pushing and deleting metrics.
	r.PUT("/metrics/job/:job/*labels", handler.Push(ms, true))
	r.POST("/metrics/job/:job/*labels", handler.Push(ms, false))
	r.DELETE("/metrics/job/:job/*labels", handler.Delete(ms))
	r.PUT("/metrics/job/:job", handler.Push(ms, true))
	r.POST("/metrics/job/:job", handler.Push(ms, false))
	r.DELETE("/metrics/job/:job", handler.Delete(ms))

	// Handlers for the deprecated API.
	r.PUT("/metrics/jobs/:job/instances/:instance", handler.LegacyPush(ms, true))
	r.POST("/metrics/jobs/:job/instances/:instance", handler.LegacyPush(ms, false))
	r.DELETE("/metrics/jobs/:job/instances/:instance", handler.LegacyDelete(ms))
	r.PUT("/metrics/jobs/:job", handler.LegacyPush(ms, true))
	r.POST("/metrics/jobs/:job", handler.LegacyPush(ms, false))
	r.DELETE("/metrics/jobs/:job", handler.LegacyDelete(ms))

	r.Handler("GET", "/static/*filepath", prometheus.InstrumentHandler(
		"static",
		http.FileServer(
			&assetfs.AssetFS{Asset: Asset, AssetDir: AssetDir, AssetInfo: AssetInfo},
		),
	))
	statusHandler := prometheus.InstrumentHandlerFunc("status", handler.Status(ms, Asset, flags))
	r.Handler("GET", "/status", statusHandler)
	r.Handler("GET", "/", statusHandler)

	// Re-enable pprof.
	r.GET("/debug/pprof/*pprof", handlePprof)

	log.Infof("Listening on %s.", *listenAddress)
	l, err := net.Listen("tcp", *listenAddress)
	if err != nil {
		log.Fatal(err)
	}
	go interruptHandler(l)
	err = (&http.Server{Addr: *listenAddress, Handler: r}).Serve(l)
	log.Errorln("HTTP server stopped:", err)
	// To give running connections a chance to submit their payload, we wait
	// for 1sec, but we don't want to wait long (e.g. until all connections
	// are done) to not delay the shutdown.
	time.Sleep(time.Second)
	if err := ms.Shutdown(); err != nil {
		log.Errorln("Problem shutting down metric storage:", err)
	}
}
Beispiel #15
0
// Endpoints is a listing of all endpoints available in the svc.
func (s *svc) Endpoints() map[string]map[string]http.HandlerFunc {

	return map[string]map[string]http.HandlerFunc{
		"/status.php": {
			"GET": prometheus.InstrumentHandlerFunc("/status.php", s.Status),
		},
		"/ocs/v1.php/cloud/capabilities": {
			"GET": prometheus.InstrumentHandlerFunc("/ocs/v1.php/cloud/capabilities", s.Capabilities),
		},
		"/remote.php/webdav/{path:.*}": {
			"GET":       prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Get)),
			"PUT":       prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Put)),
			"OPTIONS":   prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Options)),
			"LOCK":      prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Lock)),
			"UNLOCK":    prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Unlock)),
			"HEAD":      prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Head)),
			"MKCOL":     prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Mkcol)),
			"PROPPATCH": prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Proppatch)),
			"PROPFIND":  prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Propfind)),
			"DELETE":    prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Delete)),
			"MOVE":      prometheus.InstrumentHandlerFunc("/remote.php/webdav", s.basicAuthHandlerFunc(s.Move)),
		},
	}
}