From 0e18784c643bb07c18d48f994fed0540b40d671f Mon Sep 17 00:00:00 2001 From: Ceesjan Luiten Date: Tue, 24 Mar 2015 22:04:38 +0100 Subject: [PATCH] Make all paths absolute to support proxies --- console_libraries/menu.lib | 4 +- console_libraries/prom.lib | 20 +++---- main.go | 24 ++++++++- rules/manager/manager.go | 4 +- templates/templates.go | 5 +- templates/templates_test.go | 2 +- web/alerts.go | 6 +-- web/api/api.go | 14 ++--- web/api/api_test.go | 2 +- web/consoles.go | 3 +- web/handler.go | 9 +++- web/static/js/graph.js | 8 +-- web/static/js/graph_template.handlebar | 4 +- web/static/js/prom_console.js | 6 +-- web/status.go | 3 +- web/templates/_base.html | 18 ++++--- web/templates/alerts.html | 4 +- web/templates/graph.html | 26 ++++----- web/web.go | 73 +++++++++++++++----------- 19 files changed, 142 insertions(+), 93 deletions(-) diff --git a/console_libraries/menu.lib b/console_libraries/menu.lib index a6acc51e6..dc0678895 100644 --- a/console_libraries/menu.lib +++ b/console_libraries/menu.lib @@ -12,12 +12,12 @@ - Prometheus + Prometheus diff --git a/console_libraries/prom.lib b/console_libraries/prom.lib index ac8638f7f..f80ea58b7 100644 --- a/console_libraries/prom.lib +++ b/console_libraries/prom.lib @@ -1,15 +1,17 @@ {{/* vim: set ft=html: */}} {{/* Load Prometheus console library JS/CSS. Should go in */}} {{ define "prom_console_head" }} - - - - - - - - - + + + + + + + + + + + {{ end }} {{/* Top of all pages. */}} diff --git a/main.go b/main.go index 19e355744..50e6aa061 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,7 @@ import ( "os/signal" "sync" "syscall" + "strings" "time" "github.com/golang/glog" @@ -65,6 +66,8 @@ var ( storageDirty = flag.Bool("storage.local.dirty", false, "If set, the local storage layer will perform crash recovery even if the last shutdown appears to be clean.") storagePedanticChecks = flag.Bool("storage.local.pedantic-checks", false, "If set, a crash recovery will perform checks on each series file. This might take a very long time.") + pathPrefix = flag.String("web.path-prefix", "/", "Prefix for all web paths.") + printVersion = flag.Bool("version", false, "Print version information.") ) @@ -140,7 +143,8 @@ func NewPrometheus() *prometheus { NotificationHandler: notificationHandler, EvaluationInterval: conf.EvaluationInterval(), Storage: memStorage, - PrometheusURL: web.MustBuildServerURL(), + PrometheusURL: web.MustBuildServerURL(*pathPrefix), + PathPrefix: *pathPrefix, }) if err := ruleManager.AddRulesFromConfig(conf); err != nil { glog.Fatal("Error loading rule files: ", err) @@ -157,14 +161,21 @@ func NewPrometheus() *prometheus { TargetPools: targetManager.Pools(), Flags: flags, Birth: time.Now(), + PathPrefix: *pathPrefix, } alertsHandler := &web.AlertsHandler{ RuleManager: ruleManager, + PathPrefix: *pathPrefix, } consolesHandler := &web.ConsolesHandler{ Storage: memStorage, + PathPrefix: *pathPrefix, + } + + graphsHandler := &web.GraphsHandler{ + PathPrefix: *pathPrefix, } metricsService := &api.MetricsService{ @@ -177,6 +188,7 @@ func NewPrometheus() *prometheus { MetricsHandler: metricsService, ConsolesHandler: consolesHandler, AlertsHandler: alertsHandler, + GraphsHandler: graphsHandler, } p := &prometheus{ @@ -205,7 +217,7 @@ func (p *prometheus) Serve() { p.storage.Start() go func() { - err := p.webService.ServeForever() + err := p.webService.ServeForever(*pathPrefix) if err != nil { glog.Fatal(err) } @@ -255,6 +267,14 @@ func (p *prometheus) Collect(ch chan<- registry.Metric) { func main() { flag.Parse() + + if !strings.HasPrefix(*pathPrefix, "/") { + *pathPrefix = "/" + *pathPrefix + } + if !strings.HasSuffix(*pathPrefix, "/") { + *pathPrefix = *pathPrefix + "/" + } + versionInfoTmpl.Execute(os.Stdout, BuildInfo) if *printVersion { diff --git a/rules/manager/manager.go b/rules/manager/manager.go index 8dfdc561a..0b1a386a5 100644 --- a/rules/manager/manager.go +++ b/rules/manager/manager.go @@ -99,6 +99,7 @@ type ruleManager struct { notificationHandler *notification.NotificationHandler prometheusURL string + pathPrefix string } // RuleManagerOptions bundles options for the RuleManager. @@ -110,6 +111,7 @@ type RuleManagerOptions struct { SampleAppender storage.SampleAppender PrometheusURL string + PathPrefix string } // NewRuleManager returns an implementation of RuleManager, ready to be started @@ -190,7 +192,7 @@ func (m *ruleManager) queueAlertNotifications(rule *rules.AlertingRule, timestam defs := "{{$labels := .Labels}}{{$value := .Value}}" expand := func(text string) string { - template := templates.NewTemplateExpander(defs+text, "__alert_"+rule.Name(), tmplData, timestamp, m.storage) + template := templates.NewTemplateExpander(defs+text, "__alert_"+rule.Name(), tmplData, timestamp, m.storage, m.pathPrefix) result, err := template.Expand() if err != nil { result = err.Error() diff --git a/templates/templates.go b/templates/templates.go index 2bbb70f25..b07258482 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -92,7 +92,7 @@ type templateExpander struct { } // NewTemplateExpander returns a template expander ready to use. -func NewTemplateExpander(text string, name string, data interface{}, timestamp clientmodel.Timestamp, storage local.Storage) *templateExpander { +func NewTemplateExpander(text string, name string, data interface{}, timestamp clientmodel.Timestamp, storage local.Storage, pathPrefix string) *templateExpander { return &templateExpander{ text: text, name: name, @@ -218,6 +218,9 @@ func NewTemplateExpander(text string, name string, data interface{}, timestamp c } return fmt.Sprintf("%.4g%ss", v, prefix) }, + "pathPrefix": func() string { + return pathPrefix; + }, }, } } diff --git a/templates/templates_test.go b/templates/templates_test.go index 9caa14897..f4c769b50 100644 --- a/templates/templates_test.go +++ b/templates/templates_test.go @@ -178,7 +178,7 @@ func TestTemplateExpansion(t *testing.T) { for i, s := range scenarios { var result string var err error - expander := NewTemplateExpander(s.text, "test", s.input, time, storage) + expander := NewTemplateExpander(s.text, "test", s.input, time, storage, "/") if s.html { result, err = expander.ExpandHTML(nil) } else { diff --git a/web/alerts.go b/web/alerts.go index 77eb9d49b..864e289fe 100644 --- a/web/alerts.go +++ b/web/alerts.go @@ -47,9 +47,9 @@ func (s byAlertStateSorter) Swap(i, j int) { // AlertsHandler implements http.Handler. type AlertsHandler struct { + mutex sync.Mutex RuleManager manager.RuleManager - - mutex sync.Mutex + PathPrefix string } func (h *AlertsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -68,5 +68,5 @@ func (h *AlertsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { rules.Firing: "danger", }, } - executeTemplate(w, "alerts", alertStatus) + executeTemplate(w, "alerts", alertStatus, h.PathPrefix) } diff --git a/web/api/api.go b/web/api/api.go index 0ab6576c9..90d1c1453 100644 --- a/web/api/api.go +++ b/web/api/api.go @@ -31,19 +31,19 @@ type MetricsService struct { } // RegisterHandler registers the handler for the various endpoints below /api. -func (msrv *MetricsService) RegisterHandler() { +func (msrv *MetricsService) RegisterHandler(pathPrefix string) { handler := func(h func(http.ResponseWriter, *http.Request)) http.Handler { return httputils.CompressionHandler{ Handler: http.HandlerFunc(h), } } - http.Handle("/api/query", prometheus.InstrumentHandler( - "/api/query", handler(msrv.Query), + http.Handle(pathPrefix + "api/query", prometheus.InstrumentHandler( + pathPrefix + "api/query", handler(msrv.Query), )) - http.Handle("/api/query_range", prometheus.InstrumentHandler( - "/api/query_range", handler(msrv.QueryRange), + http.Handle(pathPrefix + "api/query_range", prometheus.InstrumentHandler( + pathPrefix + "api/query_range", handler(msrv.QueryRange), )) - http.Handle("/api/metrics", prometheus.InstrumentHandler( - "/api/metrics", handler(msrv.Metrics), + http.Handle(pathPrefix + "api/metrics", prometheus.InstrumentHandler( + pathPrefix + "api/metrics", handler(msrv.Metrics), )) } diff --git a/web/api/api_test.go b/web/api/api_test.go index d76f9f7f1..e185fbb9d 100644 --- a/web/api/api_test.go +++ b/web/api/api_test.go @@ -95,7 +95,7 @@ func TestQuery(t *testing.T) { Now: testNow, Storage: storage, } - api.RegisterHandler() + api.RegisterHandler("/") server := httptest.NewServer(http.DefaultServeMux) defer server.Close() diff --git a/web/consoles.go b/web/consoles.go index 6e0fd00da..d8874aaae 100644 --- a/web/consoles.go +++ b/web/consoles.go @@ -34,6 +34,7 @@ var ( // ConsolesHandler implements http.Handler. type ConsolesHandler struct { Storage local.Storage + PathPrefix string } func (h *ConsolesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -69,7 +70,7 @@ func (h *ConsolesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { Path: r.URL.Path, } - template := templates.NewTemplateExpander(string(text), "__console_"+r.URL.Path, data, clientmodel.Now(), h.Storage) + template := templates.NewTemplateExpander(string(text), "__console_"+r.URL.Path, data, clientmodel.Now(), h.Storage, h.PathPrefix) filenames, err := filepath.Glob(*consoleLibrariesPath + "/*.lib") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/web/handler.go b/web/handler.go index ba46993c0..c4a070a1b 100644 --- a/web/handler.go +++ b/web/handler.go @@ -17,6 +17,11 @@ import ( "net/http" ) -func graphHandler(w http.ResponseWriter, r *http.Request) { - executeTemplate(w, "graph", nil) +// GraphsHandler implements http.Handler. +type GraphsHandler struct { + PathPrefix string +} + +func (h *GraphsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + executeTemplate(w, "graph", nil, h.PathPrefix) } diff --git a/web/static/js/graph.js b/web/static/js/graph.js index 3a87ace49..73caf0204 100644 --- a/web/static/js/graph.js +++ b/web/static/js/graph.js @@ -4,6 +4,8 @@ var graphTemplate; var SECOND = 1000; +Handlebars.registerHelper('pathPrefix', function() { return PATH_PREFIX; }); + Prometheus.Graph = function(element, options) { this.el = element; this.options = options; @@ -158,7 +160,7 @@ Prometheus.Graph.prototype.populateInsertableMetrics = function() { var self = this; $.ajax({ method: "GET", - url: "/api/metrics", + url: PATH_PREFIX + "api/metrics", dataType: "json", success: function(json, textStatus) { var availableMetrics = []; @@ -310,7 +312,7 @@ Prometheus.Graph.prototype.submitQuery = function() { url = self.queryForm.attr("action"); success = function(json, textStatus) { self.handleGraphResponse(json, textStatus); }; } else { - url = "/api/query"; + url = PATH_PREFIX + "api/query"; success = function(text, textStatus) { self.handleConsoleResponse(text, textStatus); }; } @@ -609,7 +611,7 @@ function init() { }); $.ajax({ - url: "/static/js/graph_template.handlebar", + url: PATH_PREFIX + "static/js/graph_template.handlebar", success: function(data) { graphTemplate = Handlebars.compile(data); var options = parseGraphOptionsFromURL(); diff --git a/web/static/js/graph_template.handlebar b/web/static/js/graph_template.handlebar index 6f7326e6f..70b8d5f3b 100644 --- a/web/static/js/graph_template.handlebar +++ b/web/static/js/graph_template.handlebar @@ -1,5 +1,5 @@
-
+
@@ -14,7 +14,7 @@
- ajax_spinner + ajax_spinner
diff --git a/web/static/js/prom_console.js b/web/static/js/prom_console.js index a6c0079c6..3c088390c 100644 --- a/web/static/js/prom_console.js +++ b/web/static/js/prom_console.js @@ -502,7 +502,7 @@ PromConsole.Graph.prototype.dispatch = function() { var pending_requests = this.params.expr.length; for (var i = 0; i < this.params.expr.length; ++i) { var endTime = this.params.endTime; - var url = "/api/query_range?expr=" + encodeURIComponent(this.params.expr[i]) + var url = PATH_PREFIX + "api/query_range?expr=" + encodeURIComponent(this.params.expr[i]) + "&step=" + this.params.duration / this.graphTd.offsetWidth + "&range=" + this.params.duration + "&end=" + endTime; var xhr = new XMLHttpRequest(); @@ -539,7 +539,7 @@ PromConsole.Graph.prototype.dispatch = function() { } var loadingImg = document.createElement("img"); - loadingImg.src = '/static/img/ajax-loader.gif'; + loadingImg.src = PATH_PREFIX + 'static/img/ajax-loader.gif'; loadingImg.alt = 'Loading...'; loadingImg.className = 'prom_graph_loading'; this.graphTd.appendChild(loadingImg); @@ -605,6 +605,6 @@ PromConsole._graphsToSlashGraphURL = function(exprs) { for (var i = 0; i < exprs.length; ++i) { data.push({'expr': exprs[i], 'tab': 0}); } - return '/graph#' + encodeURIComponent(JSON.stringify(data)); + return PATH_PREFIX + 'graph#' + encodeURIComponent(JSON.stringify(data)); }; diff --git a/web/status.go b/web/status.go index af82d52ec..2e905dd2b 100644 --- a/web/status.go +++ b/web/status.go @@ -33,6 +33,7 @@ type PrometheusStatusHandler struct { TargetPools map[string]*retrieval.TargetPool Birth time.Time + PathPrefix string } // TargetStateToClass returns a map of TargetState to the name of a Bootstrap CSS class. @@ -45,5 +46,5 @@ func (h *PrometheusStatusHandler) TargetStateToClass() map[retrieval.TargetState } func (h *PrometheusStatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - executeTemplate(w, "status", h) + executeTemplate(w, "status", h, h.PathPrefix) } diff --git a/web/templates/_base.html b/web/templates/_base.html index 9079cc242..b32195cdc 100644 --- a/web/templates/_base.html +++ b/web/templates/_base.html @@ -3,10 +3,12 @@ Prometheus Time Series Collection and Processing Server - + - - + + + + {{template "head" .}} @@ -21,17 +23,17 @@ - Prometheus + Prometheus