func JSON(h func(miniprofiler.Timer, http.ResponseWriter, *http.Request) (interface{}, error)) http.Handler { return miniprofiler.NewHandler(func(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) { d, err := h(t, w, r) if err != nil { serveError(w, err) return } if d == nil { return } buf := new(bytes.Buffer) if err := json.NewEncoder(buf).Encode(d); err != nil { slog.Error(err) serveError(w, err) return } var tw io.Writer = w if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { w.Header().Set("Content-Encoding", "gzip") gz := gzip.NewWriter(w) defer gz.Close() tw = gz } if cb := r.FormValue("callback"); cb != "" { w.Header().Add("Content-Type", "application/javascript") tw.Write([]byte(cb + "(")) buf.WriteTo(tw) tw.Write([]byte(")")) return } w.Header().Add("Content-Type", "application/json") buf.WriteTo(tw) }) }
// NewHandler returns a profiled, appstats-aware appengine.Context. func NewHandler(f func(Context, http.ResponseWriter, *http.Request)) http.Handler { return appstats.NewHandler(func(c appengine.Context, w http.ResponseWriter, r *http.Request) { h := miniprofiler.NewHandler(func(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) { pc := Context{ Context: c.(appstats.Context), Timer: t, } t.SetName(miniprofiler.FuncName(f)) f(pc, w, r) t.AddCustomLink("appstats", pc.URL()) }) h.ServeHTTP(w, r) }) }
func Listen(listenAddr string, devMode bool, tsdbHost string, reloadFunc func() error) error { if devMode { slog.Infoln("using local web assets") } webFS := FS(devMode) indexTemplate = func() *template.Template { str := FSMustString(devMode, "/templates/index.html") templates, err := template.New("").Parse(str) if err != nil { slog.Fatal(err) } return templates } reload = reloadFunc if !devMode { tpl := indexTemplate() indexTemplate = func() *template.Template { return tpl } } if tsdbHost != "" { router.HandleFunc("/api/index", IndexTSDB) router.Handle("/api/put", Relay(tsdbHost)) } router.HandleFunc("/api/", APIRedirect) router.Handle("/api/action", JSON(Action)) router.Handle("/api/alerts", JSON(Alerts)) router.Handle("/api/config", miniprofiler.NewHandler(Config)) router.Handle("/api/config_test", miniprofiler.NewHandler(ConfigTest)) router.Handle("/api/save_enabled", JSON(SaveEnabled)) if schedule.SystemConf.ReloadEnabled() { // Is true of save is enabled router.Handle("/api/reload", JSON(Reload)).Methods(http.MethodPost) } if schedule.SystemConf.SaveEnabled() { router.Handle("/api/config/bulkedit", miniprofiler.NewHandler(BulkEdit)).Methods(http.MethodPost) router.Handle("/api/config/save", miniprofiler.NewHandler(SaveConfig)).Methods(http.MethodPost) router.Handle("/api/config/diff", miniprofiler.NewHandler(DiffConfig)).Methods(http.MethodPost) router.Handle("/api/config/running_hash", JSON(ConfigRunningHash)) } router.Handle("/api/egraph/{bs}.{format:svg|png}", JSON(ExprGraph)) router.Handle("/api/errors", JSON(ErrorHistory)) router.Handle("/api/expr", JSON(Expr)) router.Handle("/api/graph", JSON(Graph)) router.Handle("/api/health", JSON(HealthCheck)) router.Handle("/api/host", JSON(Host)) router.Handle("/api/last", JSON(Last)) router.Handle("/api/quiet", JSON(Quiet)) router.Handle("/api/incidents", JSON(Incidents)) router.Handle("/api/incidents/open", JSON(ListOpenIncidents)) router.Handle("/api/incidents/events", JSON(IncidentEvents)) router.Handle("/api/metadata/get", JSON(GetMetadata)) router.Handle("/api/metadata/metrics", JSON(MetadataMetrics)) router.Handle("/api/metadata/put", JSON(PutMetadata)) router.Handle("/api/metadata/delete", JSON(DeleteMetadata)).Methods("DELETE") router.Handle("/api/metric", JSON(UniqueMetrics)) router.Handle("/api/metric/{tagk}", JSON(MetricsByTagKey)) router.Handle("/api/metric/{tagk}/{tagv}", JSON(MetricsByTagPair)) router.Handle("/api/rule", JSON(Rule)) router.HandleFunc("/api/shorten", Shorten) router.Handle("/api/silence/clear", JSON(SilenceClear)) router.Handle("/api/silence/get", JSON(SilenceGet)) router.Handle("/api/silence/set", JSON(SilenceSet)) router.Handle("/api/status", JSON(Status)) router.Handle("/api/tagk/{metric}", JSON(TagKeysByMetric)) router.Handle("/api/tagv/{tagk}", JSON(TagValuesByTagKey)) router.Handle("/api/tagv/{tagk}/{metric}", JSON(TagValuesByMetricTagKey)) router.Handle("/api/tagsets/{metric}", JSON(FilteredTagsetsByMetric)) router.Handle("/api/opentsdb/version", JSON(OpenTSDBVersion)) router.Handle("/api/annotate", JSON(AnnotateEnabled)) // Annotations if schedule.SystemConf.AnnotateEnabled() { index := schedule.SystemConf.GetAnnotateIndex() if index == "" { index = "annotate" } annotateBackend = backend.NewElastic(schedule.SystemConf.GetAnnotateElasticHosts(), index) go func() { for { err := annotateBackend.InitBackend() if err == nil { return } slog.Warningf("could not initalize annotate backend, will try again: %v", err) time.Sleep(time.Second * 30) } }() web.AddRoutes(router, "/api", []backend.Backend{annotateBackend}, false, false) } router.HandleFunc("/api/version", Version) router.Handle("/api/debug/schedlock", JSON(ScheduleLockStatus)) http.Handle("/", miniprofiler.NewHandler(Index)) http.Handle("/api/", router) fs := http.FileServer(webFS) http.Handle("/partials/", fs) http.Handle("/static/", http.StripPrefix("/static/", fs)) http.Handle("/favicon.ico", fs) slog.Infoln("bosun web listening on:", listenAddr) slog.Infoln("tsdb host:", tsdbHost) return http.ListenAndServe(listenAddr, nil) }
func main() { miniprofiler.TrivialMilliseconds = 0 http.Handle("/", miniprofiler.NewHandler(Index)) fmt.Println("serving") http.ListenAndServe(":8080", nil) }