diff --git a/server/graph.go b/server/graph.go
index 9406f760158029519ecf32edb07f7993c6dfc632..9c679bc5a0386a9ed48a4900a8a5c7d9a7f7af27 100644 (file)
--- a/server/graph.go
+++ b/server/graph.go
import (
"bytes"
- "errors"
"fmt"
"io"
"net/http"
"time"
- "code.google.com/p/plotinum/plot"
- "code.google.com/p/plotinum/plotter"
- "code.google.com/p/plotinum/plotutil"
- "code.google.com/p/plotinum/vg"
- "code.google.com/p/plotinum/vg/vgsvg"
- "github.com/sysdb/go/proto"
- "github.com/sysdb/go/sysdb"
+ "github.com/gonum/plot/vg"
+ "github.com/sysdb/webui/graph"
)
-func (s *Server) graph(w http.ResponseWriter, req request) {
- if len(req.args) != 2 {
- s.internal(w, fmt.Errorf("Missing host/metric information"))
- }
+var urldate = "20060102150405"
- host := proto.EscapeString(req.args[0])
- metric := proto.EscapeString(req.args[1])
- res, err := s.query(fmt.Sprintf("TIMESERIES %s.%s", host, metric))
- if err != nil {
- s.internal(w, fmt.Errorf("Failed to retrieve graph data: %v", err))
+func (s *Server) graph(w http.ResponseWriter, req request) {
+ if len(req.args) < 2 || 4 < len(req.args) {
+ s.badrequest(w, fmt.Errorf("Missing host/metric information"))
return
}
- ts, ok := res.(sysdb.Timeseries)
- if !ok {
- s.internal(w, errors.New("TIMESERIES did not return a time-series"))
- return
+ end := time.Now()
+ start := end.Add(-24 * time.Hour)
+ var err error
+ if len(req.args) > 2 {
+ if start, err = time.Parse(urldate, req.args[2]); err != nil {
+ s.badrequest(w, fmt.Errorf("Invalid start time: %v", err))
+ return
+ }
}
-
- p, err := plot.New()
+ if len(req.args) > 3 {
+ if end, err = time.Parse(urldate, req.args[3]); err != nil {
+ s.badrequest(w, fmt.Errorf("Invalid start time: %v", err))
+ return
+ }
+ }
+ g := &graph.Graph{
+ Start: start,
+ End: end,
+ Metrics: [][2]string{{req.args[0], req.args[1]}},
+ }
+ p, err := g.Plot(s.c)
if err != nil {
- s.internal(w, fmt.Errorf("Failed to create plot: %v", err))
+ s.internal(w, err)
return
}
- p.Add(plotter.NewGrid())
- p.X.Tick.Marker = dateTicks
- var i int
- for name, data := range ts.Data {
- pts := make(plotter.XYs, len(data))
- for i, p := range data {
- pts[i].X = float64(time.Time(p.Timestamp).UnixNano())
- pts[i].Y = p.Value
- }
- l, err := plotter.NewLine(pts)
- if err != nil {
- s.internal(w, fmt.Errorf("Failed to create line plotter: %v", err))
- return
- }
- l.LineStyle.Color = plotutil.DarkColors[i%len(plotutil.DarkColors)]
- p.Add(l)
- p.Legend.Add(name, l)
- i++
+ pw, err := p.WriterTo(vg.Length(500), vg.Length(200), "svg")
+ if err != nil {
+ s.internal(w, fmt.Errorf("Failed to write plot: %v", err))
+ return
}
- c := vgsvg.New(vg.Length(500), vg.Length(200))
- p.Draw(plot.MakeDrawArea(c))
-
var buf bytes.Buffer
- if _, err := c.WriteTo(&buf); err != nil {
+ if _, err := pw.WriteTo(&buf); err != nil {
s.internal(w, fmt.Errorf("Failed to write plot: %v", err))
return
}
io.Copy(w, &buf)
}
-func dateTicks(min, max float64) []plot.Tick {
- // TODO: this is surely not the best we can do
- // but it'll distribute ticks evenly.
- ticks := plot.DefaultTicks(min, max)
- for i, t := range ticks {
- if t.Label == "" {
- // Skip minor ticks.
- continue
- }
- ticks[i].Label = time.Unix(0, int64(t.Value)).Format(time.RFC822)
- }
- return ticks
-}
-
// vim: set tw=78 sw=4 sw=4 noexpandtab :