Code

Make a metric's graph's time-range configurable.
authorSebastian Harl <sh@tokkee.org>
Mon, 24 Nov 2014 08:57:23 +0000 (09:57 +0100)
committerSebastian Harl <sh@tokkee.org>
Mon, 24 Nov 2014 08:57:23 +0000 (09:57 +0100)
server/graph.go
server/query.go
static/style/main.css
templates/metric.tmpl

index 47ba193c1d052ceff42c6e23930f61a83e7acb40..5134ed6659f2ed5bd8539efe9d1580def3c4aec0 100644 (file)
@@ -43,7 +43,7 @@ import (
        "github.com/sysdb/go/sysdb"
 )
 
-var timeLayout = "20060102150405"
+var urldate = "20060102150405"
 
 func (s *Server) graph(w http.ResponseWriter, req request) {
        if len(req.args) < 2 || 4 < len(req.args) {
@@ -55,13 +55,13 @@ func (s *Server) graph(w http.ResponseWriter, req request) {
        start := end.Add(-24 * time.Hour)
        var err error
        if len(req.args) > 2 {
-               if start, err = time.Parse(timeLayout, req.args[2]); err != nil {
+               if start, err = time.Parse(urldate, req.args[2]); err != nil {
                        s.badrequest(w, fmt.Errorf("Invalid start time: %v", err))
                        return
                }
        }
        if len(req.args) > 3 {
-               if end, err = time.Parse(timeLayout, req.args[3]); err != nil {
+               if end, err = time.Parse(urldate, req.args[3]); err != nil {
                        s.badrequest(w, fmt.Errorf("Invalid start time: %v", err))
                        return
                }
index 75707ffbdd6540edeb1a4e00330ba7e53f35bd3b..a95dba56125fcdef08a5c0f95ddf5c3c725cecf0 100644 (file)
@@ -85,6 +85,9 @@ func fetch(req request, s *Server) (*page, error) {
                        return nil, fmt.Errorf("%s not found", strings.Title(req.cmd))
                }
                res, err = s.query("FETCH %s %s.%s", identifier(req.cmd), req.args[0], req.args[1])
+               if req.cmd == "metric" {
+                       return metric(req, res, s)
+               }
        default:
                panic("Unknown request: fetch(" + req.cmd + ")")
        }
@@ -94,6 +97,42 @@ func fetch(req request, s *Server) (*page, error) {
        return tmpl(s.results[req.cmd], res)
 }
 
+var datetime = "2006-01-02 15:04:05"
+
+func metric(req request, res interface{}, s *Server) (*page, error) {
+       start := time.Now().Add(-24 * time.Hour)
+       end := time.Now()
+       if req.r.Method == "POST" {
+               var err error
+               // Parse the values first to verify their format.
+               if s := req.r.FormValue("start_date"); s != "" {
+                       if start, err = time.Parse(datetime, s); err != nil {
+                               return nil, fmt.Errorf("Invalid start time %q", s)
+                       }
+               }
+               if e := req.r.FormValue("end_date"); e != "" {
+                       if end, err = time.Parse(datetime, e); err != nil {
+                               return nil, fmt.Errorf("Invalid end time %q", e)
+                       }
+               }
+       }
+
+       p := struct {
+               StartTime string
+               EndTime   string
+               URLStart  string
+               URLEnd    string
+               Data      interface{}
+       }{
+               start.Format(datetime),
+               end.Format(datetime),
+               start.Format(urldate),
+               end.Format(urldate),
+               res,
+       }
+       return tmpl(s.results["metric"], &p)
+}
+
 type identifier string
 
 func (s *Server) query(cmd string, args ...interface{}) (interface{}, error) {
@@ -107,7 +146,7 @@ func (s *Server) query(cmd string, args ...interface{}) (interface{}, error) {
                case string:
                        args[i] = proto.EscapeString(v)
                case time.Time:
-                       args[i] = v.Format("2006-01-02 15:04:05")
+                       args[i] = v.Format(datetime)
                default:
                        panic(fmt.Sprintf("query: invalid type %T", arg))
                }
index 4ad9665675b10f8cf988f56c81f96129ed54d97b..4127602aa6de6c352091f2c43f73abf5964f51e1 100644 (file)
@@ -165,3 +165,18 @@ table.results th, table.results td {
 table.results td.value {
        word-break: break-all;
 }
+
+input[type=text].datetime {
+       width: 12em;
+       height: 25px;
+       border: 1px solid #000;
+       padding: 0px 3px;
+}
+
+button {
+       background-color: #000;
+       color: #fff;
+       border: 1px solid #000;
+       height: 25px;
+       padding: 0px;
+}
index d855356695e2962d9aa718f41bdd191b796ad1d5..5dc51c1008a0e2ad113bbbb3127a7dfa4e91bd71 100644 (file)
@@ -1,10 +1,17 @@
-<section>{{$m := index .Metrics 0}}
-       <h1>Metric {{$.Name}} &mdash; {{$m.Name}}</h1>
+<section>{{$m := index .Data.Metrics 0}}
+       <h1>Metric {{.Data.Name}} &mdash; {{$m.Name}}</h1>
 {{if $m.Timeseries}}
-       <img src="/graph/{{urlquery $.Name}}/{{urlquery $m.Name}}" border="0" />
+       <form action="/metric/{{urlquery .Data.Name}}/{{urlquery $m.Name}}" method="POST">
+               <b>Time range:</b>
+               <input type="text" name="start_date" value="{{.StartTime}}" class="datetime">
+               &mdash;
+               <input type="text" name="end_date" value="{{.EndTime}}" class="datetime">
+               <button type="submit">Apply</button>
+       </form><br />
+       <img src="/graph/{{urlquery .Data.Name}}/{{urlquery $m.Name}}/{{.URLStart}}/{{.URLEnd}}" border="0" />
 {{end}}
        <table class="results">
-               <tr><td><b>Host</b></td><td><a href="/host/{{urlquery $.Name}}">{{$.Name}}</a></td></tr>
+               <tr><td><b>Host</b></td><td><a href="/host/{{urlquery .Data.Name}}">{{.Data.Name}}</a></td></tr>
                <tr><td><b>Last update</b></td><td>{{$m.LastUpdate}}</td></tr>
                <tr><td><b>Update interval</b></td><td>{{$m.UpdateInterval}}</td></tr>
                <tr><td><b>Backends</b></td><td>{{$m.Backends}}</td></tr>