mirror of
https://github.com/prometheus/prometheus.git
synced 2024-11-09 23:24:05 -08:00
Make all paths absolute to support proxies
This commit is contained in:
parent
b456240c46
commit
0e18784c64
|
@ -12,12 +12,12 @@
|
|||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/">Prometheus</a>
|
||||
<a class="navbar-brand" href="{{ pathPrefix }}">Prometheus</a>
|
||||
</div>
|
||||
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li><a href="/alerts">Alerts</a></li>
|
||||
<li><a href="{{ pathPrefix }}alerts">Alerts</a></li>
|
||||
<li><a href="https://www.pagerduty.com/">PagerDuty</a></li>
|
||||
</div>
|
||||
</ul>
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
{{/* vim: set ft=html: */}}
|
||||
{{/* Load Prometheus console library JS/CSS. Should go in <head> */}}
|
||||
{{ define "prom_console_head" }}
|
||||
<link type="text/css" rel="stylesheet" href="/static/vendor/rickshaw/rickshaw.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="/static/vendor/bootstrap-3.3.1/css/bootstrap.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="/static/css/prom_console.css">
|
||||
<script src="/static/vendor/rickshaw/vendor/d3.v3.js"></script>
|
||||
<script src="/static/vendor/rickshaw/vendor/d3.layout.min.js"></script>
|
||||
<script src="/static/vendor/rickshaw/rickshaw.min.js"></script>
|
||||
<script src="/static/vendor/js/jquery.min.js"></script>
|
||||
<script src="/static/vendor/bootstrap-3.3.1/js/bootstrap.min.js"></script>
|
||||
<script src="/static/js/prom_console.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="{{ pathPrefix }}static/vendor/rickshaw/rickshaw.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="{{ pathPrefix }}static/vendor/bootstrap-3.3.1/css/bootstrap.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="{{ pathPrefix }}static/css/prom_console.css">
|
||||
<script src="{{ pathPrefix }}static/vendor/rickshaw/vendor/d3.v3.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/rickshaw/vendor/d3.layout.min.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/rickshaw/rickshaw.min.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/js/jquery.min.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/bootstrap-3.3.1/js/bootstrap.min.js"></script>
|
||||
|
||||
<script>var PATH_PREFIX = "{{ pathPrefix }}";</script>
|
||||
<script src="{{ pathPrefix }}static/js/prom_console.js"></script>
|
||||
{{ end }}
|
||||
|
||||
{{/* Top of all pages. */}}
|
||||
|
|
24
main.go
24
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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
))
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div id="graph_wrapper{{id}}" class="graph_wrapper">
|
||||
<form action="/api/query_range" method="GET" class="query_form form-inline">
|
||||
<form action="{{ pathPrefix }}api/query_range" method="GET" class="query_form form-inline">
|
||||
<div class="row">
|
||||
<div class="col-lg-10">
|
||||
<span class="input-group expression_input_group">
|
||||
|
@ -14,7 +14,7 @@
|
|||
</div>
|
||||
<div class="col-lg-2">
|
||||
<div class="eval_stats pull-right"></div>
|
||||
<img src="/static/img/ajax-loader.gif" class="spinner" alt="ajax_spinner">
|
||||
<img src="{{ pathPrefix }}static/img/ajax-loader.gif" class="spinner" alt="ajax_spinner">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
|
|
@ -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));
|
||||
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>Prometheus Time Series Collection and Processing Server</title>
|
||||
<script src="/static/vendor/js/jquery.min.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/js/jquery.min.js"></script>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="/static/vendor/bootstrap-3.3.1/css/bootstrap.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="/static/css/prometheus.css">
|
||||
<link type="text/css" rel="stylesheet" href="{{ pathPrefix }}static/vendor/bootstrap-3.3.1/css/bootstrap.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="{{ pathPrefix }}static/css/prometheus.css">
|
||||
|
||||
<script>var PATH_PREFIX = "{{ pathPrefix }}";</script>
|
||||
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
@ -21,17 +23,17 @@
|
|||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="/">Prometheus</a>
|
||||
<a class="navbar-brand" href="{{ pathPrefix }}">Prometheus</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-left">
|
||||
{{$consoles := getConsoles}}
|
||||
{{if $consoles}}
|
||||
<li><a href="{{$consoles}}">Consoles</a></li>
|
||||
<li><a href="{{ pathPrefix }}{{$consoles}}">Consoles</a></li>
|
||||
{{ end }}
|
||||
<li><a href="/alerts">Alerts</a></li>
|
||||
<li><a href="/graph">Graph</a></li>
|
||||
<li><a href="/">Status</a></li>
|
||||
<li><a href="{{ pathPrefix }}alerts">Alerts</a></li>
|
||||
<li><a href="{{ pathPrefix }}graph">Graph</a></li>
|
||||
<li><a href="{{ pathPrefix }}">Status</a></li>
|
||||
<li>
|
||||
<a href="http://prometheus.io" target="_blank">Help</a>
|
||||
</li>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{define "head"}}
|
||||
<link type="text/css" rel="stylesheet" href="/static/css/alerts.css">
|
||||
<script src="/static/js/alerts.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="{{ pathPrefix }}static/css/alerts.css">
|
||||
<script src="{{ pathPrefix }}static/js/alerts.js"></script>
|
||||
{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
{{define "head"}}
|
||||
<script src="/static/vendor/bootstrap-3.3.1/js/bootstrap.min.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/bootstrap-3.3.1/js/bootstrap.min.js"></script>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="/static/css/graph.css">
|
||||
<link type="text/css" rel="stylesheet" href="{{ pathPrefix }}static/css/graph.css">
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="/static/vendor/rickshaw/rickshaw.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="/static/vendor/bootstrap-datetimepicker/bootstrap-datetimepicker.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="{{ pathPrefix }}static/vendor/rickshaw/rickshaw.min.css">
|
||||
<link type="text/css" rel="stylesheet" href="{{ pathPrefix }}static/vendor/bootstrap-datetimepicker/bootstrap-datetimepicker.min.css">
|
||||
|
||||
<script src="/static/vendor/rickshaw/vendor/d3.v3.js"></script>
|
||||
<script src="/static/vendor/rickshaw/vendor/d3.layout.min.js"></script>
|
||||
<script src="/static/vendor/rickshaw/rickshaw.min.js"></script>
|
||||
<script src="/static/vendor/bootstrap-datetimepicker/bootstrap-datetimepicker.js"></script>
|
||||
<script src="/static/vendor/bootstrap3-typeahead/bootstrap3-typeahead.min.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/rickshaw/vendor/d3.v3.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/rickshaw/vendor/d3.layout.min.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/rickshaw/rickshaw.min.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/bootstrap-datetimepicker/bootstrap-datetimepicker.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/bootstrap3-typeahead/bootstrap3-typeahead.min.js"></script>
|
||||
|
||||
<script src="/static/vendor/js/handlebars.js"></script>
|
||||
<script src="/static/vendor/js/jquery.selection.js"></script>
|
||||
<script src="/static/vendor/js/jquery.hotkeys.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/js/handlebars.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/js/jquery.selection.js"></script>
|
||||
<script src="{{ pathPrefix }}static/vendor/js/jquery.hotkeys.js"></script>
|
||||
|
||||
<script src="/static/js/graph.js"></script>
|
||||
<script src="{{ pathPrefix }}static/js/graph.js"></script>
|
||||
|
||||
<script id="graph_template" type="text/x-handlebars-template"></script>
|
||||
{{end}}
|
||||
|
|
73
web/web.go
73
web/web.go
|
@ -21,6 +21,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
pprof_runtime "runtime/pprof"
|
||||
|
@ -47,52 +48,60 @@ type WebService struct {
|
|||
MetricsHandler *api.MetricsService
|
||||
AlertsHandler *AlertsHandler
|
||||
ConsolesHandler *ConsolesHandler
|
||||
GraphsHandler *GraphsHandler
|
||||
|
||||
QuitChan chan struct{}
|
||||
}
|
||||
|
||||
// ServeForever serves the HTTP endpoints and only returns upon errors.
|
||||
func (ws WebService) ServeForever() error {
|
||||
func (ws WebService) ServeForever(pathPrefix string) error {
|
||||
|
||||
http.Handle("/favicon.ico", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "", 404)
|
||||
}))
|
||||
|
||||
http.Handle("/", prometheus.InstrumentHandler(
|
||||
"/", ws.StatusHandler,
|
||||
http.Handle(pathPrefix, prometheus.InstrumentHandler(
|
||||
pathPrefix, ws.StatusHandler,
|
||||
))
|
||||
http.Handle("/alerts", prometheus.InstrumentHandler(
|
||||
"/alerts", ws.AlertsHandler,
|
||||
http.Handle(pathPrefix + "alerts", prometheus.InstrumentHandler(
|
||||
pathPrefix + "alerts", ws.AlertsHandler,
|
||||
))
|
||||
http.Handle("/consoles/", prometheus.InstrumentHandler(
|
||||
"/consoles/", http.StripPrefix("/consoles/", ws.ConsolesHandler),
|
||||
http.Handle(pathPrefix + "consoles/", prometheus.InstrumentHandler(
|
||||
pathPrefix + "consoles/", http.StripPrefix(pathPrefix + "consoles/", ws.ConsolesHandler),
|
||||
))
|
||||
http.Handle("/graph", prometheus.InstrumentHandler(
|
||||
"/graph", http.HandlerFunc(graphHandler),
|
||||
http.Handle(pathPrefix + "graph", prometheus.InstrumentHandler(
|
||||
pathPrefix + "graph", ws.GraphsHandler,
|
||||
))
|
||||
http.Handle("/heap", prometheus.InstrumentHandler(
|
||||
"/heap", http.HandlerFunc(dumpHeap),
|
||||
http.Handle(pathPrefix + "heap", prometheus.InstrumentHandler(
|
||||
pathPrefix + "heap", http.HandlerFunc(dumpHeap),
|
||||
))
|
||||
|
||||
ws.MetricsHandler.RegisterHandler()
|
||||
http.Handle(*metricsPath, prometheus.Handler())
|
||||
ws.MetricsHandler.RegisterHandler(pathPrefix)
|
||||
http.Handle(pathPrefix + strings.TrimLeft(*metricsPath, "/"), prometheus.Handler())
|
||||
if *useLocalAssets {
|
||||
http.Handle("/static/", prometheus.InstrumentHandler(
|
||||
"/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static"))),
|
||||
http.Handle(pathPrefix + "static/", prometheus.InstrumentHandler(
|
||||
pathPrefix + "static/", http.StripPrefix(pathPrefix + "static/", http.FileServer(http.Dir("web/static"))),
|
||||
))
|
||||
} else {
|
||||
http.Handle("/static/", prometheus.InstrumentHandler(
|
||||
"/static/", http.StripPrefix("/static/", new(blob.Handler)),
|
||||
http.Handle(pathPrefix + "static/", prometheus.InstrumentHandler(
|
||||
pathPrefix + "static/", http.StripPrefix(pathPrefix + "static/", new(blob.Handler)),
|
||||
))
|
||||
}
|
||||
|
||||
if *userAssetsPath != "" {
|
||||
http.Handle("/user/", prometheus.InstrumentHandler(
|
||||
"/user/", http.StripPrefix("/user/", http.FileServer(http.Dir(*userAssetsPath))),
|
||||
http.Handle(pathPrefix + "user/", prometheus.InstrumentHandler(
|
||||
pathPrefix + "user/", http.StripPrefix(pathPrefix + "user/", http.FileServer(http.Dir(*userAssetsPath))),
|
||||
))
|
||||
}
|
||||
|
||||
if *enableQuit {
|
||||
http.Handle("/-/quit", http.HandlerFunc(ws.quitHandler))
|
||||
http.Handle(pathPrefix + "-/quit", http.HandlerFunc(ws.quitHandler))
|
||||
}
|
||||
|
||||
if pathPrefix != "/" {
|
||||
http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, pathPrefix, http.StatusFound)
|
||||
}))
|
||||
}
|
||||
|
||||
glog.Info("listening on ", *listenAddress)
|
||||
|
@ -129,23 +138,25 @@ func getTemplateFile(name string) (string, error) {
|
|||
return string(file), nil
|
||||
}
|
||||
|
||||
func getConsoles() string {
|
||||
if _, err := os.Stat(*consoleTemplatesPath + "/index.html"); !os.IsNotExist(err) {
|
||||
return "/consoles/index.html"
|
||||
func getConsoles(pathPrefix string) string {
|
||||
if _, err := os.Stat(pathPrefix + *consoleTemplatesPath + "/index.html"); !os.IsNotExist(err) {
|
||||
return pathPrefix + "consoles/index.html"
|
||||
}
|
||||
if *userAssetsPath != "" {
|
||||
if _, err := os.Stat(*userAssetsPath + "/index.html"); !os.IsNotExist(err) {
|
||||
return "/user/index.html"
|
||||
if _, err := os.Stat(pathPrefix + *userAssetsPath + "/index.html"); !os.IsNotExist(err) {
|
||||
return pathPrefix + "user/index.html"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getTemplate(name string) (t *template.Template, err error) {
|
||||
func getTemplate(name string, pathPrefix string) (t *template.Template, err error) {
|
||||
t = template.New("_base")
|
||||
|
||||
t.Funcs(template.FuncMap{
|
||||
"since": time.Since,
|
||||
"getConsoles": getConsoles,
|
||||
"getConsoles": func() string { return getConsoles(pathPrefix) },
|
||||
"pathPrefix": func() string { return pathPrefix },
|
||||
})
|
||||
file, err := getTemplateFile("_base")
|
||||
if err != nil {
|
||||
|
@ -163,8 +174,8 @@ func getTemplate(name string) (t *template.Template, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func executeTemplate(w http.ResponseWriter, name string, data interface{}) {
|
||||
tpl, err := getTemplate(name)
|
||||
func executeTemplate(w http.ResponseWriter, name string, data interface{}, pathPrefix string) {
|
||||
tpl, err := getTemplate(name, pathPrefix)
|
||||
if err != nil {
|
||||
glog.Error("Error preparing layout template: ", err)
|
||||
return
|
||||
|
@ -188,7 +199,7 @@ func dumpHeap(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// MustBuildServerURL returns the server URL and panics in case an error occurs.
|
||||
func MustBuildServerURL() string {
|
||||
func MustBuildServerURL(pathPrefix string) string {
|
||||
_, port, err := net.SplitHostPort(*listenAddress)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -197,5 +208,5 @@ func MustBuildServerURL() string {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return fmt.Sprintf("http://%s:%s", hostname, port)
|
||||
return fmt.Sprintf("http://%s:%s%s", hostname, port, pathPrefix)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue