From f27adac8485c280cad7d2b4b8c943f709460da0d Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Wed, 27 Mar 2013 17:40:01 +0100 Subject: [PATCH 1/8] Split status template into two templates. This is now using a base template (_base.html) for the 'layout' of the web UI. Within that base template, the actual content templates get rendered. --- web/status.go | 18 +----------------- web/templates/_base.html | 13 +++++++++++++ web/templates/status.html | 16 +++------------- web/web.go | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 web/templates/_base.html diff --git a/web/status.go b/web/status.go index 07f310b3d..2874fe9d7 100644 --- a/web/status.go +++ b/web/status.go @@ -16,9 +16,6 @@ package web import ( "github.com/prometheus/prometheus/appstate" "github.com/prometheus/prometheus/retrieval" - "github.com/prometheus/prometheus/web/blob" - "html/template" - "log" "net/http" ) @@ -40,18 +37,5 @@ func (h *StatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { Status: "TODO: add status information here", TargetPools: h.appState.TargetManager.Pools(), } - - var t *template.Template - if *useLocalAssets { - t, _ = template.ParseFiles("web/templates/status.html") - } else { - templateFile, err := blob.GetFile(blob.TemplateFiles, "status.html") - if err != nil { - log.Fatalf("Could not read template: %s", err) - } - - t, _ = template.New("status").Parse(string(templateFile)) - } - - t.Execute(w, status) + executeTemplate(w, "status", status) } diff --git a/web/templates/_base.html b/web/templates/_base.html new file mode 100644 index 000000000..02f80d234 --- /dev/null +++ b/web/templates/_base.html @@ -0,0 +1,13 @@ + + + + + Prometheus + + + + + + {{template "content" .}} + + diff --git a/web/templates/status.html b/web/templates/status.html index 62712d5c2..a7602dab4 100644 --- a/web/templates/status.html +++ b/web/templates/status.html @@ -1,14 +1,5 @@ - - - - - Prometheus Status - - - - - -

Status

+{{define "content"}} +

Status

{{.Status}}
@@ -41,5 +32,4 @@ {{end}} - - +{{end}} diff --git a/web/web.go b/web/web.go index e3672a707..6c9b55e2d 100644 --- a/web/web.go +++ b/web/web.go @@ -20,6 +20,8 @@ import ( "github.com/prometheus/prometheus/appstate" "github.com/prometheus/prometheus/web/api" "github.com/prometheus/prometheus/web/blob" + "html/template" + "log" "net/http" _ "net/http/pprof" ) @@ -45,3 +47,36 @@ func StartServing(appState *appstate.ApplicationState) { go http.ListenAndServe(*listenAddress, nil) } + +func getTemplate(name string) (t *template.Template, err error) { + if *useLocalAssets { + return template.ParseFiles("web/templates/_base.html", "web/templates/"+name+".html") + } + + t = template.New("_base") + + file, err := blob.GetFile(blob.TemplateFiles, "_base.html") + if err != nil { + log.Printf("Could not read base template: %s", err) + return nil, err + } + t.Parse(string(file)) + + file, err = blob.GetFile(blob.TemplateFiles, name+".html") + if err != nil { + log.Printf("Could not read %s template: %s", name, err) + return nil, err + } + t.Parse(string(file)) + + return +} + +func executeTemplate(w http.ResponseWriter, name string, data interface{}) { + tpl, err := getTemplate(name) + if err != nil { + log.Printf("Errror preparing layout template: %s", err) + return + } + tpl.Execute(w, data) +} From fed467ede02948ae8b834b4dad20dbf31de1da40 Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Wed, 27 Mar 2013 18:44:47 +0100 Subject: [PATCH 2/8] Moved graph and console to use templates as well. --- web/{static/index.html => templates/console.html} | 0 web/{static => templates}/graph.html | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename web/{static/index.html => templates/console.html} (100%) rename web/{static => templates}/graph.html (100%) diff --git a/web/static/index.html b/web/templates/console.html similarity index 100% rename from web/static/index.html rename to web/templates/console.html diff --git a/web/static/graph.html b/web/templates/graph.html similarity index 100% rename from web/static/graph.html rename to web/templates/graph.html From 1a3fb459e05b6faa6f72216a1f11133e424df7d7 Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Tue, 2 Apr 2013 19:14:02 +0200 Subject: [PATCH 3/8] Add navigation menu to all pages + change routes. To achieve that, this PR - converts static/index.html ("console") and graph to templates - moved the handlebars template to separated file to avoid escaping issues Route changes: /status -> / /static -> /console /static/graph.html -> /graph --- web/handler.go | 26 +++++++++ web/static/css/prometheus.css | 16 +++++- web/static/js/graph.js | 31 ++++++----- web/static/js/graph_template.handlebar | 42 +++++++++++++++ web/templates/_base.html | 8 ++- web/templates/console.html | 16 ++---- web/templates/graph.html | 75 +++++--------------------- web/templates/status.html | 2 + web/web.go | 5 +- 9 files changed, 131 insertions(+), 90 deletions(-) create mode 100644 web/handler.go create mode 100644 web/static/js/graph_template.handlebar diff --git a/web/handler.go b/web/handler.go new file mode 100644 index 000000000..75b411eb7 --- /dev/null +++ b/web/handler.go @@ -0,0 +1,26 @@ +// Copyright 2013 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package web + +import ( + "net/http" +) + +func graphHandler(w http.ResponseWriter, r *http.Request) { + executeTemplate(w, "graph", nil) +} + +func consoleHandler(w http.ResponseWriter, r *http.Request) { + executeTemplate(w, "console", nil) +} diff --git a/web/static/css/prometheus.css b/web/static/css/prometheus.css index 96a8ca84b..da245fd77 100644 --- a/web/static/css/prometheus.css +++ b/web/static/css/prometheus.css @@ -2,8 +2,8 @@ body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px; - color: #333333; - background-color: #eee; + color: #333; + background-color: #f2f2f2; margin: 0px; padding: 0px; } @@ -49,3 +49,15 @@ input[name=end_input], input[name=range_input] { margin-left: -4px; margin-right: -4px; } + +#navigation { + font-size: 20pt; + background-color: #333; + color: #F2F2F2; + line-height: 120%; +} + +#navigation a { padding-right: 1em; text-decoration: none } +#navigation a:visited { color: #F2F2F2 } +#navigation a:active { color: #F60 } +#navigation a:hover { color: #06C } diff --git a/web/static/js/graph.js b/web/static/js/graph.js index e2bc92fce..260a5ab64 100644 --- a/web/static/js/graph.js +++ b/web/static/js/graph.js @@ -20,6 +20,7 @@ var Prometheus = Prometheus || {}; var graphs = []; +var graphTemplate; Prometheus.Graph = function(element, options) { this.el = element; @@ -57,9 +58,8 @@ Prometheus.Graph.prototype.initialize = function() { self.options['stacked_checked'] = self.options['stacked'] ? "checked" : ""; // Draw graph controls and container from Handlebars template. - var source = $("#graph_template").html(); - var template = Handlebars.compile(source); - var graphHtml = template(self.options); + + var graphHtml = graphTemplate(self.options); self.el.append(graphHtml); // Get references to all the interesting elements in the graph container and @@ -428,15 +428,22 @@ function init() { cache: false }); - var options = parseGraphOptionsFromUrl(); - if (options.length == 0) { - options.push({}); - } - for (var i = 0; i < options.length; i++) { - addGraph(options[i]); - } - - $("#add_graph").click(function() { addGraph({}); }); + $.ajax({ + url: "/static/js/graph_template.handlebar", + success: function(data) { + console.log("got template") + console.log(data) + graphTemplate = Handlebars.compile(data); + var options = parseGraphOptionsFromUrl(); + if (options.length == 0) { + options.push({}); + } + for (var i = 0; i < options.length; i++) { + addGraph(options[i]); + } + $("#add_graph").click(function() { addGraph({}); }); + } + }) } $(init); diff --git a/web/static/js/graph_template.handlebar b/web/static/js/graph_template.handlebar new file mode 100644 index 000000000..e24277197 --- /dev/null +++ b/web/static/js/graph_template.handlebar @@ -0,0 +1,42 @@ +
+
+
+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + +
+
+
+
+ ajax_spinner +
+
+
+
+
+
+
+
diff --git a/web/templates/_base.html b/web/templates/_base.html index 02f80d234..79c1b23f8 100644 --- a/web/templates/_base.html +++ b/web/templates/_base.html @@ -4,10 +4,16 @@ Prometheus - + + {{template "head" .}} + {{template "content" .}} diff --git a/web/templates/console.html b/web/templates/console.html index df6e32cfa..c97356e01 100644 --- a/web/templates/console.html +++ b/web/templates/console.html @@ -1,15 +1,8 @@ - - - - - Prometheus Expression Browser - - - +{{define "head"}} - +{{end}} - +{{define "content"}}
@@ -23,5 +16,4 @@
- - +{{end}} diff --git a/web/templates/graph.html b/web/templates/graph.html index ca2ad0eda..2181bb0ca 100644 --- a/web/templates/graph.html +++ b/web/templates/graph.html @@ -1,17 +1,12 @@ - - - - - Prometheus Expression Browser - +{{define "head"}} - - + + - - + + @@ -19,61 +14,17 @@ - - - + + + - + - - + +{{end}} - +{{define "content"}}
- - +{{end}} diff --git a/web/templates/status.html b/web/templates/status.html index a7602dab4..722d9dc4a 100644 --- a/web/templates/status.html +++ b/web/templates/status.html @@ -1,3 +1,5 @@ +{{define "head"}}{{end}} + {{define "content"}}

Status

diff --git a/web/web.go b/web/web.go index 6c9b55e2d..76b38e8cb 100644 --- a/web/web.go +++ b/web/web.go @@ -36,7 +36,10 @@ func StartServing(appState *appstate.ApplicationState) { gorest.RegisterService(api.NewMetricsService(appState)) exporter := registry.DefaultRegistry.YieldExporter() - http.Handle("/status", &StatusHandler{appState: appState}) + http.Handle("/", &StatusHandler{appState: appState}) + http.HandleFunc("/graph", graphHandler) + http.HandleFunc("/console", consoleHandler) + http.Handle("/api/", gorest.Handle()) http.Handle("/metrics.json", exporter) if *useLocalAssets { From 1cb4c819e184cd4f780e9be2f2bd8471cf067889 Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Thu, 4 Apr 2013 19:02:29 +0200 Subject: [PATCH 4/8] Remove cruft. --- web/static/js/graph.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/static/js/graph.js b/web/static/js/graph.js index 260a5ab64..4a6163d85 100644 --- a/web/static/js/graph.js +++ b/web/static/js/graph.js @@ -431,8 +431,6 @@ function init() { $.ajax({ url: "/static/js/graph_template.handlebar", success: function(data) { - console.log("got template") - console.log(data) graphTemplate = Handlebars.compile(data); var options = parseGraphOptionsFromUrl(); if (options.length == 0) { From 84d17b4d9760daf9e7729d40923ed2bb68421c69 Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Thu, 4 Apr 2013 19:08:20 +0200 Subject: [PATCH 5/8] Replace YieldExporter() with Handler() --- web/web.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/web.go b/web/web.go index 76b38e8cb..83f025057 100644 --- a/web/web.go +++ b/web/web.go @@ -34,14 +34,13 @@ var ( func StartServing(appState *appstate.ApplicationState) { gorest.RegisterService(api.NewMetricsService(appState)) - exporter := registry.DefaultRegistry.YieldExporter() http.Handle("/", &StatusHandler{appState: appState}) http.HandleFunc("/graph", graphHandler) http.HandleFunc("/console", consoleHandler) http.Handle("/api/", gorest.Handle()) - http.Handle("/metrics.json", exporter) + http.Handle("/metrics.json", registry.DefaultRegistry.Handler()) if *useLocalAssets { http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static")))) } else { From 3aead8468c1204b94ee2b4859a72393cfbaecc71 Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Thu, 4 Apr 2013 19:19:58 +0200 Subject: [PATCH 6/8] Fix typo. --- web/web.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/web.go b/web/web.go index 83f025057..ccb25dc41 100644 --- a/web/web.go +++ b/web/web.go @@ -77,7 +77,7 @@ func getTemplate(name string) (t *template.Template, err error) { func executeTemplate(w http.ResponseWriter, name string, data interface{}) { tpl, err := getTemplate(name) if err != nil { - log.Printf("Errror preparing layout template: %s", err) + log.Printf("Error preparing layout template: %s", err) return } tpl.Execute(w, data) From 1c091a97231ad2029345f7777c21454b97341078 Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Fri, 5 Apr 2013 13:24:50 +0200 Subject: [PATCH 7/8] Use client_golang.exp for automatic telemetry. --- web/web.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/web/web.go b/web/web.go index ccb25dc41..babf467c2 100644 --- a/web/web.go +++ b/web/web.go @@ -17,6 +17,7 @@ import ( "code.google.com/p/gorest" "flag" "github.com/prometheus/client_golang" + "github.com/prometheus/client_golang/exp" "github.com/prometheus/prometheus/appstate" "github.com/prometheus/prometheus/web/api" "github.com/prometheus/prometheus/web/blob" @@ -35,19 +36,19 @@ var ( func StartServing(appState *appstate.ApplicationState) { gorest.RegisterService(api.NewMetricsService(appState)) - http.Handle("/", &StatusHandler{appState: appState}) - http.HandleFunc("/graph", graphHandler) - http.HandleFunc("/console", consoleHandler) + exp.Handle("/", &StatusHandler{appState: appState}) + exp.HandleFunc("/graph", graphHandler) + exp.HandleFunc("/console", consoleHandler) - http.Handle("/api/", gorest.Handle()) - http.Handle("/metrics.json", registry.DefaultRegistry.Handler()) + exp.Handle("/api/", gorest.Handle()) + exp.Handle("/metrics.json", registry.DefaultHandler) if *useLocalAssets { - http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static")))) + exp.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static")))) } else { - http.Handle("/static/", http.StripPrefix("/static/", new(blob.Handler))) + exp.Handle("/static/", http.StripPrefix("/static/", new(blob.Handler))) } - go http.ListenAndServe(*listenAddress, nil) + go http.ListenAndServe(*listenAddress, exp.DefaultCoarseMux) } func getTemplate(name string) (t *template.Template, err error) { From 0f775a417829931780a78477629b8c2488301f12 Mon Sep 17 00:00:00 2001 From: Johannes 'fish' Ziemke Date: Fri, 5 Apr 2013 13:41:52 +0200 Subject: [PATCH 8/8] Use Sprintf instead of string concatenation. --- web/web.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/web.go b/web/web.go index babf467c2..2a25f9d9c 100644 --- a/web/web.go +++ b/web/web.go @@ -16,6 +16,7 @@ package web import ( "code.google.com/p/gorest" "flag" + "fmt" "github.com/prometheus/client_golang" "github.com/prometheus/client_golang/exp" "github.com/prometheus/prometheus/appstate" @@ -53,7 +54,7 @@ func StartServing(appState *appstate.ApplicationState) { func getTemplate(name string) (t *template.Template, err error) { if *useLocalAssets { - return template.ParseFiles("web/templates/_base.html", "web/templates/"+name+".html") + return template.ParseFiles("web/templates/_base.html", fmt.Sprintf("web/templates/%s.html", name)) } t = template.New("_base")