mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-03-11 15:34:56 +00:00
vmalert: make UI and assets links relative (#2831)
* make all links in vmalert relative, so links continue to work even if vmalert sits behind the proxy; * update vmalert's routing to always have component-unique path prefix, e.g. /vmalert; See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2825 Signed-off-by: hagen1778 <roman@victoriametrics.com>
This commit is contained in:
parent
edc76286ac
commit
84e7c517d3
9 changed files with 716 additions and 690 deletions
|
@ -1,12 +1,19 @@
|
||||||
{% import (
|
{% import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
|
"net/http"
|
||||||
|
"strings"
|
||||||
) %}
|
) %}
|
||||||
|
|
||||||
{% func Footer() %}
|
|
||||||
{% code pathPrefix := httpserver.GetPathPrefix() %}
|
{% func Footer(r *http.Request) %}
|
||||||
|
{%code
|
||||||
|
prefix := "/vmalert/"
|
||||||
|
if strings.HasPrefix(r.URL.Path, prefix) {
|
||||||
|
prefix = ""
|
||||||
|
}
|
||||||
|
%}
|
||||||
</main>
|
</main>
|
||||||
<script src="{%s pathPrefix %}/static/js/jquery-3.6.0.min.js" type="text/javascript"></script>
|
<script src="{%s prefix %}static/js/jquery-3.6.0.min.js" type="text/javascript"></script>
|
||||||
<script src="{%s pathPrefix %}/static/js/bootstrap.bundle.min.js" type="text/javascript"></script>
|
<script src="{%s prefix %}static/js/bootstrap.bundle.min.js" type="text/javascript"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function expandAll() {
|
function expandAll() {
|
||||||
$('.collapse').addClass('show');
|
$('.collapse').addClass('show');
|
||||||
|
|
|
@ -6,43 +6,47 @@ package tpl
|
||||||
|
|
||||||
//line app/vmalert/tpl/footer.qtpl:1
|
//line app/vmalert/tpl/footer.qtpl:1
|
||||||
import (
|
import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
|
"net/http"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
//line app/vmalert/tpl/footer.qtpl:5
|
//line app/vmalert/tpl/footer.qtpl:7
|
||||||
import (
|
import (
|
||||||
qtio422016 "io"
|
qtio422016 "io"
|
||||||
|
|
||||||
qt422016 "github.com/valyala/quicktemplate"
|
qt422016 "github.com/valyala/quicktemplate"
|
||||||
)
|
)
|
||||||
|
|
||||||
//line app/vmalert/tpl/footer.qtpl:5
|
//line app/vmalert/tpl/footer.qtpl:7
|
||||||
var (
|
var (
|
||||||
_ = qtio422016.Copy
|
_ = qtio422016.Copy
|
||||||
_ = qt422016.AcquireByteBuffer
|
_ = qt422016.AcquireByteBuffer
|
||||||
)
|
)
|
||||||
|
|
||||||
//line app/vmalert/tpl/footer.qtpl:5
|
//line app/vmalert/tpl/footer.qtpl:7
|
||||||
func StreamFooter(qw422016 *qt422016.Writer) {
|
func StreamFooter(qw422016 *qt422016.Writer, r *http.Request) {
|
||||||
//line app/vmalert/tpl/footer.qtpl:5
|
//line app/vmalert/tpl/footer.qtpl:7
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
`)
|
`)
|
||||||
//line app/vmalert/tpl/footer.qtpl:6
|
//line app/vmalert/tpl/footer.qtpl:9
|
||||||
pathPrefix := httpserver.GetPathPrefix()
|
prefix := "/vmalert/"
|
||||||
|
if strings.HasPrefix(r.URL.Path, prefix) {
|
||||||
|
prefix = ""
|
||||||
|
}
|
||||||
|
|
||||||
//line app/vmalert/tpl/footer.qtpl:6
|
//line app/vmalert/tpl/footer.qtpl:13
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
</main>
|
</main>
|
||||||
<script src="`)
|
<script src="`)
|
||||||
//line app/vmalert/tpl/footer.qtpl:8
|
//line app/vmalert/tpl/footer.qtpl:15
|
||||||
qw422016.E().S(pathPrefix)
|
qw422016.E().S(prefix)
|
||||||
//line app/vmalert/tpl/footer.qtpl:8
|
//line app/vmalert/tpl/footer.qtpl:15
|
||||||
qw422016.N().S(`/static/js/jquery-3.6.0.min.js" type="text/javascript"></script>
|
qw422016.N().S(`static/js/jquery-3.6.0.min.js" type="text/javascript"></script>
|
||||||
<script src="`)
|
<script src="`)
|
||||||
//line app/vmalert/tpl/footer.qtpl:9
|
//line app/vmalert/tpl/footer.qtpl:16
|
||||||
qw422016.E().S(pathPrefix)
|
qw422016.E().S(prefix)
|
||||||
//line app/vmalert/tpl/footer.qtpl:9
|
//line app/vmalert/tpl/footer.qtpl:16
|
||||||
qw422016.N().S(`/static/js/bootstrap.bundle.min.js" type="text/javascript"></script>
|
qw422016.N().S(`static/js/bootstrap.bundle.min.js" type="text/javascript"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function expandAll() {
|
function expandAll() {
|
||||||
$('.collapse').addClass('show');
|
$('.collapse').addClass('show');
|
||||||
|
@ -75,31 +79,31 @@ func StreamFooter(qw422016 *qt422016.Writer) {
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`)
|
`)
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
}
|
}
|
||||||
|
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
func WriteFooter(qq422016 qtio422016.Writer) {
|
func WriteFooter(qq422016 qtio422016.Writer, r *http.Request) {
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
StreamFooter(qw422016)
|
StreamFooter(qw422016, r)
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
qt422016.ReleaseWriter(qw422016)
|
qt422016.ReleaseWriter(qw422016)
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
}
|
}
|
||||||
|
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
func Footer() string {
|
func Footer(r *http.Request) string {
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
qb422016 := qt422016.AcquireByteBuffer()
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
WriteFooter(qb422016)
|
WriteFooter(qb422016, r)
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
qs422016 := string(qb422016.B)
|
qs422016 := string(qb422016.B)
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
qt422016.ReleaseByteBuffer(qb422016)
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
return qs422016
|
return qs422016
|
||||||
//line app/vmalert/tpl/footer.qtpl:41
|
//line app/vmalert/tpl/footer.qtpl:48
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
{% import (
|
{% import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
|
"strings"
|
||||||
|
"net/http"
|
||||||
|
"path"
|
||||||
) %}
|
) %}
|
||||||
|
|
||||||
{% func Header(title string, pages []NavItem) %}
|
{% func Header(r *http.Request, navItems []NavItem, title string) %}
|
||||||
{% code pathPrefix := httpserver.GetPathPrefix() %}
|
{%code
|
||||||
|
prefix := "/vmalert/"
|
||||||
|
if strings.HasPrefix(r.URL.Path, prefix) {
|
||||||
|
prefix = ""
|
||||||
|
}
|
||||||
|
%}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>vmalert{% if title != "" %} - {%s title %}{% endif %}</title>
|
<title>vmalert{% if title != "" %} - {%s title %}{% endif %}</title>
|
||||||
<link href="{%s pathPrefix %}/static/css/bootstrap.min.css" rel="stylesheet" />
|
<link href="{%s prefix %}static/css/bootstrap.min.css" rel="stylesheet" />
|
||||||
<style>
|
<style>
|
||||||
body{
|
body{
|
||||||
min-height: 75rem;
|
min-height: 75rem;
|
||||||
|
@ -57,6 +64,37 @@
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{%= PrintNavItems(title, pages) %}
|
{%= printNavItems(r, title, navItems) %}
|
||||||
<main class="px-2">
|
<main class="px-2">
|
||||||
{% endfunc %}
|
{% endfunc %}
|
||||||
|
|
||||||
|
|
||||||
|
{% code
|
||||||
|
type NavItem struct {
|
||||||
|
Name string
|
||||||
|
Url string
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
{% func printNavItems(r *http.Request, current string, items []NavItem) %}
|
||||||
|
{%code
|
||||||
|
prefix := "/vmalert/"
|
||||||
|
if strings.HasPrefix(r.URL.Path, prefix) {
|
||||||
|
prefix = ""
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||||
|
<ul class="navbar-nav me-auto mb-2 mb-md-0">
|
||||||
|
{% for _, item := range items %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link{% if current == item.Name %} active{% endif %}" href="{%s path.Join(prefix,item.Url) %}">
|
||||||
|
{%s item.Name %}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
{% endfunc %}
|
|
@ -6,51 +6,56 @@ package tpl
|
||||||
|
|
||||||
//line app/vmalert/tpl/header.qtpl:1
|
//line app/vmalert/tpl/header.qtpl:1
|
||||||
import (
|
import (
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/lib/httpserver"
|
"net/http"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
//line app/vmalert/tpl/header.qtpl:5
|
//line app/vmalert/tpl/header.qtpl:7
|
||||||
import (
|
import (
|
||||||
qtio422016 "io"
|
qtio422016 "io"
|
||||||
|
|
||||||
qt422016 "github.com/valyala/quicktemplate"
|
qt422016 "github.com/valyala/quicktemplate"
|
||||||
)
|
)
|
||||||
|
|
||||||
//line app/vmalert/tpl/header.qtpl:5
|
//line app/vmalert/tpl/header.qtpl:7
|
||||||
var (
|
var (
|
||||||
_ = qtio422016.Copy
|
_ = qtio422016.Copy
|
||||||
_ = qt422016.AcquireByteBuffer
|
_ = qt422016.AcquireByteBuffer
|
||||||
)
|
)
|
||||||
|
|
||||||
//line app/vmalert/tpl/header.qtpl:5
|
//line app/vmalert/tpl/header.qtpl:7
|
||||||
func StreamHeader(qw422016 *qt422016.Writer, title string, pages []NavItem) {
|
func StreamHeader(qw422016 *qt422016.Writer, r *http.Request, navItems []NavItem, title string) {
|
||||||
//line app/vmalert/tpl/header.qtpl:5
|
//line app/vmalert/tpl/header.qtpl:7
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
`)
|
`)
|
||||||
//line app/vmalert/tpl/header.qtpl:6
|
//line app/vmalert/tpl/header.qtpl:9
|
||||||
pathPrefix := httpserver.GetPathPrefix()
|
prefix := "/vmalert/"
|
||||||
|
if strings.HasPrefix(r.URL.Path, prefix) {
|
||||||
|
prefix = ""
|
||||||
|
}
|
||||||
|
|
||||||
//line app/vmalert/tpl/header.qtpl:6
|
//line app/vmalert/tpl/header.qtpl:13
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>vmalert`)
|
<title>vmalert`)
|
||||||
//line app/vmalert/tpl/header.qtpl:10
|
//line app/vmalert/tpl/header.qtpl:17
|
||||||
if title != "" {
|
if title != "" {
|
||||||
//line app/vmalert/tpl/header.qtpl:10
|
//line app/vmalert/tpl/header.qtpl:17
|
||||||
qw422016.N().S(` - `)
|
qw422016.N().S(` - `)
|
||||||
//line app/vmalert/tpl/header.qtpl:10
|
//line app/vmalert/tpl/header.qtpl:17
|
||||||
qw422016.E().S(title)
|
qw422016.E().S(title)
|
||||||
//line app/vmalert/tpl/header.qtpl:10
|
//line app/vmalert/tpl/header.qtpl:17
|
||||||
}
|
}
|
||||||
//line app/vmalert/tpl/header.qtpl:10
|
//line app/vmalert/tpl/header.qtpl:17
|
||||||
qw422016.N().S(`</title>
|
qw422016.N().S(`</title>
|
||||||
<link href="`)
|
<link href="`)
|
||||||
//line app/vmalert/tpl/header.qtpl:11
|
//line app/vmalert/tpl/header.qtpl:18
|
||||||
qw422016.E().S(pathPrefix)
|
qw422016.E().S(prefix)
|
||||||
//line app/vmalert/tpl/header.qtpl:11
|
//line app/vmalert/tpl/header.qtpl:18
|
||||||
qw422016.N().S(`/static/css/bootstrap.min.css" rel="stylesheet" />
|
qw422016.N().S(`static/css/bootstrap.min.css" rel="stylesheet" />
|
||||||
<style>
|
<style>
|
||||||
body{
|
body{
|
||||||
min-height: 75rem;
|
min-height: 75rem;
|
||||||
|
@ -100,37 +105,124 @@ func StreamHeader(qw422016 *qt422016.Writer, title string, pages []NavItem) {
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
`)
|
`)
|
||||||
//line app/vmalert/tpl/header.qtpl:60
|
//line app/vmalert/tpl/header.qtpl:67
|
||||||
StreamPrintNavItems(qw422016, title, pages)
|
streamprintNavItems(qw422016, r, title, navItems)
|
||||||
//line app/vmalert/tpl/header.qtpl:60
|
//line app/vmalert/tpl/header.qtpl:67
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
<main class="px-2">
|
<main class="px-2">
|
||||||
`)
|
`)
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
}
|
}
|
||||||
|
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
func WriteHeader(qq422016 qtio422016.Writer, title string, pages []NavItem) {
|
func WriteHeader(qq422016 qtio422016.Writer, r *http.Request, navItems []NavItem, title string) {
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
StreamHeader(qw422016, title, pages)
|
StreamHeader(qw422016, r, navItems, title)
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
qt422016.ReleaseWriter(qw422016)
|
qt422016.ReleaseWriter(qw422016)
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
}
|
}
|
||||||
|
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
func Header(title string, pages []NavItem) string {
|
func Header(r *http.Request, navItems []NavItem, title string) string {
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
qb422016 := qt422016.AcquireByteBuffer()
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
WriteHeader(qb422016, title, pages)
|
WriteHeader(qb422016, r, navItems, title)
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
qs422016 := string(qb422016.B)
|
qs422016 := string(qb422016.B)
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
qt422016.ReleaseByteBuffer(qb422016)
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
return qs422016
|
return qs422016
|
||||||
//line app/vmalert/tpl/header.qtpl:62
|
//line app/vmalert/tpl/header.qtpl:69
|
||||||
|
}
|
||||||
|
|
||||||
|
//line app/vmalert/tpl/header.qtpl:73
|
||||||
|
type NavItem struct {
|
||||||
|
Name string
|
||||||
|
Url string
|
||||||
|
}
|
||||||
|
|
||||||
|
//line app/vmalert/tpl/header.qtpl:79
|
||||||
|
func streamprintNavItems(qw422016 *qt422016.Writer, r *http.Request, current string, items []NavItem) {
|
||||||
|
//line app/vmalert/tpl/header.qtpl:79
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:81
|
||||||
|
prefix := "/vmalert/"
|
||||||
|
if strings.HasPrefix(r.URL.Path, prefix) {
|
||||||
|
prefix = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
//line app/vmalert/tpl/header.qtpl:85
|
||||||
|
qw422016.N().S(`
|
||||||
|
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||||
|
<ul class="navbar-nav me-auto mb-2 mb-md-0">
|
||||||
|
`)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:90
|
||||||
|
for _, item := range items {
|
||||||
|
//line app/vmalert/tpl/header.qtpl:90
|
||||||
|
qw422016.N().S(`
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link`)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:92
|
||||||
|
if current == item.Name {
|
||||||
|
//line app/vmalert/tpl/header.qtpl:92
|
||||||
|
qw422016.N().S(` active`)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:92
|
||||||
|
}
|
||||||
|
//line app/vmalert/tpl/header.qtpl:92
|
||||||
|
qw422016.N().S(`" href="`)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:92
|
||||||
|
qw422016.E().S(path.Join(prefix, item.Url))
|
||||||
|
//line app/vmalert/tpl/header.qtpl:92
|
||||||
|
qw422016.N().S(`">
|
||||||
|
`)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:93
|
||||||
|
qw422016.E().S(item.Name)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:93
|
||||||
|
qw422016.N().S(`
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
`)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:96
|
||||||
|
}
|
||||||
|
//line app/vmalert/tpl/header.qtpl:96
|
||||||
|
qw422016.N().S(`
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
`)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
}
|
||||||
|
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
func writeprintNavItems(qq422016 qtio422016.Writer, r *http.Request, current string, items []NavItem) {
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
streamprintNavItems(qw422016, r, current, items)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
}
|
||||||
|
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
func printNavItems(r *http.Request, current string, items []NavItem) string {
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
writeprintNavItems(qb422016, r, current, items)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
|
return qs422016
|
||||||
|
//line app/vmalert/tpl/header.qtpl:100
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
{% code
|
|
||||||
type NavItem struct {
|
|
||||||
Name string
|
|
||||||
Url string
|
|
||||||
}
|
|
||||||
%}
|
|
||||||
|
|
||||||
{% func PrintNavItems(current string, items []NavItem) %}
|
|
||||||
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
|
||||||
<ul class="navbar-nav me-auto mb-2 mb-md-0">
|
|
||||||
{% for _, item := range items %}
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link{% if current == item.Name %} active{% endif %}" href="{%s item.Url %}">
|
|
||||||
{%s item.Name %}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
{% endfunc %}
|
|
||||||
|
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
// Code generated by qtc from "nav.qtpl". DO NOT EDIT.
|
|
||||||
// See https://github.com/valyala/quicktemplate for details.
|
|
||||||
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:1
|
|
||||||
package tpl
|
|
||||||
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:1
|
|
||||||
import (
|
|
||||||
qtio422016 "io"
|
|
||||||
|
|
||||||
qt422016 "github.com/valyala/quicktemplate"
|
|
||||||
)
|
|
||||||
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:1
|
|
||||||
var (
|
|
||||||
_ = qtio422016.Copy
|
|
||||||
_ = qt422016.AcquireByteBuffer
|
|
||||||
)
|
|
||||||
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:2
|
|
||||||
type NavItem struct {
|
|
||||||
Name string
|
|
||||||
Url string
|
|
||||||
}
|
|
||||||
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:8
|
|
||||||
func StreamPrintNavItems(qw422016 *qt422016.Writer, current string, items []NavItem) {
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:8
|
|
||||||
qw422016.N().S(`
|
|
||||||
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
|
||||||
<ul class="navbar-nav me-auto mb-2 mb-md-0">
|
|
||||||
`)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:13
|
|
||||||
for _, item := range items {
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:13
|
|
||||||
qw422016.N().S(`
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link`)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:15
|
|
||||||
if current == item.Name {
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:15
|
|
||||||
qw422016.N().S(` active`)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:15
|
|
||||||
}
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:15
|
|
||||||
qw422016.N().S(`" href="`)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:15
|
|
||||||
qw422016.E().S(item.Url)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:15
|
|
||||||
qw422016.N().S(`">
|
|
||||||
`)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:16
|
|
||||||
qw422016.E().S(item.Name)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:16
|
|
||||||
qw422016.N().S(`
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
`)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:19
|
|
||||||
}
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:19
|
|
||||||
qw422016.N().S(`
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
`)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
}
|
|
||||||
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
func WritePrintNavItems(qq422016 qtio422016.Writer, current string, items []NavItem) {
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
StreamPrintNavItems(qw422016, current, items)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
qt422016.ReleaseWriter(qw422016)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
}
|
|
||||||
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
func PrintNavItems(current string, items []NavItem) string {
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
qb422016 := qt422016.AcquireByteBuffer()
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
WritePrintNavItems(qb422016, current, items)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
qs422016 := string(qb422016.B)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
qt422016.ReleaseByteBuffer(qb422016)
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
return qs422016
|
|
||||||
//line app/vmalert/tpl/nav.qtpl:23
|
|
||||||
}
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -24,30 +23,24 @@ var (
|
||||||
navItems []tpl.NavItem
|
navItems []tpl.NavItem
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
//go:embed static
|
|
||||||
staticFiles embed.FS
|
|
||||||
staticServer = http.FileServer(http.FS(staticFiles))
|
|
||||||
)
|
|
||||||
|
|
||||||
func initLinks() {
|
func initLinks() {
|
||||||
pathPrefix := httpserver.GetPathPrefix()
|
|
||||||
if pathPrefix == "" {
|
|
||||||
pathPrefix = "/"
|
|
||||||
}
|
|
||||||
apiLinks = [][2]string{
|
apiLinks = [][2]string{
|
||||||
{path.Join(pathPrefix, "api/v1/rules"), "list all loaded groups and rules"},
|
// api links are relative since they can be used by external clients
|
||||||
{path.Join(pathPrefix, "api/v1/alerts"), "list all active alerts"},
|
// such as Grafana and proxied via vmselect.
|
||||||
{path.Join(pathPrefix, "api/v1/groupID/alertID/status"), "get alert status by ID"},
|
{"api/v1/rules", "list all loaded groups and rules"},
|
||||||
{path.Join(pathPrefix, "flags"), "command-line flags"},
|
{"api/v1/alerts", "list all active alerts"},
|
||||||
{path.Join(pathPrefix, "metrics"), "list of application metrics"},
|
{"api/v1/groupID/alertID/status", "get alert status by ID"},
|
||||||
{path.Join(pathPrefix, "-/reload"), "reload configuration"},
|
|
||||||
|
// system links
|
||||||
|
{"/flags", "command-line flags"},
|
||||||
|
{"/metrics", "list of application metrics"},
|
||||||
|
{"/-/reload", "reload configuration"},
|
||||||
}
|
}
|
||||||
navItems = []tpl.NavItem{
|
navItems = []tpl.NavItem{
|
||||||
{Name: "vmalert", Url: path.Join(pathPrefix, "/")},
|
{Name: "vmalert", Url: "home"},
|
||||||
{Name: "Groups", Url: path.Join(pathPrefix, "groups")},
|
{Name: "Groups", Url: "groups"},
|
||||||
{Name: "Alerts", Url: path.Join(pathPrefix, "alerts")},
|
{Name: "Alerts", Url: "alerts"},
|
||||||
{Name: "Notifiers", Url: path.Join(pathPrefix, "notifiers")},
|
{Name: "Notifiers", Url: "notifiers"},
|
||||||
{Name: "Docs", Url: "https://docs.victoriametrics.com/vmalert.html"},
|
{Name: "Docs", Url: "https://docs.victoriametrics.com/vmalert.html"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,33 +49,50 @@ type requestHandler struct {
|
||||||
m *manager
|
m *manager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
//go:embed static
|
||||||
|
staticFiles embed.FS
|
||||||
|
staticHandler = http.FileServer(http.FS(staticFiles))
|
||||||
|
staticServer = http.StripPrefix("/vmalert", staticHandler)
|
||||||
|
)
|
||||||
|
|
||||||
func (rh *requestHandler) handler(w http.ResponseWriter, r *http.Request) bool {
|
func (rh *requestHandler) handler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
initLinks()
|
initLinks()
|
||||||
})
|
})
|
||||||
|
|
||||||
pathPrefix := httpserver.GetPathPrefix()
|
if strings.HasPrefix(r.URL.Path, "/vmalert/static") {
|
||||||
if pathPrefix == "" {
|
staticServer.ServeHTTP(w, r)
|
||||||
pathPrefix = "/"
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
switch r.URL.Path {
|
switch r.URL.Path {
|
||||||
case "/":
|
case "/", "/vmalert", "/vmalert/home":
|
||||||
if r.Method != "GET" {
|
if r.Method != "GET" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
WriteWelcome(w)
|
WriteWelcome(w, r)
|
||||||
return true
|
return true
|
||||||
case "/alerts":
|
case "/vmalert/alerts":
|
||||||
WriteListAlerts(w, pathPrefix, rh.groupAlerts())
|
WriteListAlerts(w, r, rh.groupAlerts())
|
||||||
return true
|
return true
|
||||||
case "/groups", "/rules":
|
case "/vmalert/groups":
|
||||||
WriteListGroups(w, rh.groups())
|
WriteListGroups(w, r, rh.groups())
|
||||||
return true
|
return true
|
||||||
case "/notifiers":
|
case "/vmalert/notifiers":
|
||||||
WriteListTargets(w, notifier.GetTargets())
|
WriteListTargets(w, r, notifier.GetTargets())
|
||||||
return true
|
return true
|
||||||
case "/api/v1/rules":
|
|
||||||
|
// special cases for Grafana requests,
|
||||||
|
// served without `vmalert` prefix:
|
||||||
|
case "/rules":
|
||||||
|
// Grafana makes an extra request to `/rules`
|
||||||
|
// handler in addition to `/api/v1/rules` calls in alerts UI,
|
||||||
|
WriteListGroups(w, r, rh.groups())
|
||||||
|
return true
|
||||||
|
|
||||||
|
case "/vmalert/api/v1/rules", "/api/v1/rules":
|
||||||
|
// path used by Grafana for ng alerting
|
||||||
data, err := rh.listGroups()
|
data, err := rh.listGroups()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpserver.Errorf(w, r, "%s", err)
|
httpserver.Errorf(w, r, "%s", err)
|
||||||
|
@ -91,7 +101,8 @@ func (rh *requestHandler) handler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
return true
|
return true
|
||||||
case "/api/v1/alerts":
|
case "/vmalert/api/v1/alerts", "/api/v1/alerts":
|
||||||
|
// path used by Grafana for ng alerting
|
||||||
data, err := rh.listAlerts()
|
data, err := rh.listAlerts()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpserver.Errorf(w, r, "%s", err)
|
httpserver.Errorf(w, r, "%s", err)
|
||||||
|
@ -100,17 +111,14 @@ func (rh *requestHandler) handler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.Write(data)
|
w.Write(data)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case "/-/reload":
|
case "/-/reload":
|
||||||
logger.Infof("api config reload was called, sending sighup")
|
logger.Infof("api config reload was called, sending sighup")
|
||||||
procutil.SelfSIGHUP()
|
procutil.SelfSIGHUP()
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
return true
|
return true
|
||||||
default:
|
|
||||||
if strings.HasPrefix(r.URL.Path, "/static") {
|
|
||||||
staticServer.ServeHTTP(w, r)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
default:
|
||||||
if !strings.HasSuffix(r.URL.Path, "/status") {
|
if !strings.HasSuffix(r.URL.Path, "/status") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -133,7 +141,7 @@ func (rh *requestHandler) handler(w http.ResponseWriter, r *http.Request) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// <groupID>/<alertID>/status
|
// <groupID>/<alertID>/status
|
||||||
WriteAlert(w, pathPrefix, alert)
|
WriteAlert(w, r, alert)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,15 @@
|
||||||
"time"
|
"time"
|
||||||
"sort"
|
"sort"
|
||||||
"path"
|
"path"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmalert/tpl"
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmalert/tpl"
|
||||||
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmalert/notifier"
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmalert/notifier"
|
||||||
) %}
|
) %}
|
||||||
|
|
||||||
|
|
||||||
{% func Welcome() %}
|
{% func Welcome(r *http.Request) %}
|
||||||
{%= tpl.Header("vmalert", navItems) %}
|
{%= tpl.Header(r, navItems, "vmalert") %}
|
||||||
<p>
|
<p>
|
||||||
API:<br>
|
API:<br>
|
||||||
{% for _, p := range apiLinks %}
|
{% for _, p := range apiLinks %}
|
||||||
|
@ -21,11 +22,11 @@
|
||||||
<a href="{%s p %}">{%s p %}</a> - {%s doc %}<br/>
|
<a href="{%s p %}">{%s p %}</a> - {%s doc %}<br/>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
{%= tpl.Footer() %}
|
{%= tpl.Footer(r) %}
|
||||||
{% endfunc %}
|
{% endfunc %}
|
||||||
|
|
||||||
{% func ListGroups(groups []APIGroup) %}
|
{% func ListGroups(r *http.Request, groups []APIGroup) %}
|
||||||
{%= tpl.Header("Groups", navItems) %}
|
{%= tpl.Header(r, navItems, "Groups") %}
|
||||||
{% if len(groups) > 0 %}
|
{% if len(groups) > 0 %}
|
||||||
{%code
|
{%code
|
||||||
rOk := make(map[string]int)
|
rOk := make(map[string]int)
|
||||||
|
@ -112,13 +113,13 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{%= tpl.Footer() %}
|
{%= tpl.Footer(r) %}
|
||||||
|
|
||||||
{% endfunc %}
|
{% endfunc %}
|
||||||
|
|
||||||
|
|
||||||
{% func ListAlerts(pathPrefix string, groupAlerts []GroupAlerts) %}
|
{% func ListAlerts(r *http.Request, groupAlerts []GroupAlerts) %}
|
||||||
{%= tpl.Header("Alerts", navItems) %}
|
{%= tpl.Header(r, navItems, "Alerts") %}
|
||||||
{% if len(groupAlerts) > 0 %}
|
{% if len(groupAlerts) > 0 %}
|
||||||
<a class="btn btn-primary" role="button" onclick="collapseAll()">Collapse All</a>
|
<a class="btn btn-primary" role="button" onclick="collapseAll()">Collapse All</a>
|
||||||
<a class="btn btn-primary" role="button" onclick="expandAll()">Expand All</a>
|
<a class="btn btn-primary" role="button" onclick="expandAll()">Expand All</a>
|
||||||
|
@ -182,7 +183,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td>{%s ar.Value %}</td>
|
<td>{%s ar.Value %}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{%s path.Join(pathPrefix, g.ID, ar.ID, "status") %}">Details</a>
|
<a href="{%s path.Join(g.ID, ar.ID, "status") %}">Details</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -199,12 +200,12 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{%= tpl.Footer() %}
|
{%= tpl.Footer(r) %}
|
||||||
|
|
||||||
{% endfunc %}
|
{% endfunc %}
|
||||||
|
|
||||||
{% func ListTargets(targets map[notifier.TargetType][]notifier.Target) %}
|
{% func ListTargets(r *http.Request, targets map[notifier.TargetType][]notifier.Target) %}
|
||||||
{%= tpl.Header("Notifiers", navItems) %}
|
{%= tpl.Header(r, navItems, "Notifiers") %}
|
||||||
{% if len(targets) > 0 %}
|
{% if len(targets) > 0 %}
|
||||||
<a class="btn btn-primary" role="button" onclick="collapseAll()">Collapse All</a>
|
<a class="btn btn-primary" role="button" onclick="collapseAll()">Collapse All</a>
|
||||||
<a class="btn btn-primary" role="button" onclick="expandAll()">Expand All</a>
|
<a class="btn btn-primary" role="button" onclick="expandAll()">Expand All</a>
|
||||||
|
@ -255,12 +256,12 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{%= tpl.Footer() %}
|
{%= tpl.Footer(r) %}
|
||||||
|
|
||||||
{% endfunc %}
|
{% endfunc %}
|
||||||
|
|
||||||
{% func Alert(pathPrefix string, alert *APIAlert) %}
|
{% func Alert(r *http.Request, alert *APIAlert) %}
|
||||||
{%= tpl.Header("", navItems) %}
|
{%= tpl.Header(r, navItems, "") %}
|
||||||
{%code
|
{%code
|
||||||
var labelKeys []string
|
var labelKeys []string
|
||||||
for k := range alert.Labels {
|
for k := range alert.Labels {
|
||||||
|
@ -326,7 +327,7 @@
|
||||||
Group
|
Group
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<a target="_blank" href="{%s path.Join(pathPrefix,"groups") %}#group-{%s alert.GroupID %}">{%s alert.GroupID %}</a>
|
<a target="_blank" href="/groups#group-{%s alert.GroupID %}">{%s alert.GroupID %}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -340,7 +341,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{%= tpl.Footer() %}
|
{%= tpl.Footer(r) %}
|
||||||
|
|
||||||
{% endfunc %}
|
{% endfunc %}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue