/* * JSON Response: * [ * {"target": "status.200", "datapoints": [[1720.0, 1370846820], ...], }, * {"target": "status.204", "datapoints": [[null, 1370846820], ..., ]} * ]s */ func (h *RenderHandler) jsonResponse(w http.ResponseWriter, data interface{}) { if m, ok := data.([]*metrics.Metrics); ok { w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "%s([", h.jsonp) for i, mi := range m { if i > 0 { fmt.Fprintf(w, ",") } fmt.Fprintf(w, `{"target":"%s","datapoints":[`, mi.Target) for ii := 0; ii < len(mi.Datapoints); ii++ { if ii > 0 { fmt.Fprintf(w, ",") } val := "null" if mi.Datapoints[ii][0] != nil { val = fmt.Sprintf("%.2f", *mi.Datapoints[ii][0]) } fmt.Fprintf(w, "[%s, %.0f]", val, *mi.Datapoints[ii][1]) } fmt.Fprintf(w, "]}") } fmt.Fprintf(w, "])") glog.Infof("%v\n", data) } else { glog.Errorf("%v\n", data) http.Error(w, fmt.Sprintf("%v", data), http.StatusBadRequest) } }
func (api *Api) Value(name string, from int64, to int64) interface{} { glog.Infof("Api.Value(%s, %d, %d)", name, from, to) // check constant value first if f, err := strconv.ParseFloat(name, 10); err == nil { return f } return Get(name, from, to, api.MaxDataPoints) }
// Handle TCP Connections func handle(conn net.Conn) { glog.Infof("Connection: %s -> %s\n", conn.RemoteAddr(), conn.LocalAddr()) defer func() { glog.Infof("Closing connection: %s\n", conn.RemoteAddr()) conn.Close() glog.Flush() }() scanner := bufio.NewScanner(conn) for scanner.Scan() { if m := strings.Split(scanner.Text(), " "); len(m) > 2 { if ts, err := strconv.ParseInt(m[2], 10, 0); err != nil { glog.Warningln(err) continue } else { metrics.Add(m[0], m[1], ts) } } } if err := scanner.Err(); err != nil { glog.Errorln(err) } }
func Handler(w http.ResponseWriter, r *http.Request) { t := time.Now() glog.Infoln(r.RequestURI) // ResponseWriter wrapper w.Header().Set("Server", "YAG") w.Header().Set("Content-Type", "application/json") rw := &RenderResponseWriter{w: w} // Handler composition http.TimeoutHandler(&RenderHandler{}, time.Duration(config.Cfg.Webserver.Timeout)*time.Second, http.StatusText(http.StatusRequestTimeout)).ServeHTTP(rw, r) glog.Infof("[%v] in %v\n", rw.Code, time.Now().Sub(t)) }
// GET: /render?target=my.key&from=-1h[&to=...&jsonp=...] func (h *RenderHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": glog.Infof("%v\n", r.URL) err := h.parseQuery(r) if err != nil { glog.Warningln(err) http.Error(w, err.Error(), http.StatusBadRequest) return } h.jsonResponse(w, api.Eval(h.target, h.from, h.to, &metrics.Api{h.maxDataPoints})) glog.Flush() default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) } }
func Add(key string, value string, timestamp int64) { if client, err := db.Client(); err != nil { glog.Errorln(err) } else { defer db.Release(client) if r := client.Cmd("EVALSHA", addSha, 1, key, value, timestamp); r.Err != nil { glog.Warningln(r.Err) if r = client.Cmd("EVAL", config.Cfg.Metrics.AddScript, 1, key, value, timestamp); r.Err != nil { glog.Errorln(r.Err) } } else { glog.Infof("[OK: %v]\t(%s %s)|%d", r, key, value, timestamp) } } }
func init() { // Max log file size - rotate log file if exceed 10MB glog.MaxSize = 10 * 1024 * 1024 var f = flag.String("f", "config.json", "read configuration from file") flag.StringVar(&Pprof.Cpu, "cpuprofile", "", "write cpu profile to file") flag.StringVar(&Pprof.Mem, "memprofile", "", "write memory profile to this file") flag.Parse() if cfg, err := ioutil.ReadFile(*f); err != nil { glog.Errorln(err) return } else { if err := json.Unmarshal(cfg, &Cfg); err != nil { glog.Fatal(err) } glog.Infof("%v", string(cfg)) } dir := filepath.Dir(*f) + "/" if script, err := ioutil.ReadFile(dir + Cfg.Metrics.AddScript); err != nil { glog.Errorln(err) Cfg.Metrics.AddScript = "" } else { Cfg.Metrics.AddScript = string(script) } if script, err := ioutil.ReadFile(dir + Cfg.Metrics.GetScript); err != nil { glog.Errorln(err) Cfg.Metrics.GetScript = "" } else { Cfg.Metrics.GetScript = string(script) } if script, err := ioutil.ReadFile(dir + Cfg.Metrics.TtlScript); err != nil { glog.Errorln(err) Cfg.Metrics.TtlScript = "" } else { Cfg.Metrics.TtlScript = string(script) } }
func Ttl(from int64, to int64) { if client, err := db.Client(); err != nil { glog.Errorln(err) } else { t0 := time.Now() defer db.Release(client) if r := client.Cmd("EVALSHA", ttlSha, 1, "*", from, to); r.Err != nil { glog.Warningln(r.Err) if r = client.Cmd("EVAL", config.Cfg.Metrics.TtlScript, 1, "*", from, to); r.Err != nil { glog.Errorln(r.Err) } } else { t1 := time.Now() glog.Infof("ZREMRANGEBYSCORE(%d, %d): %v in %v", from, to, r, t1.Sub(t0)) } } }