lib/promscrape: adds service discovery visualization for /targets page(#2675)

* lib/promscrape: updated template

* lib/promscrape: fixed click on unhealthy and all btns

* app/vmselect: jquery scripts into static folder

Co-authored-by: f41gh7 <nik@victoriametrics.com>
This commit is contained in:
Dmytro Kozlov 2022-06-03 16:38:45 +03:00 committed by GitHub
parent a18914abee
commit 8edb390e21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 1287 additions and 569 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -15,6 +15,7 @@ The following tip changes can be tested by building VictoriaMetrics components f
## tip ## tip
* FEATURE: adds service discovery visualisation tab for `/targets` page. It simplifies service discovery debugging. See [this PR](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/2675).
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): Allows using kubeconfig file within `kubernetes_sd_configs`. It may be useful for kubernetes cluster monitoring by `vmagent` outside kubernetes cluster. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1464). * FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): Allows using kubeconfig file within `kubernetes_sd_configs`. It may be useful for kubernetes cluster monitoring by `vmagent` outside kubernetes cluster. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1464).
* FEATURE: allow overriding default limits for in-memory cache `indexdb/tagFilters` via flag `-storage.cacheSizeIndexDBTagFilters`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2663). * FEATURE: allow overriding default limits for in-memory cache `indexdb/tagFilters` via flag `-storage.cacheSizeIndexDBTagFilters`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2663).
* FEATURE: add support of `lowercase` and `uppercase` relabeling actions in the same way as [Prometheus 2.36.0 does](https://github.com/prometheus/prometheus/releases/tag/v2.36.0). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2664). * FEATURE: add support of `lowercase` and `uppercase` relabeling actions in the same way as [Prometheus 2.36.0 does](https://github.com/prometheus/prometheus/releases/tag/v2.36.0). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2664).

View file

@ -0,0 +1,82 @@
{% import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
) %}
{% func ServiceDiscovery(jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, droppedKeyStatuses []droppedKeyStatus) %}
<div class="row mt-4">
<div class="col-12">
{% for i, js := range jts %}
{% if showOnlyUnhealthy && js.upCount == js.targetsTotal %}{% continue %}{% endif %}
<h4>
<span class="me-2">{%s js.job %}{% space %}({%d js.upCount %}/{%d js.targetsTotal %}{% space %}up)</span>
<button type="button" class="btn btn-primary btn-sm me-1"
onclick="document.querySelector('.table-discovery-{%d i %}').style.display='none'">collapse
</button>
<button type="button" class="btn btn-secondary btn-sm me-1"
onclick="document.querySelector('.table-discovery-{%d i %}').style.display='block'">expand
</button>
</h4>
<div id="table-discovery-{%d i %}" class="table-responsive table-discovery-{%d i %}">
<table class="table table-striped table-hover table-bordered table-sm">
<thead>
<tr>
<th scope="col" style="width: 50%">Discovered Labels</th>
<th scope="col" style="width: 50%">Target Labels</th>
</tr>
</thead>
<tbody class="list-{%d i %}">
{% for _, ts := range js.targetsStatus %}
{% if showOnlyUnhealthy && ts.up %}{% continue %}{% endif %}
<tr {% if !ts.up %}{%space%}class="alert alert-danger" role="alert" {% endif %}>
<td class="labels">
{%= formatLabel(ts.sw.Config.OriginalLabels) %}
</td>
<td class="labels">
{%= formatLabel(promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels)) %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endfor %}
</div>
</div>
{% for i,jobName := range emptyJobs %}
<div>
<h4>
<a>{%s jobName %} (0/0 up)</a>
<button type="button" class="btn btn-primary btn-sm me-1"
onclick="document.querySelector('.table-empty-{%d i %}').style.display='none'">collapse
</button>
<button type="button" class="btn btn-secondary btn-sm me-1"
onclick="document.querySelector('.table-empty-{%d i %}').style.display='block'">expand
</button>
</h4>
<table id="table-empty-{%d i %}" class="table table-striped table-hover table-bordered table-sm table-empty-{%d i %}">
<thead>
<tr>
<th scope="col" style="width: 50%">Discovered Labels</th>
<th scope="col" style="width: 50%">Target Labels</th>
</tr>
</thead>
<tbody class="list-{%d i %}">
{% for _, status := range droppedKeyStatuses %}
{% for _, label := range status.originalLabels %}
{% if label.Value == jobName %}
<tr>
<td class="labels">
{%= formatLabel(status.originalLabels) %}
</td>
<td class="labels">
<span class="badge bg-danger">DROPPED</span>
</td>
</tr>
{% endif %}
{% endfor %}
{% endfor %}
</tbody>
</table>
</div>
{% endfor %}
{% endfunc %}

View file

@ -0,0 +1,279 @@
// Code generated by qtc from "service_discovery.qtpl". DO NOT EDIT.
// See https://github.com/valyala/quicktemplate for details.
//line lib/promscrape/service_discovery.qtpl:1
package promscrape
//line lib/promscrape/service_discovery.qtpl:1
import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
)
//line lib/promscrape/service_discovery.qtpl:5
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line lib/promscrape/service_discovery.qtpl:5
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line lib/promscrape/service_discovery.qtpl:5
func StreamServiceDiscovery(qw422016 *qt422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, droppedKeyStatuses []droppedKeyStatus) {
//line lib/promscrape/service_discovery.qtpl:5
qw422016.N().S(`
<div class="row mt-4">
<div class="col-12">
`)
//line lib/promscrape/service_discovery.qtpl:8
for i, js := range jts {
//line lib/promscrape/service_discovery.qtpl:8
qw422016.N().S(`
`)
//line lib/promscrape/service_discovery.qtpl:9
if showOnlyUnhealthy && js.upCount == js.targetsTotal {
//line lib/promscrape/service_discovery.qtpl:9
continue
//line lib/promscrape/service_discovery.qtpl:9
}
//line lib/promscrape/service_discovery.qtpl:9
qw422016.N().S(`
<h4>
<span class="me-2">`)
//line lib/promscrape/service_discovery.qtpl:11
qw422016.E().S(js.job)
//line lib/promscrape/service_discovery.qtpl:11
qw422016.N().S(` `)
//line lib/promscrape/service_discovery.qtpl:11
qw422016.N().S(`(`)
//line lib/promscrape/service_discovery.qtpl:11
qw422016.N().D(js.upCount)
//line lib/promscrape/service_discovery.qtpl:11
qw422016.N().S(`/`)
//line lib/promscrape/service_discovery.qtpl:11
qw422016.N().D(js.targetsTotal)
//line lib/promscrape/service_discovery.qtpl:11
qw422016.N().S(` `)
//line lib/promscrape/service_discovery.qtpl:11
qw422016.N().S(`up)</span>
<button type="button" class="btn btn-primary btn-sm me-1"
onclick="document.querySelector('.table-discovery-`)
//line lib/promscrape/service_discovery.qtpl:13
qw422016.N().D(i)
//line lib/promscrape/service_discovery.qtpl:13
qw422016.N().S(`').style.display='none'">collapse
</button>
<button type="button" class="btn btn-secondary btn-sm me-1"
onclick="document.querySelector('.table-discovery-`)
//line lib/promscrape/service_discovery.qtpl:16
qw422016.N().D(i)
//line lib/promscrape/service_discovery.qtpl:16
qw422016.N().S(`').style.display='block'">expand
</button>
</h4>
<div id="table-discovery-`)
//line lib/promscrape/service_discovery.qtpl:19
qw422016.N().D(i)
//line lib/promscrape/service_discovery.qtpl:19
qw422016.N().S(`" class="table-responsive table-discovery-`)
//line lib/promscrape/service_discovery.qtpl:19
qw422016.N().D(i)
//line lib/promscrape/service_discovery.qtpl:19
qw422016.N().S(`">
<table class="table table-striped table-hover table-bordered table-sm">
<thead>
<tr>
<th scope="col" style="width: 50%">Discovered Labels</th>
<th scope="col" style="width: 50%">Target Labels</th>
</tr>
</thead>
<tbody class="list-`)
//line lib/promscrape/service_discovery.qtpl:27
qw422016.N().D(i)
//line lib/promscrape/service_discovery.qtpl:27
qw422016.N().S(`">
`)
//line lib/promscrape/service_discovery.qtpl:28
for _, ts := range js.targetsStatus {
//line lib/promscrape/service_discovery.qtpl:28
qw422016.N().S(`
`)
//line lib/promscrape/service_discovery.qtpl:29
if showOnlyUnhealthy && ts.up {
//line lib/promscrape/service_discovery.qtpl:29
continue
//line lib/promscrape/service_discovery.qtpl:29
}
//line lib/promscrape/service_discovery.qtpl:29
qw422016.N().S(`
<tr `)
//line lib/promscrape/service_discovery.qtpl:30
if !ts.up {
//line lib/promscrape/service_discovery.qtpl:30
qw422016.N().S(` `)
//line lib/promscrape/service_discovery.qtpl:30
qw422016.N().S(`class="alert alert-danger" role="alert" `)
//line lib/promscrape/service_discovery.qtpl:30
}
//line lib/promscrape/service_discovery.qtpl:30
qw422016.N().S(`>
<td class="labels">
`)
//line lib/promscrape/service_discovery.qtpl:32
streamformatLabel(qw422016, ts.sw.Config.OriginalLabels)
//line lib/promscrape/service_discovery.qtpl:32
qw422016.N().S(`
</td>
<td class="labels">
`)
//line lib/promscrape/service_discovery.qtpl:35
streamformatLabel(qw422016, promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels))
//line lib/promscrape/service_discovery.qtpl:35
qw422016.N().S(`
</td>
</tr>
`)
//line lib/promscrape/service_discovery.qtpl:38
}
//line lib/promscrape/service_discovery.qtpl:38
qw422016.N().S(`
</tbody>
</table>
</div>
`)
//line lib/promscrape/service_discovery.qtpl:42
}
//line lib/promscrape/service_discovery.qtpl:42
qw422016.N().S(`
</div>
</div>
`)
//line lib/promscrape/service_discovery.qtpl:45
for i, jobName := range emptyJobs {
//line lib/promscrape/service_discovery.qtpl:45
qw422016.N().S(`
<div>
<h4>
<a>`)
//line lib/promscrape/service_discovery.qtpl:48
qw422016.E().S(jobName)
//line lib/promscrape/service_discovery.qtpl:48
qw422016.N().S(` (0/0 up)</a>
<button type="button" class="btn btn-primary btn-sm me-1"
onclick="document.querySelector('.table-empty-`)
//line lib/promscrape/service_discovery.qtpl:50
qw422016.N().D(i)
//line lib/promscrape/service_discovery.qtpl:50
qw422016.N().S(`').style.display='none'">collapse
</button>
<button type="button" class="btn btn-secondary btn-sm me-1"
onclick="document.querySelector('.table-empty-`)
//line lib/promscrape/service_discovery.qtpl:53
qw422016.N().D(i)
//line lib/promscrape/service_discovery.qtpl:53
qw422016.N().S(`').style.display='block'">expand
</button>
</h4>
<table id="table-empty-`)
//line lib/promscrape/service_discovery.qtpl:56
qw422016.N().D(i)
//line lib/promscrape/service_discovery.qtpl:56
qw422016.N().S(`" class="table table-striped table-hover table-bordered table-sm table-empty-`)
//line lib/promscrape/service_discovery.qtpl:56
qw422016.N().D(i)
//line lib/promscrape/service_discovery.qtpl:56
qw422016.N().S(`">
<thead>
<tr>
<th scope="col" style="width: 50%">Discovered Labels</th>
<th scope="col" style="width: 50%">Target Labels</th>
</tr>
</thead>
<tbody class="list-`)
//line lib/promscrape/service_discovery.qtpl:63
qw422016.N().D(i)
//line lib/promscrape/service_discovery.qtpl:63
qw422016.N().S(`">
`)
//line lib/promscrape/service_discovery.qtpl:64
for _, status := range droppedKeyStatuses {
//line lib/promscrape/service_discovery.qtpl:64
qw422016.N().S(`
`)
//line lib/promscrape/service_discovery.qtpl:65
for _, label := range status.originalLabels {
//line lib/promscrape/service_discovery.qtpl:65
qw422016.N().S(`
`)
//line lib/promscrape/service_discovery.qtpl:66
if label.Value == jobName {
//line lib/promscrape/service_discovery.qtpl:66
qw422016.N().S(`
<tr>
<td class="labels">
`)
//line lib/promscrape/service_discovery.qtpl:69
streamformatLabel(qw422016, status.originalLabels)
//line lib/promscrape/service_discovery.qtpl:69
qw422016.N().S(`
</td>
<td class="labels">
<span class="badge bg-danger">DROPPED</span>
</td>
</tr>
`)
//line lib/promscrape/service_discovery.qtpl:75
}
//line lib/promscrape/service_discovery.qtpl:75
qw422016.N().S(`
`)
//line lib/promscrape/service_discovery.qtpl:76
}
//line lib/promscrape/service_discovery.qtpl:76
qw422016.N().S(`
`)
//line lib/promscrape/service_discovery.qtpl:77
}
//line lib/promscrape/service_discovery.qtpl:77
qw422016.N().S(`
</tbody>
</table>
</div>
`)
//line lib/promscrape/service_discovery.qtpl:81
}
//line lib/promscrape/service_discovery.qtpl:81
qw422016.N().S(`
`)
//line lib/promscrape/service_discovery.qtpl:82
}
//line lib/promscrape/service_discovery.qtpl:82
func WriteServiceDiscovery(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, droppedKeyStatuses []droppedKeyStatus) {
//line lib/promscrape/service_discovery.qtpl:82
qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/service_discovery.qtpl:82
StreamServiceDiscovery(qw422016, jts, emptyJobs, showOnlyUnhealthy, droppedKeyStatuses)
//line lib/promscrape/service_discovery.qtpl:82
qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/service_discovery.qtpl:82
}
//line lib/promscrape/service_discovery.qtpl:82
func ServiceDiscovery(jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, droppedKeyStatuses []droppedKeyStatus) string {
//line lib/promscrape/service_discovery.qtpl:82
qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/service_discovery.qtpl:82
WriteServiceDiscovery(qb422016, jts, emptyJobs, showOnlyUnhealthy, droppedKeyStatuses)
//line lib/promscrape/service_discovery.qtpl:82
qs422016 := string(qb422016.B)
//line lib/promscrape/service_discovery.qtpl:82
qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/service_discovery.qtpl:82
return qs422016
//line lib/promscrape/service_discovery.qtpl:82
}

107
lib/promscrape/targets.qtpl Normal file
View file

@ -0,0 +1,107 @@
{% import (
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
) %}
{% func Targets(jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool) %}
<div class="row mt-4">
<div class="col-12">
{% for i, js := range jts %}
{% if showOnlyUnhealthy && js.upCount == js.targetsTotal %}{% continue %}{% endif %}
<div class="row mb-4">
<div class="col-12">
<h4>
<span class="me-2">{%s js.job %}{% space %}({%d js.upCount %}/{%d js.targetsTotal %}{% space %}up)</span>
<button type="button" class="btn btn-primary btn-sm me-1"
onclick="document.getElementById('table-{%d i %}').style.display='none'">collapse
</button>
<button type="button" class="btn btn-secondary btn-sm me-1"
onclick="document.getElementById('table-{%d i %}').style.display='block'">expand
</button>
</h4>
<div id="table-{%d i %}" class="table-responsive">
<table class="table table-striped table-hover table-bordered table-sm">
<thead>
<tr>
<th scope="col">Endpoint</th>
<th scope="col">State</th>
<th scope="col" title="scrape target labels">Labels</th>
<th scope="col" title="total scrapes">Scrapes</th>
<th scope="col" title="total scrape errors">Errors</th>
<th scope="col" title="the time of the last scrape">Last Scrape</th>
<th scope="col" title="the duration of the last scrape">Duration</th>
<th scope="col" title="the number of metrics scraped during the last scrape">Samples</th>
<th scope="col" title="error from the last scrape (if any)">Last error</th>
</tr>
</thead>
<tbody class="list-{%d i %}">
{% for _, ts := range js.targetsStatus %}
{% code
endpoint := ts.sw.Config.ScrapeURL
targetID := getTargetID(ts.sw)
lastScrapeTime := ts.getDurationFromLastScrape()
%}
{% if showOnlyUnhealthy && ts.up %}{% continue %}{% endif %}
<tr {% if !ts.up %}{%space%}class="alert alert-danger" role="alert" {% endif %}>
<td class="endpoint"><a href="{%s endpoint %}" target="_blank">{%s endpoint %}</a> (
<a href="target_response?id={%s targetID %}" target="_blank"
title="click to fetch target response on behalf of the scraper">response</a>
)
</td>
<td>
{% if ts.up %}
<span class="badge bg-success">UP</span>
{% else %}
<span class="badge bg-danger">DOWN</span>
{% endif %}
</td>
<td class="labels">
<div title="click to show original labels"
onclick="document.getElementById('original_labels_{%s targetID %}').style.display='block'">
{%= formatLabel(promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels)) %}
</div>
<div style="display:none" id="original_labels_{%s targetID %}">
{%= formatLabel(ts.sw.Config.OriginalLabels) %}
</div>
</td>
<td>{%d ts.scrapesTotal %}</td>
<td>{%d ts.scrapesFailed %}</td>
<td>
{% if lastScrapeTime < 365*24*time.Hour %}
{%f.3 lastScrapeTime.Seconds() %}s ago
{% else %}
none
{% endif %}
<td>{%d int(ts.scrapeDuration) %}ms</td>
<td>{%d ts.samplesScraped %}</td>
<td>{% if ts.err != nil %}{%s ts.err.Error() %}{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% for _, jobName := range emptyJobs %}
<div>
<h4><a>{%s jobName %} (0/0 up)</a></h4>
<table class="table table-striped table-hover table-bordered table-sm">
<thead>
<tr>
<th scope="col">Endpoint</th>
<th scope="col">State</th>
<th scope="col">Labels</th>
<th scope="col">Last Scrape</th>
<th scope="col">Scrape Duration</th>
<th scope="col">Samples Scraped</th>
<th scope="col">Error</th>
</tr>
</thead>
</table>
</div>
{% endfor %}
{% endfunc %}

View file

@ -0,0 +1,327 @@
// Code generated by qtc from "targets.qtpl". DO NOT EDIT.
// See https://github.com/valyala/quicktemplate for details.
//line lib/promscrape/targets.qtpl:1
package promscrape
//line lib/promscrape/targets.qtpl:1
import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
"time"
)
//line lib/promscrape/targets.qtpl:6
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line lib/promscrape/targets.qtpl:6
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line lib/promscrape/targets.qtpl:6
func StreamTargets(qw422016 *qt422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool) {
//line lib/promscrape/targets.qtpl:6
qw422016.N().S(`
<div class="row mt-4">
<div class="col-12">
`)
//line lib/promscrape/targets.qtpl:9
for i, js := range jts {
//line lib/promscrape/targets.qtpl:9
qw422016.N().S(`
`)
//line lib/promscrape/targets.qtpl:10
if showOnlyUnhealthy && js.upCount == js.targetsTotal {
//line lib/promscrape/targets.qtpl:10
continue
//line lib/promscrape/targets.qtpl:10
}
//line lib/promscrape/targets.qtpl:10
qw422016.N().S(`
<div class="row mb-4">
<div class="col-12">
<h4>
<span class="me-2">`)
//line lib/promscrape/targets.qtpl:14
qw422016.E().S(js.job)
//line lib/promscrape/targets.qtpl:14
qw422016.N().S(` `)
//line lib/promscrape/targets.qtpl:14
qw422016.N().S(`(`)
//line lib/promscrape/targets.qtpl:14
qw422016.N().D(js.upCount)
//line lib/promscrape/targets.qtpl:14
qw422016.N().S(`/`)
//line lib/promscrape/targets.qtpl:14
qw422016.N().D(js.targetsTotal)
//line lib/promscrape/targets.qtpl:14
qw422016.N().S(` `)
//line lib/promscrape/targets.qtpl:14
qw422016.N().S(`up)</span>
<button type="button" class="btn btn-primary btn-sm me-1"
onclick="document.getElementById('table-`)
//line lib/promscrape/targets.qtpl:16
qw422016.N().D(i)
//line lib/promscrape/targets.qtpl:16
qw422016.N().S(`').style.display='none'">collapse
</button>
<button type="button" class="btn btn-secondary btn-sm me-1"
onclick="document.getElementById('table-`)
//line lib/promscrape/targets.qtpl:19
qw422016.N().D(i)
//line lib/promscrape/targets.qtpl:19
qw422016.N().S(`').style.display='block'">expand
</button>
</h4>
<div id="table-`)
//line lib/promscrape/targets.qtpl:22
qw422016.N().D(i)
//line lib/promscrape/targets.qtpl:22
qw422016.N().S(`" class="table-responsive">
<table class="table table-striped table-hover table-bordered table-sm">
<thead>
<tr>
<th scope="col">Endpoint</th>
<th scope="col">State</th>
<th scope="col" title="scrape target labels">Labels</th>
<th scope="col" title="total scrapes">Scrapes</th>
<th scope="col" title="total scrape errors">Errors</th>
<th scope="col" title="the time of the last scrape">Last Scrape</th>
<th scope="col" title="the duration of the last scrape">Duration</th>
<th scope="col" title="the number of metrics scraped during the last scrape">Samples</th>
<th scope="col" title="error from the last scrape (if any)">Last error</th>
</tr>
</thead>
<tbody class="list-`)
//line lib/promscrape/targets.qtpl:37
qw422016.N().D(i)
//line lib/promscrape/targets.qtpl:37
qw422016.N().S(`">
`)
//line lib/promscrape/targets.qtpl:38
for _, ts := range js.targetsStatus {
//line lib/promscrape/targets.qtpl:38
qw422016.N().S(`
`)
//line lib/promscrape/targets.qtpl:40
endpoint := ts.sw.Config.ScrapeURL
targetID := getTargetID(ts.sw)
lastScrapeTime := ts.getDurationFromLastScrape()
//line lib/promscrape/targets.qtpl:43
qw422016.N().S(`
`)
//line lib/promscrape/targets.qtpl:44
if showOnlyUnhealthy && ts.up {
//line lib/promscrape/targets.qtpl:44
continue
//line lib/promscrape/targets.qtpl:44
}
//line lib/promscrape/targets.qtpl:44
qw422016.N().S(`
<tr `)
//line lib/promscrape/targets.qtpl:45
if !ts.up {
//line lib/promscrape/targets.qtpl:45
qw422016.N().S(` `)
//line lib/promscrape/targets.qtpl:45
qw422016.N().S(`class="alert alert-danger" role="alert" `)
//line lib/promscrape/targets.qtpl:45
}
//line lib/promscrape/targets.qtpl:45
qw422016.N().S(`>
<td class="endpoint"><a href="`)
//line lib/promscrape/targets.qtpl:46
qw422016.E().S(endpoint)
//line lib/promscrape/targets.qtpl:46
qw422016.N().S(`" target="_blank">`)
//line lib/promscrape/targets.qtpl:46
qw422016.E().S(endpoint)
//line lib/promscrape/targets.qtpl:46
qw422016.N().S(`</a> (
<a href="target_response?id=`)
//line lib/promscrape/targets.qtpl:47
qw422016.E().S(targetID)
//line lib/promscrape/targets.qtpl:47
qw422016.N().S(`" target="_blank"
title="click to fetch target response on behalf of the scraper">response</a>
)
</td>
<td>
`)
//line lib/promscrape/targets.qtpl:52
if ts.up {
//line lib/promscrape/targets.qtpl:52
qw422016.N().S(`
<span class="badge bg-success">UP</span>
`)
//line lib/promscrape/targets.qtpl:54
} else {
//line lib/promscrape/targets.qtpl:54
qw422016.N().S(`
<span class="badge bg-danger">DOWN</span>
`)
//line lib/promscrape/targets.qtpl:56
}
//line lib/promscrape/targets.qtpl:56
qw422016.N().S(`
</td>
<td class="labels">
<div title="click to show original labels"
onclick="document.getElementById('original_labels_`)
//line lib/promscrape/targets.qtpl:60
qw422016.E().S(targetID)
//line lib/promscrape/targets.qtpl:60
qw422016.N().S(`').style.display='block'">
`)
//line lib/promscrape/targets.qtpl:61
streamformatLabel(qw422016, promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels))
//line lib/promscrape/targets.qtpl:61
qw422016.N().S(`
</div>
<div style="display:none" id="original_labels_`)
//line lib/promscrape/targets.qtpl:63
qw422016.E().S(targetID)
//line lib/promscrape/targets.qtpl:63
qw422016.N().S(`">
`)
//line lib/promscrape/targets.qtpl:64
streamformatLabel(qw422016, ts.sw.Config.OriginalLabels)
//line lib/promscrape/targets.qtpl:64
qw422016.N().S(`
</div>
</td>
<td>`)
//line lib/promscrape/targets.qtpl:67
qw422016.N().D(ts.scrapesTotal)
//line lib/promscrape/targets.qtpl:67
qw422016.N().S(`</td>
<td>`)
//line lib/promscrape/targets.qtpl:68
qw422016.N().D(ts.scrapesFailed)
//line lib/promscrape/targets.qtpl:68
qw422016.N().S(`</td>
<td>
`)
//line lib/promscrape/targets.qtpl:70
if lastScrapeTime < 365*24*time.Hour {
//line lib/promscrape/targets.qtpl:70
qw422016.N().S(`
`)
//line lib/promscrape/targets.qtpl:71
qw422016.N().FPrec(lastScrapeTime.Seconds(), 3)
//line lib/promscrape/targets.qtpl:71
qw422016.N().S(`s ago
`)
//line lib/promscrape/targets.qtpl:72
} else {
//line lib/promscrape/targets.qtpl:72
qw422016.N().S(`
none
`)
//line lib/promscrape/targets.qtpl:74
}
//line lib/promscrape/targets.qtpl:74
qw422016.N().S(`
<td>`)
//line lib/promscrape/targets.qtpl:75
qw422016.N().D(int(ts.scrapeDuration))
//line lib/promscrape/targets.qtpl:75
qw422016.N().S(`ms</td>
<td>`)
//line lib/promscrape/targets.qtpl:76
qw422016.N().D(ts.samplesScraped)
//line lib/promscrape/targets.qtpl:76
qw422016.N().S(`</td>
<td>`)
//line lib/promscrape/targets.qtpl:77
if ts.err != nil {
//line lib/promscrape/targets.qtpl:77
qw422016.E().S(ts.err.Error())
//line lib/promscrape/targets.qtpl:77
}
//line lib/promscrape/targets.qtpl:77
qw422016.N().S(`</td>
</tr>
`)
//line lib/promscrape/targets.qtpl:79
}
//line lib/promscrape/targets.qtpl:79
qw422016.N().S(`
</tbody>
</table>
</div>
</div>
</div>
`)
//line lib/promscrape/targets.qtpl:85
}
//line lib/promscrape/targets.qtpl:85
qw422016.N().S(`
</div>
</div>
`)
//line lib/promscrape/targets.qtpl:89
for _, jobName := range emptyJobs {
//line lib/promscrape/targets.qtpl:89
qw422016.N().S(`
<div>
<h4><a>`)
//line lib/promscrape/targets.qtpl:91
qw422016.E().S(jobName)
//line lib/promscrape/targets.qtpl:91
qw422016.N().S(` (0/0 up)</a></h4>
<table class="table table-striped table-hover table-bordered table-sm">
<thead>
<tr>
<th scope="col">Endpoint</th>
<th scope="col">State</th>
<th scope="col">Labels</th>
<th scope="col">Last Scrape</th>
<th scope="col">Scrape Duration</th>
<th scope="col">Samples Scraped</th>
<th scope="col">Error</th>
</tr>
</thead>
</table>
</div>
`)
//line lib/promscrape/targets.qtpl:106
}
//line lib/promscrape/targets.qtpl:106
qw422016.N().S(`
`)
//line lib/promscrape/targets.qtpl:107
}
//line lib/promscrape/targets.qtpl:107
func WriteTargets(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool) {
//line lib/promscrape/targets.qtpl:107
qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targets.qtpl:107
StreamTargets(qw422016, jts, emptyJobs, showOnlyUnhealthy)
//line lib/promscrape/targets.qtpl:107
qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targets.qtpl:107
}
//line lib/promscrape/targets.qtpl:107
func Targets(jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool) string {
//line lib/promscrape/targets.qtpl:107
qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targets.qtpl:107
WriteTargets(qb422016, jts, emptyJobs, showOnlyUnhealthy)
//line lib/promscrape/targets.qtpl:107
qs422016 := string(qb422016.B)
//line lib/promscrape/targets.qtpl:107
qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targets.qtpl:107
return qs422016
//line lib/promscrape/targets.qtpl:107
}

View file

@ -16,7 +16,7 @@ import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime" "github.com/VictoriaMetrics/VictoriaMetrics/lib/fasttime"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal" "github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel" "github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
xxhash "github.com/cespare/xxhash/v2" "github.com/cespare/xxhash/v2"
) )
var maxDroppedTargets = flag.Int("promscrape.maxDroppedTargets", 1000, "The maximum number of droppedTargets to show at /api/v1/targets page. "+ var maxDroppedTargets = flag.Int("promscrape.maxDroppedTargets", 1000, "The maximum number of droppedTargets to show at /api/v1/targets page. "+
@ -49,12 +49,20 @@ func WriteHumanReadableTargetsStatus(w http.ResponseWriter, r *http.Request) {
showOnlyUnhealthy, _ := strconv.ParseBool(r.FormValue("show_only_unhealthy")) showOnlyUnhealthy, _ := strconv.ParseBool(r.FormValue("show_only_unhealthy"))
endpointSearch := strings.TrimSpace(r.FormValue("endpoint_search")) endpointSearch := strings.TrimSpace(r.FormValue("endpoint_search"))
labelSearch := strings.TrimSpace(r.FormValue("label_search")) labelSearch := strings.TrimSpace(r.FormValue("label_search"))
activeTab := strings.TrimSpace(r.FormValue("active_tab"))
filter := requestFilter{
showOriginalLabels: showOriginalLabels,
showOnlyUnhealthy: showOnlyUnhealthy,
endpointSearch: endpointSearch,
labelSearch: labelSearch,
activeTab: activeTab,
}
if accept := r.Header.Get("Accept"); strings.Contains(accept, "text/html") { if accept := r.Header.Get("Accept"); strings.Contains(accept, "text/html") {
w.Header().Set("Content-Type", "text/html; charset=utf-8") w.Header().Set("Content-Type", "text/html; charset=utf-8")
tsmGlobal.WriteTargetsHTML(w, showOnlyUnhealthy, endpointSearch, labelSearch) tsmGlobal.WriteTargetsHTML(w, filter)
} else { } else {
w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.Header().Set("Content-Type", "text/plain; charset=utf-8")
tsmGlobal.WriteTargetsPlain(w, showOriginalLabels, showOnlyUnhealthy, endpointSearch, labelSearch) tsmGlobal.WriteTargetsPlain(w, filter)
} }
} }
@ -167,17 +175,17 @@ func (tsm *targetStatusMap) StatusByGroup(group string, up bool) int {
return count return count
} }
// WriteActiveTargetsJSON writes `activeTargets` contents to w according to https://prometheus.io/docs/prometheus/latest/querying/api/#targets type activeKeyStatus struct {
func (tsm *targetStatusMap) WriteActiveTargetsJSON(w io.Writer) { key string
st targetStatus
}
func (tsm *targetStatusMap) getActiveKeyStatuses() []activeKeyStatus {
tsm.mu.Lock() tsm.mu.Lock()
type keyStatus struct { kss := make([]activeKeyStatus, 0, len(tsm.m))
key string
st targetStatus
}
kss := make([]keyStatus, 0, len(tsm.m))
for sw, st := range tsm.m { for sw, st := range tsm.m {
key := promLabelsString(sw.Config.OriginalLabels) key := promLabelsString(sw.Config.OriginalLabels)
kss = append(kss, keyStatus{ kss = append(kss, activeKeyStatus{
key: key, key: key,
st: *st, st: *st,
}) })
@ -187,6 +195,12 @@ func (tsm *targetStatusMap) WriteActiveTargetsJSON(w io.Writer) {
sort.Slice(kss, func(i, j int) bool { sort.Slice(kss, func(i, j int) bool {
return kss[i].key < kss[j].key return kss[i].key < kss[j].key
}) })
return kss
}
// WriteActiveTargetsJSON writes `activeTargets` contents to w according to https://prometheus.io/docs/prometheus/latest/querying/api/#targets
func (tsm *targetStatusMap) WriteActiveTargetsJSON(w io.Writer) {
kss := tsm.getActiveKeyStatuses()
fmt.Fprintf(w, `[`) fmt.Fprintf(w, `[`)
for i, ks := range kss { for i, ks := range kss {
st := ks.st st := ks.st
@ -244,15 +258,38 @@ func (st *targetStatus) getDurationFromLastScrape() time.Duration {
return time.Since(time.Unix(st.scrapeTime/1000, (st.scrapeTime%1000)*1e6)) return time.Since(time.Unix(st.scrapeTime/1000, (st.scrapeTime%1000)*1e6))
} }
type droppedTargets struct { type (
mu sync.Mutex droppedTargets struct {
m map[uint64]droppedTarget mu sync.Mutex
lastCleanupTime uint64 m map[uint64]droppedTarget
} lastCleanupTime uint64
}
droppedTarget struct {
originalLabels []prompbmarshal.Label
deadline uint64
}
droppedKeyStatus struct {
key string
originalLabels []prompbmarshal.Label
}
)
type droppedTarget struct { func (dt *droppedTargets) getDroppedKeyStatuses() []droppedKeyStatus {
originalLabels []prompbmarshal.Label dt.mu.Lock()
deadline uint64 kss := make([]droppedKeyStatus, 0, len(dt.m))
for _, v := range dt.m {
key := promLabelsString(v.originalLabels)
kss = append(kss, droppedKeyStatus{
key: key,
originalLabels: v.originalLabels,
})
}
dt.mu.Unlock()
sort.Slice(kss, func(i, j int) bool {
return kss[i].key < kss[j].key
})
return kss
} }
func (dt *droppedTargets) Register(originalLabels []prompbmarshal.Label) { func (dt *droppedTargets) Register(originalLabels []prompbmarshal.Label) {
@ -300,24 +337,7 @@ var xxhashPool = &sync.Pool{
// WriteDroppedTargetsJSON writes `droppedTargets` contents to w according to https://prometheus.io/docs/prometheus/latest/querying/api/#targets // WriteDroppedTargetsJSON writes `droppedTargets` contents to w according to https://prometheus.io/docs/prometheus/latest/querying/api/#targets
func (dt *droppedTargets) WriteDroppedTargetsJSON(w io.Writer) { func (dt *droppedTargets) WriteDroppedTargetsJSON(w io.Writer) {
dt.mu.Lock() kss := dt.getDroppedKeyStatuses()
type keyStatus struct {
key string
originalLabels []prompbmarshal.Label
}
kss := make([]keyStatus, 0, len(dt.m))
for _, v := range dt.m {
key := promLabelsString(v.originalLabels)
kss = append(kss, keyStatus{
key: key,
originalLabels: v.originalLabels,
})
}
dt.mu.Unlock()
sort.Slice(kss, func(i, j int) bool {
return kss[i].key < kss[j].key
})
fmt.Fprintf(w, `[`) fmt.Fprintf(w, `[`)
for i, ks := range kss { for i, ks := range kss {
fmt.Fprintf(w, `{"discoveredLabels":`) fmt.Fprintf(w, `{"discoveredLabels":`)
@ -465,16 +485,46 @@ func getEmptyJobs(jts []jobTargetsStatuses, jobNames []string) []string {
return emptyJobs return emptyJobs
} }
type (
requestFilter struct {
showOriginalLabels bool
showOnlyUnhealthy bool
endpointSearch string
labelSearch string
activeTab string
}
targetsStatuses struct {
jobTargetsStatuses []jobTargetsStatuses
droppedKeyStatuses []droppedKeyStatus
emptyJobs []string
err error
}
scrapeTargets struct {
requestFilter
targetsStatuses
}
)
// WriteTargetsHTML writes targets status grouped by job into writer w in html table, // WriteTargetsHTML writes targets status grouped by job into writer w in html table,
// accepts filter to show only unhealthy targets. // accepts filter to show only unhealthy targets.
func (tsm *targetStatusMap) WriteTargetsHTML(w io.Writer, showOnlyUnhealthy bool, endpointSearch, labelSearch string) { func (tsm *targetStatusMap) WriteTargetsHTML(w io.Writer, filter requestFilter) {
jss, emptyJobs, err := tsm.getTargetsStatusByJob(endpointSearch, labelSearch) droppedKeyStatuses := droppedTargetsMap.getDroppedKeyStatuses()
WriteTargetsResponseHTML(w, jss, emptyJobs, showOnlyUnhealthy, endpointSearch, labelSearch, err) jss, emptyJobs, err := tsm.getTargetsStatusByJob(filter.endpointSearch, filter.labelSearch)
scrapeTargets := scrapeTargets{
requestFilter: filter,
targetsStatuses: targetsStatuses{
jobTargetsStatuses: jss,
droppedKeyStatuses: droppedKeyStatuses,
emptyJobs: emptyJobs,
err: err,
},
}
WriteTargetsResponseHTML(w, scrapeTargets)
} }
// WriteTargetsPlain writes targets grouped by job into writer w in plain text, // WriteTargetsPlain writes targets grouped by job into writer w in plain text,
// accept filter to show original labels. // accept filter to show original labels.
func (tsm *targetStatusMap) WriteTargetsPlain(w io.Writer, showOriginalLabels, showOnlyUnhealthy bool, endpointSearch, labelSearch string) { func (tsm *targetStatusMap) WriteTargetsPlain(w io.Writer, filter requestFilter) {
jss, emptyJobs, err := tsm.getTargetsStatusByJob(endpointSearch, labelSearch) jss, emptyJobs, err := tsm.getTargetsStatusByJob(filter.endpointSearch, filter.labelSearch)
WriteTargetsResponsePlain(w, jss, emptyJobs, showOriginalLabels, showOnlyUnhealthy, err) WriteTargetsResponsePlain(w, jss, emptyJobs, filter.showOriginalLabels, filter.showOnlyUnhealthy, err)
} }

View file

@ -1,6 +1,5 @@
{% import ( {% import (
"net/url" "net/url"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal" "github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel" "github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
) %} ) %}
@ -42,7 +41,14 @@ job={%q= jobName %} (0/0 up)
{% endfunc %} {% endfunc %}
{% func TargetsResponseHTML(jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, endpointSearch, labelSearch string, err error) %} {% func TargetsResponseHTML(scrapeTargets scrapeTargets) %}
{% code
targetsStatuses := scrapeTargets.targetsStatuses
filter := scrapeTargets.requestFilter
if filter.activeTab == "" {
filter.activeTab="targets-tab"
}
%}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -52,21 +58,23 @@ job={%q= jobName %} (0/0 up)
<title>Scrape targets</title> <title>Scrape targets</title>
<script> <script>
function collapse_all() { function collapse_all() {
for (var i = 0; i < {%d len(jts) %}; i++) { for (var i = 0; i <= {%d len(targetsStatuses.jobTargetsStatuses) %}; i++) {
let el = document.getElementById("table-" + i); ["table-"+i, "table-discovery-"+i, "table-empty-"+i].forEach((id) => {
if (!el) { let el = document.getElementById(id);
continue; if (el) {
} el.style.display = 'none';
el.style.display = 'none'; }
})
} }
} }
function expand_all() { function expand_all() {
for (var i = 0; i < {%d len(jts) %}; i++) { for (var i = 0; i <= {%d len(targetsStatuses.jobTargetsStatuses) %}; i++) {
let el = document.getElementById("table-" + i); ["table-"+i, "table-discovery-"+i, "table-empty-"+i].forEach((id) => {
if (!el) { let el = document.getElementById(id);
continue; if (el) {
} el.style.display = 'block';
el.style.display = 'block'; }
});
} }
} }
</script> </script>
@ -81,8 +89,8 @@ function expand_all() {
</div> </div>
</div> </div>
<div class="container-fluid"> <div class="container-fluid">
{% if err != nil %} {% if targetsStatuses.err != nil %}
{%= errorNotification(err) %} {%= errorNotification(targetsStatuses.err) %}
{% endif %} {% endif %}
<div class="row"> <div class="row">
<main class="col-12"> <main class="col-12">
@ -90,19 +98,21 @@ function expand_all() {
<hr /> <hr />
<div class="row g-3 align-items-center mb-3"> <div class="row g-3 align-items-center mb-3">
<div class="col-auto"> <div class="col-auto">
<button type="button" class="btn{% space %}{% if !showOnlyUnhealthy %}btn-secondary{% else %}btn-success{% endif %}" onclick="location.href='?{%= queryArgs(map[string]string{ <button id="all-btn" type="button" class="btn{% space %}{% if !filter.showOnlyUnhealthy %}btn-secondary{% else %}btn-success{% endif %}" onclick="location.href='?{%= queryArgs(map[string]string{
"show_only_unhealthy": "false", "show_only_unhealthy": "false",
"endpoint_search": endpointSearch, "endpoint_search": filter.endpointSearch,
"label_search": labelSearch, "label_search": filter.labelSearch,
"active_tab": filter.activeTab,
}) %}'"> }) %}'">
All All
</button> </button>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<button type="button" class="btn{% space %}{% if showOnlyUnhealthy %}btn-secondary{% else %}btn-danger{% endif %}" onclick="location.href='?{%= queryArgs(map[string]string{ <button id="unhealthy-btn" type="button" class="btn{% space %}{% if filter.showOnlyUnhealthy %}btn-secondary{% else %}btn-danger{% endif %}" onclick="location.href='?{%= queryArgs(map[string]string{
"show_only_unhealthy": "true", "show_only_unhealthy": "true",
"endpoint_search": endpointSearch, "endpoint_search": filter.endpointSearch,
"label_search": labelSearch, "label_search": filter.labelSearch,
"active_tab": filter.activeTab,
}) %}'"> }) %}'">
Unhealthy Unhealthy
</button> </button>
@ -118,7 +128,7 @@ function expand_all() {
</button> </button>
</div> </div>
<div class="col-auto"> <div class="col-auto">
{% if endpointSearch == "" && labelSearch == "" %} {% if filter.endpointSearch == "" && filter.labelSearch == "" %}
<button type="button" class="btn btn-success" onclick="document.getElementById('filters').style.display='block'"> <button type="button" class="btn btn-success" onclick="document.getElementById('filters').style.display='block'">
Filter targets Filter targets
</button> </button>
@ -129,126 +139,77 @@ function expand_all() {
{% endif %} {% endif %}
</div> </div>
</div> </div>
<div id="filters" {% if endpointSearch == "" && labelSearch == "" %}style="display:none"{% endif %}> <div id="filters" {% if filter.endpointSearch == "" && filter.labelSearch == "" %}style="display:none"{% endif %}>
<form class="form-horizontal"> <form class="form-horizontal">
<div class="form-group mb-3"> <div class="form-group mb-3">
<label for="endpoint_search" class="col-sm-10 control-label">Endpoint filter (<a target="_blank" href="https://github.com/google/re2/wiki/Syntax">Regexp</a> is accepted)</label> <label for="endpoint_search" class="col-sm-10 control-label">Endpoint filter (<a target="_blank" href="https://github.com/google/re2/wiki/Syntax">Regexp</a> is accepted)</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" id="endpoint_search" name="endpoint_search" <input type="text" id="endpoint_search" name="endpoint_search"
placeholder="For example, 127.0.0.1" class="form-control" value="{%s endpointSearch %}"/> placeholder="For example, 127.0.0.1" class="form-control" value="{%s filter.endpointSearch %}"/>
</div> </div>
</div> </div>
<div class="form-group mb-3"> <div class="form-group mb-3">
<label for="label_search" class="col-sm-10 control-label">Labels filter (<a target="_blank" href="https://prometheus.io/docs/prometheus/latest/querying/basics/#time-series-selectors">Arbitrary time series selectors</a> are accepted)</label> <label for="label_search" class="col-sm-10 control-label">Labels filter (<a target="_blank" href="https://prometheus.io/docs/prometheus/latest/querying/basics/#time-series-selectors">Arbitrary time series selectors</a> are accepted)</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" id="label_search" name="label_search" <input type="text" id="label_search" name="label_search"
placeholder="For example, {instance=~'.+:9100'}" class="form-control" value="{%s labelSearch %}"/> placeholder="For example, {instance=~'.+:9100'}" class="form-control" value="{%s filter.labelSearch %}"/>
</div> </div>
</div> </div>
<input type="hidden" name="show_only_unhealthy" value="{%v showOnlyUnhealthy %}"/> <input type="hidden" name="show_only_unhealthy" value="{%v filter.showOnlyUnhealthy %}"/>
<input id="tab_input" type="hidden" name="active_tab" value="{%s filter.activeTab %}" />
<button type="submit" class="btn btn-success mb-3">Submit</button> <button type="submit" class="btn btn-success mb-3">Submit</button>
</form> </form>
</div> </div>
<hr /> <hr />
<div class="row"> <ul class="nav nav-tabs" id="myTab" role="tablist">
<div class="col-12"> <li class="nav-item" role="presentation">
{% for i, js := range jts %} <button id="targets-tab" class="nav-link {%if filter.activeTab=="targets-tab"%} {% space %}active {%endif%}" data-bs-toggle="tab" data-bs-target="#targets" type="button" role="tab" aria-controls="home" aria-selected="true">Targets</button>
{% if showOnlyUnhealthy && js.upCount == js.targetsTotal %}{% continue %}{% endif %} </li>
<div class="row mb-4"> <li class="nav-item" role="presentation">
<div class="col-12"> <button id="discovery-tab" class="nav-link {%if filter.activeTab=="discovery-tab"%} {% space %}active {%endif%}" data-bs-toggle="tab" data-bs-target="#discovery" type="button" role="tab" aria-controls="profile" aria-selected="false">Service Discovery</button>
<h4> </li>
<span class="me-2">{%s js.job %}{% space %}({%d js.upCount %}/{%d js.targetsTotal %}{% space %}up)</span> </ul>
<button type="button" class="btn btn-primary btn-sm me-1" <div class="tab-content">
onclick="document.getElementById('table-{%d i %}').style.display='none'">collapse <div id="targets" class="tab-pane {%if filter.activeTab=="targets-tab"%} {% space %}active{%endif%}" role="tabpanel" aria-labelledby="targets-tab">
</button> {%= Targets(targetsStatuses.jobTargetsStatuses, targetsStatuses.emptyJobs, filter.showOnlyUnhealthy) %}
<button type="button" class="btn btn-secondary btn-sm me-1" </div>
onclick="document.getElementById('table-{%d i %}').style.display='block'">expand <div id="discovery" class="tab-pane {%if filter.activeTab=="discovery-tab"%} {% space %}active{%endif%}" role="tabpanel" aria-labelledby="profile-tab">
</button> {%= ServiceDiscovery(targetsStatuses.jobTargetsStatuses, targetsStatuses.emptyJobs, filter.showOnlyUnhealthy, targetsStatuses.droppedKeyStatuses) %}
</h4>
<div id="table-{%d i %}" class="table-responsive">
<table class="table table-striped table-hover table-bordered table-sm">
<thead>
<tr>
<th scope="col">Endpoint</th>
<th scope="col">State</th>
<th scope="col" title="scrape target labels">Labels</th>
<th scope="col" title="total scrapes">Scrapes</th>
<th scope="col" title="total scrape errors">Errors</th>
<th scope="col" title="the time of the last scrape">Last Scrape</th>
<th scope="col" title="the duration of the last scrape">Duration</th>
<th scope="col" title="the number of metrics scraped during the last scrape">Samples</th>
<th scope="col" title="error from the last scrape (if any)">Last error</th>
</tr>
</thead>
<tbody class="list-{%d i %}">
{% for _, ts := range js.targetsStatus %}
{% code
endpoint := ts.sw.Config.ScrapeURL
targetID := getTargetID(ts.sw)
lastScrapeTime := ts.getDurationFromLastScrape()
%}
{% if showOnlyUnhealthy && ts.up %}{% continue %}{% endif %}
<tr {% if !ts.up %}{%space%}class="alert alert-danger" role="alert" {% endif %}>
<td class="endpoint"><a href="{%s endpoint %}" target="_blank">{%s endpoint %}</a> (
<a href="target_response?id={%s targetID %}" target="_blank"
title="click to fetch target response on behalf of the scraper">response</a>
)
</td>
<td>{% if ts.up %}UP{% else %}DOWN{% endif %}</td>
<td class="labels">
<div title="click to show original labels"
onclick="document.getElementById('original_labels_{%s targetID %}').style.display='block'">
{%= formatLabel(promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels)) %}
</div>
<div style="display:none" id="original_labels_{%s targetID %}">
{%= formatLabel(ts.sw.Config.OriginalLabels) %}
</div>
</td>
<td>{%d ts.scrapesTotal %}</td>
<td>{%d ts.scrapesFailed %}</td>
<td>
{% if lastScrapeTime < 365*24*time.Hour %}
{%f.3 lastScrapeTime.Seconds() %}s ago
{% else %}
none
{% endif %}
<td>{%d int(ts.scrapeDuration) %}ms</td>
<td>{%d ts.samplesScraped %}</td>
<td>{% if ts.err != nil %}{%s ts.err.Error() %}{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endfor %}
</div> </div>
</div> </div>
{% for _, jobName := range emptyJobs %}
<div>
<h4>
<a>{%s jobName %} (0/0 up)</a>
</h4>
<table class="table table-striped table-hover table-bordered table-sm">
<thead>
<tr>
<th scope="col">Endpoint</th>
<th scope="col">State</th>
<th scope="col">Labels</th>
<th scope="col">Last Scrape</th>
<th scope="col">Scrape Duration</th>
<th scope="col">Samples Scraped</th>
<th scope="col">Error</th>
</tr>
</thead>
</table>
</div>
{% endfor %}
</main> </main>
</div> </div>
</div> </div>
<script src="static/js/jquery-3.6.0.min.js" type="text/javascript"></script>
<script src="static/js/bootstrap.bundle.min.js" type="text/javascript"></script>
<script>
(function(){
const navBtns = document.querySelectorAll(".nav-link");
const tabInput = document.getElementById("tab_input");
const unhealthyBtn = document.getElementById("unhealthy-btn");
const allBtn = document.getElementById("all-btn");
navBtns.forEach((btn) => {
if (btn) {
btn.addEventListener("click", (e) => {
if (window.history.replaceState) {
var url = new URL(window.location.href);
url.searchParams.set("active_tab", e.target.id);
tabInput.value = e.target.id;
unhealthyBtn.onclick = () => {
url.searchParams.set("show_only_unhealthy", "true");
window.location.href=url;
};
allBtn.onclick = () => {
url.searchParams.set("show_only_unhealthy", "false");
window.location.href=url;
};
window.history.replaceState({}, "", url);
}
});
}
})
})()
</script>
</body> </body>
</html> </html>
{% endfunc %} {% endfunc %}

View file

@ -9,625 +9,520 @@ import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal" "github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel" "github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
"net/url" "net/url"
"time"
) )
//line lib/promscrape/targetstatus.qtpl:10 //line lib/promscrape/targetstatus.qtpl:9
import ( import (
qtio422016 "io" qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate" qt422016 "github.com/valyala/quicktemplate"
) )
//line lib/promscrape/targetstatus.qtpl:10 //line lib/promscrape/targetstatus.qtpl:9
var ( var (
_ = qtio422016.Copy _ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer _ = qt422016.AcquireByteBuffer
) )
//line lib/promscrape/targetstatus.qtpl:10 //line lib/promscrape/targetstatus.qtpl:9
func StreamTargetsResponsePlain(qw422016 *qt422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels, showOnlyUnhealthy bool, err error) { func StreamTargetsResponsePlain(qw422016 *qt422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels, showOnlyUnhealthy bool, err error) {
//line lib/promscrape/targetstatus.qtpl:12 //line lib/promscrape/targetstatus.qtpl:11
if err != nil { if err != nil {
//line lib/promscrape/targetstatus.qtpl:13 //line lib/promscrape/targetstatus.qtpl:12
qw422016.N().S(err.Error()) qw422016.N().S(err.Error())
//line lib/promscrape/targetstatus.qtpl:14 //line lib/promscrape/targetstatus.qtpl:13
return return
//line lib/promscrape/targetstatus.qtpl:15 //line lib/promscrape/targetstatus.qtpl:14
} }
//line lib/promscrape/targetstatus.qtpl:17 //line lib/promscrape/targetstatus.qtpl:16
for _, js := range jts { for _, js := range jts {
//line lib/promscrape/targetstatus.qtpl:18 //line lib/promscrape/targetstatus.qtpl:17
if showOnlyUnhealthy && js.upCount == js.targetsTotal { if showOnlyUnhealthy && js.upCount == js.targetsTotal {
//line lib/promscrape/targetstatus.qtpl:18 //line lib/promscrape/targetstatus.qtpl:17
continue continue
//line lib/promscrape/targetstatus.qtpl:18 //line lib/promscrape/targetstatus.qtpl:17
} }
//line lib/promscrape/targetstatus.qtpl:18 //line lib/promscrape/targetstatus.qtpl:17
qw422016.N().S(`job=`) qw422016.N().S(`job=`)
//line lib/promscrape/targetstatus.qtpl:19 //line lib/promscrape/targetstatus.qtpl:18
qw422016.N().Q(js.job) qw422016.N().Q(js.job)
//line lib/promscrape/targetstatus.qtpl:19 //line lib/promscrape/targetstatus.qtpl:18
qw422016.N().S(`(`) qw422016.N().S(`(`)
//line lib/promscrape/targetstatus.qtpl:19 //line lib/promscrape/targetstatus.qtpl:18
qw422016.N().D(js.upCount) qw422016.N().D(js.upCount)
//line lib/promscrape/targetstatus.qtpl:19 //line lib/promscrape/targetstatus.qtpl:18
qw422016.N().S(`/`) qw422016.N().S(`/`)
//line lib/promscrape/targetstatus.qtpl:19 //line lib/promscrape/targetstatus.qtpl:18
qw422016.N().D(js.targetsTotal) qw422016.N().D(js.targetsTotal)
//line lib/promscrape/targetstatus.qtpl:19 //line lib/promscrape/targetstatus.qtpl:18
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:19 //line lib/promscrape/targetstatus.qtpl:18
qw422016.N().S(`up)`) qw422016.N().S(`up)`)
//line lib/promscrape/targetstatus.qtpl:20 //line lib/promscrape/targetstatus.qtpl:19
qw422016.N().S(` qw422016.N().S(`
`) `)
//line lib/promscrape/targetstatus.qtpl:21 //line lib/promscrape/targetstatus.qtpl:20
for _, ts := range js.targetsStatus { for _, ts := range js.targetsStatus {
//line lib/promscrape/targetstatus.qtpl:22 //line lib/promscrape/targetstatus.qtpl:21
if showOnlyUnhealthy && ts.up { if showOnlyUnhealthy && ts.up {
//line lib/promscrape/targetstatus.qtpl:22 //line lib/promscrape/targetstatus.qtpl:21
continue continue
//line lib/promscrape/targetstatus.qtpl:21
}
//line lib/promscrape/targetstatus.qtpl:22 //line lib/promscrape/targetstatus.qtpl:22
}
//line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S("\t") qw422016.N().S("\t")
//line lib/promscrape/targetstatus.qtpl:23 //line lib/promscrape/targetstatus.qtpl:22
qw422016.N().S(`state=`) qw422016.N().S(`state=`)
//line lib/promscrape/targetstatus.qtpl:24 //line lib/promscrape/targetstatus.qtpl:23
if ts.up { if ts.up {
//line lib/promscrape/targetstatus.qtpl:24 //line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S(`up`) qw422016.N().S(`up`)
//line lib/promscrape/targetstatus.qtpl:24 //line lib/promscrape/targetstatus.qtpl:23
} else { } else {
//line lib/promscrape/targetstatus.qtpl:24 //line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S(`down`) qw422016.N().S(`down`)
//line lib/promscrape/targetstatus.qtpl:24 //line lib/promscrape/targetstatus.qtpl:23
} }
//line lib/promscrape/targetstatus.qtpl:24 //line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S(`,`) qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:24 //line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:24 //line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S(`endpoint=`) qw422016.N().S(`endpoint=`)
//line lib/promscrape/targetstatus.qtpl:25 //line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(ts.sw.Config.ScrapeURL) qw422016.N().S(ts.sw.Config.ScrapeURL)
//line lib/promscrape/targetstatus.qtpl:25 //line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(`,`) qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:25 //line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:25 //line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(`labels=`) qw422016.N().S(`labels=`)
//line lib/promscrape/targetstatus.qtpl:26 //line lib/promscrape/targetstatus.qtpl:25
qw422016.N().S(promLabelsString(promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels))) qw422016.N().S(promLabelsString(promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels)))
//line lib/promscrape/targetstatus.qtpl:26 //line lib/promscrape/targetstatus.qtpl:25
qw422016.N().S(`,`) qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:26 //line lib/promscrape/targetstatus.qtpl:25
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:27 //line lib/promscrape/targetstatus.qtpl:26
if showOriginLabels { if showOriginLabels {
//line lib/promscrape/targetstatus.qtpl:27 //line lib/promscrape/targetstatus.qtpl:26
qw422016.N().S(`originalLabels=`) qw422016.N().S(`originalLabels=`)
//line lib/promscrape/targetstatus.qtpl:27 //line lib/promscrape/targetstatus.qtpl:26
qw422016.N().S(promLabelsString(ts.sw.Config.OriginalLabels)) qw422016.N().S(promLabelsString(ts.sw.Config.OriginalLabels))
//line lib/promscrape/targetstatus.qtpl:27 //line lib/promscrape/targetstatus.qtpl:26
qw422016.N().S(`,`) qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:27 //line lib/promscrape/targetstatus.qtpl:26
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:27 //line lib/promscrape/targetstatus.qtpl:26
} }
//line lib/promscrape/targetstatus.qtpl:27 //line lib/promscrape/targetstatus.qtpl:26
qw422016.N().S(`scrapes_total=`) qw422016.N().S(`scrapes_total=`)
//line lib/promscrape/targetstatus.qtpl:28 //line lib/promscrape/targetstatus.qtpl:27
qw422016.N().D(ts.scrapesTotal) qw422016.N().D(ts.scrapesTotal)
//line lib/promscrape/targetstatus.qtpl:28 //line lib/promscrape/targetstatus.qtpl:27
qw422016.N().S(`,`) qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:28 //line lib/promscrape/targetstatus.qtpl:27
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:28 //line lib/promscrape/targetstatus.qtpl:27
qw422016.N().S(`scrapes_failed=`) qw422016.N().S(`scrapes_failed=`)
//line lib/promscrape/targetstatus.qtpl:29 //line lib/promscrape/targetstatus.qtpl:28
qw422016.N().D(ts.scrapesFailed) qw422016.N().D(ts.scrapesFailed)
//line lib/promscrape/targetstatus.qtpl:29 //line lib/promscrape/targetstatus.qtpl:28
qw422016.N().S(`,`) qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:29 //line lib/promscrape/targetstatus.qtpl:28
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:29 //line lib/promscrape/targetstatus.qtpl:28
qw422016.N().S(`last_scrape=`) qw422016.N().S(`last_scrape=`)
//line lib/promscrape/targetstatus.qtpl:30 //line lib/promscrape/targetstatus.qtpl:29
qw422016.N().FPrec(ts.getDurationFromLastScrape().Seconds(), 3) qw422016.N().FPrec(ts.getDurationFromLastScrape().Seconds(), 3)
//line lib/promscrape/targetstatus.qtpl:30 //line lib/promscrape/targetstatus.qtpl:29
qw422016.N().S(`s ago,`) qw422016.N().S(`s ago,`)
//line lib/promscrape/targetstatus.qtpl:30 //line lib/promscrape/targetstatus.qtpl:29
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:30 //line lib/promscrape/targetstatus.qtpl:29
qw422016.N().S(`scrape_duration=`) qw422016.N().S(`scrape_duration=`)
//line lib/promscrape/targetstatus.qtpl:31 //line lib/promscrape/targetstatus.qtpl:30
qw422016.N().D(int(ts.scrapeDuration)) qw422016.N().D(int(ts.scrapeDuration))
//line lib/promscrape/targetstatus.qtpl:31 //line lib/promscrape/targetstatus.qtpl:30
qw422016.N().S(`ms,`) qw422016.N().S(`ms,`)
//line lib/promscrape/targetstatus.qtpl:31 //line lib/promscrape/targetstatus.qtpl:30
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:31 //line lib/promscrape/targetstatus.qtpl:30
qw422016.N().S(`samples_scraped=`) qw422016.N().S(`samples_scraped=`)
//line lib/promscrape/targetstatus.qtpl:32 //line lib/promscrape/targetstatus.qtpl:31
qw422016.N().D(ts.samplesScraped) qw422016.N().D(ts.samplesScraped)
//line lib/promscrape/targetstatus.qtpl:32 //line lib/promscrape/targetstatus.qtpl:31
qw422016.N().S(`,`) qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:32 //line lib/promscrape/targetstatus.qtpl:31
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:32 //line lib/promscrape/targetstatus.qtpl:31
qw422016.N().S(`error=`) qw422016.N().S(`error=`)
//line lib/promscrape/targetstatus.qtpl:33 //line lib/promscrape/targetstatus.qtpl:32
if ts.err != nil { if ts.err != nil {
//line lib/promscrape/targetstatus.qtpl:33 //line lib/promscrape/targetstatus.qtpl:32
qw422016.N().S(ts.err.Error()) qw422016.N().S(ts.err.Error())
//line lib/promscrape/targetstatus.qtpl:33 //line lib/promscrape/targetstatus.qtpl:32
} }
//line lib/promscrape/targetstatus.qtpl:34 //line lib/promscrape/targetstatus.qtpl:33
qw422016.N().S(` qw422016.N().S(`
`) `)
//line lib/promscrape/targetstatus.qtpl:35 //line lib/promscrape/targetstatus.qtpl:34
} }
//line lib/promscrape/targetstatus.qtpl:36 //line lib/promscrape/targetstatus.qtpl:35
} }
//line lib/promscrape/targetstatus.qtpl:38 //line lib/promscrape/targetstatus.qtpl:37
for _, jobName := range emptyJobs { for _, jobName := range emptyJobs {
//line lib/promscrape/targetstatus.qtpl:38 //line lib/promscrape/targetstatus.qtpl:37
qw422016.N().S(`job=`) qw422016.N().S(`job=`)
//line lib/promscrape/targetstatus.qtpl:39 //line lib/promscrape/targetstatus.qtpl:38
qw422016.N().Q(jobName) qw422016.N().Q(jobName)
//line lib/promscrape/targetstatus.qtpl:39 //line lib/promscrape/targetstatus.qtpl:38
qw422016.N().S(`(0/0 up)`) qw422016.N().S(`(0/0 up)`)
//line lib/promscrape/targetstatus.qtpl:40 //line lib/promscrape/targetstatus.qtpl:39
qw422016.N().S(` qw422016.N().S(`
`) `)
//line lib/promscrape/targetstatus.qtpl:41 //line lib/promscrape/targetstatus.qtpl:40
} }
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
} }
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
func WriteTargetsResponsePlain(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels, showOnlyUnhealthy bool, err error) { func WriteTargetsResponsePlain(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels, showOnlyUnhealthy bool, err error) {
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
StreamTargetsResponsePlain(qw422016, jts, emptyJobs, showOriginLabels, showOnlyUnhealthy, err) StreamTargetsResponsePlain(qw422016, jts, emptyJobs, showOriginLabels, showOnlyUnhealthy, err)
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
} }
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
func TargetsResponsePlain(jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels, showOnlyUnhealthy bool, err error) string { func TargetsResponsePlain(jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels, showOnlyUnhealthy bool, err error) string {
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
WriteTargetsResponsePlain(qb422016, jts, emptyJobs, showOriginLabels, showOnlyUnhealthy, err) WriteTargetsResponsePlain(qb422016, jts, emptyJobs, showOriginLabels, showOnlyUnhealthy, err)
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
return qs422016 return qs422016
//line lib/promscrape/targetstatus.qtpl:43 //line lib/promscrape/targetstatus.qtpl:42
} }
//line lib/promscrape/targetstatus.qtpl:45 //line lib/promscrape/targetstatus.qtpl:44
func StreamTargetsResponseHTML(qw422016 *qt422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, endpointSearch, labelSearch string, err error) { func StreamTargetsResponseHTML(qw422016 *qt422016.Writer, scrapeTargets scrapeTargets) {
//line lib/promscrape/targetstatus.qtpl:45 //line lib/promscrape/targetstatus.qtpl:46
qw422016.N().S(`<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link href="static/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"><title>Scrape targets</title><script>function collapse_all() {for (var i = 0; i <`) targetsStatuses := scrapeTargets.targetsStatuses
//line lib/promscrape/targetstatus.qtpl:55 filter := scrapeTargets.requestFilter
qw422016.N().D(len(jts)) if filter.activeTab == "" {
//line lib/promscrape/targetstatus.qtpl:55 filter.activeTab = "targets-tab"
qw422016.N().S(`; i++) {let el = document.getElementById("table-" + i);if (!el) {continue;}el.style.display = 'none';}}function expand_all() {for (var i = 0; i <`)
//line lib/promscrape/targetstatus.qtpl:64
qw422016.N().D(len(jts))
//line lib/promscrape/targetstatus.qtpl:64
qw422016.N().S(`; i++) {let el = document.getElementById("table-" + i);if (!el) {continue;}el.style.display = 'block';}}</script></head><body><div class="navbar navbar-dark bg-dark box-shadow"><div class="d-flex justify-content-between"><a href="#" class="navbar-brand d-flex align-items-center ms-3" title="The High Performance Open Source Time Series Database &amp; Monitoring Solution "><svg xmlns="http://www.w3.org/2000/svg" id="VM_logo" viewBox="0 0 464.61 533.89" width="20" height="20" class="me-1"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="M459.86,467.77c9,7.67,24.12,13.49,39.3,13.69v0h1.68v0c15.18-.2,30.31-6,39.3-13.69,47.43-40.45,184.65-166.24,184.65-166.24,36.84-34.27-65.64-68.28-223.95-68.47h-1.68c-158.31.19-260.79,34.2-224,68.47C275.21,301.53,412.43,427.32,459.86,467.77Z" transform="translate(-267.7 -233.05)"/><path class="cls-1" d="M540.1,535.88c-9,7.67-24.12,13.5-39.3,13.7h-1.6c-15.18-.2-30.31-6-39.3-13.7-32.81-28-148.56-132.93-192.16-172.7v60.74c0,6.67,2.55,15.52,7.09,19.68,29.64,27.18,143.94,131.8,185.07,166.88,9,7.67,24.12,13.49,39.3,13.69v0h1.6v0c15.18-.2,30.31-6,39.3-13.69,41.13-35.08,155.43-139.7,185.07-166.88,4.54-4.16,7.09-13,7.09-19.68V363.18C688.66,403,572.91,507.9,540.1,535.88Z" transform="translate(-267.7 -233.05)"/><path class="cls-1" d="M540.1,678.64c-9,7.67-24.12,13.49-39.3,13.69v0h-1.6v0c-15.18-.2-30.31-6-39.3-13.69-32.81-28-148.56-132.94-192.16-172.7v60.73c0,6.67,2.55,15.53,7.09,19.69,29.64,27.17,143.94,131.8,185.07,166.87,9,7.67,24.12,13.5,39.3,13.7h1.6c15.18-.2,30.31-6,39.3-13.7,41.13-35.07,155.43-139.7,185.07-166.87,4.54-4.16,7.09-13,7.09-19.69V505.94C688.66,545.7,572.91,650.66,540.1,678.64Z" transform="translate(-267.7 -233.05)"/></svg><strong>VictoriaMetrics</strong></a></div></div><div class="container-fluid">`)
//line lib/promscrape/targetstatus.qtpl:84
if err != nil {
//line lib/promscrape/targetstatus.qtpl:85
streamerrorNotification(qw422016, err)
//line lib/promscrape/targetstatus.qtpl:86
} }
//line lib/promscrape/targetstatus.qtpl:86
qw422016.N().S(`<div class="row"><main class="col-12"><h1>Scrape targets</h1><hr /><div class="row g-3 align-items-center mb-3"><div class="col-auto"><button type="button" class="btn`) //line lib/promscrape/targetstatus.qtpl:51
qw422016.N().S(`<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link href="static/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous"><title>Scrape targets</title><script>function collapse_all() {for (var i = 0; i <=`)
//line lib/promscrape/targetstatus.qtpl:61
qw422016.N().D(len(targetsStatuses.jobTargetsStatuses))
//line lib/promscrape/targetstatus.qtpl:61
qw422016.N().S(`; i++) {["table-"+i, "table-discovery-"+i, "table-empty-"+i].forEach((id) => {let el = document.getElementById(id);if (el) {el.style.display = 'none';}})}}function expand_all() {for (var i = 0; i <=`)
//line lib/promscrape/targetstatus.qtpl:71
qw422016.N().D(len(targetsStatuses.jobTargetsStatuses))
//line lib/promscrape/targetstatus.qtpl:71
qw422016.N().S(`; i++) {["table-"+i, "table-discovery-"+i, "table-empty-"+i].forEach((id) => {let el = document.getElementById(id);if (el) {el.style.display = 'block';}});}}</script></head><body><div class="navbar navbar-dark bg-dark box-shadow"><div class="d-flex justify-content-between"><a href="#" class="navbar-brand d-flex align-items-center ms-3" title="The High Performance Open Source Time Series Database &amp; Monitoring Solution "><svg xmlns="http://www.w3.org/2000/svg" id="VM_logo" viewBox="0 0 464.61 533.89" width="20" height="20" class="me-1"><defs><style>.cls-1{fill:#fff;}</style></defs><path class="cls-1" d="M459.86,467.77c9,7.67,24.12,13.49,39.3,13.69v0h1.68v0c15.18-.2,30.31-6,39.3-13.69,47.43-40.45,184.65-166.24,184.65-166.24,36.84-34.27-65.64-68.28-223.95-68.47h-1.68c-158.31.19-260.79,34.2-224,68.47C275.21,301.53,412.43,427.32,459.86,467.77Z" transform="translate(-267.7 -233.05)"/><path class="cls-1" d="M540.1,535.88c-9,7.67-24.12,13.5-39.3,13.7h-1.6c-15.18-.2-30.31-6-39.3-13.7-32.81-28-148.56-132.93-192.16-172.7v60.74c0,6.67,2.55,15.52,7.09,19.68,29.64,27.18,143.94,131.8,185.07,166.88,9,7.67,24.12,13.49,39.3,13.69v0h1.6v0c15.18-.2,30.31-6,39.3-13.69,41.13-35.08,155.43-139.7,185.07-166.88,4.54-4.16,7.09-13,7.09-19.68V363.18C688.66,403,572.91,507.9,540.1,535.88Z" transform="translate(-267.7 -233.05)"/><path class="cls-1" d="M540.1,678.64c-9,7.67-24.12,13.49-39.3,13.69v0h-1.6v0c-15.18-.2-30.31-6-39.3-13.69-32.81-28-148.56-132.94-192.16-172.7v60.73c0,6.67,2.55,15.53,7.09,19.69,29.64,27.17,143.94,131.8,185.07,166.87,9,7.67,24.12,13.5,39.3,13.7h1.6c15.18-.2,30.31-6,39.3-13.7,41.13-35.07,155.43-139.7,185.07-166.87,4.54-4.16,7.09-13,7.09-19.69V505.94C688.66,545.7,572.91,650.66,540.1,678.64Z" transform="translate(-267.7 -233.05)"/></svg><strong>VictoriaMetrics</strong></a></div></div><div class="container-fluid">`)
//line lib/promscrape/targetstatus.qtpl:92
if targetsStatuses.err != nil {
//line lib/promscrape/targetstatus.qtpl:93 //line lib/promscrape/targetstatus.qtpl:93
streamerrorNotification(qw422016, targetsStatuses.err)
//line lib/promscrape/targetstatus.qtpl:94
}
//line lib/promscrape/targetstatus.qtpl:94
qw422016.N().S(`<div class="row"><main class="col-12"><h1>Scrape targets</h1><hr /><div class="row g-3 align-items-center mb-3"><div class="col-auto"><button id="all-btn" type="button" class="btn`)
//line lib/promscrape/targetstatus.qtpl:101
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:93 //line lib/promscrape/targetstatus.qtpl:101
if !showOnlyUnhealthy { if !filter.showOnlyUnhealthy {
//line lib/promscrape/targetstatus.qtpl:93 //line lib/promscrape/targetstatus.qtpl:101
qw422016.N().S(`btn-secondary`) qw422016.N().S(`btn-secondary`)
//line lib/promscrape/targetstatus.qtpl:93 //line lib/promscrape/targetstatus.qtpl:101
} else { } else {
//line lib/promscrape/targetstatus.qtpl:93 //line lib/promscrape/targetstatus.qtpl:101
qw422016.N().S(`btn-success`) qw422016.N().S(`btn-success`)
//line lib/promscrape/targetstatus.qtpl:93 //line lib/promscrape/targetstatus.qtpl:101
} }
//line lib/promscrape/targetstatus.qtpl:93 //line lib/promscrape/targetstatus.qtpl:101
qw422016.N().S(`" onclick="location.href='?`) qw422016.N().S(`" onclick="location.href='?`)
//line lib/promscrape/targetstatus.qtpl:93 //line lib/promscrape/targetstatus.qtpl:101
streamqueryArgs(qw422016, map[string]string{ streamqueryArgs(qw422016, map[string]string{
"show_only_unhealthy": "false", "show_only_unhealthy": "false",
"endpoint_search": endpointSearch, "endpoint_search": filter.endpointSearch,
"label_search": labelSearch, "label_search": filter.labelSearch,
}) "active_tab": filter.activeTab,
//line lib/promscrape/targetstatus.qtpl:97
qw422016.N().S(`'">All</button></div><div class="col-auto"><button type="button" class="btn`)
//line lib/promscrape/targetstatus.qtpl:102
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:102
if showOnlyUnhealthy {
//line lib/promscrape/targetstatus.qtpl:102
qw422016.N().S(`btn-secondary`)
//line lib/promscrape/targetstatus.qtpl:102
} else {
//line lib/promscrape/targetstatus.qtpl:102
qw422016.N().S(`btn-danger`)
//line lib/promscrape/targetstatus.qtpl:102
}
//line lib/promscrape/targetstatus.qtpl:102
qw422016.N().S(`" onclick="location.href='?`)
//line lib/promscrape/targetstatus.qtpl:102
streamqueryArgs(qw422016, map[string]string{
"show_only_unhealthy": "true",
"endpoint_search": endpointSearch,
"label_search": labelSearch,
}) })
//line lib/promscrape/targetstatus.qtpl:106 //line lib/promscrape/targetstatus.qtpl:106
qw422016.N().S(`'">Unhealthy</button></div><div class="col-auto"><button type="button" class="btn btn-primary" onclick="collapse_all()">Collapse all</button></div><div class="col-auto"><button type="button" class="btn btn-secondary" onclick="expand_all()">Expand all</button></div><div class="col-auto">`) qw422016.N().S(`'">All</button></div><div class="col-auto"><button id="unhealthy-btn" type="button" class="btn`)
//line lib/promscrape/targetstatus.qtpl:121 //line lib/promscrape/targetstatus.qtpl:111
if endpointSearch == "" && labelSearch == "" { qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:121 //line lib/promscrape/targetstatus.qtpl:111
qw422016.N().S(`<button type="button" class="btn btn-success" onclick="document.getElementById('filters').style.display='block'">Filter targets</button>`) if filter.showOnlyUnhealthy {
//line lib/promscrape/targetstatus.qtpl:125 //line lib/promscrape/targetstatus.qtpl:111
qw422016.N().S(`btn-secondary`)
//line lib/promscrape/targetstatus.qtpl:111
} else { } else {
//line lib/promscrape/targetstatus.qtpl:125 //line lib/promscrape/targetstatus.qtpl:111
qw422016.N().S(`btn-danger`)
//line lib/promscrape/targetstatus.qtpl:111
}
//line lib/promscrape/targetstatus.qtpl:111
qw422016.N().S(`" onclick="location.href='?`)
//line lib/promscrape/targetstatus.qtpl:111
streamqueryArgs(qw422016, map[string]string{
"show_only_unhealthy": "true",
"endpoint_search": filter.endpointSearch,
"label_search": filter.labelSearch,
"active_tab": filter.activeTab,
})
//line lib/promscrape/targetstatus.qtpl:116
qw422016.N().S(`'">Unhealthy</button></div><div class="col-auto"><button type="button" class="btn btn-primary" onclick="collapse_all()">Collapse all</button></div><div class="col-auto"><button type="button" class="btn btn-secondary" onclick="expand_all()">Expand all</button></div><div class="col-auto">`)
//line lib/promscrape/targetstatus.qtpl:131
if filter.endpointSearch == "" && filter.labelSearch == "" {
//line lib/promscrape/targetstatus.qtpl:131
qw422016.N().S(`<button type="button" class="btn btn-success" onclick="document.getElementById('filters').style.display='block'">Filter targets</button>`)
//line lib/promscrape/targetstatus.qtpl:135
} else {
//line lib/promscrape/targetstatus.qtpl:135
qw422016.N().S(`<button type="button" class="btn btn-danger" onclick="location.href='?'">Clear target filters</button>`) qw422016.N().S(`<button type="button" class="btn btn-danger" onclick="location.href='?'">Clear target filters</button>`)
//line lib/promscrape/targetstatus.qtpl:129 //line lib/promscrape/targetstatus.qtpl:139
} }
//line lib/promscrape/targetstatus.qtpl:129 //line lib/promscrape/targetstatus.qtpl:139
qw422016.N().S(`</div></div><div id="filters"`) qw422016.N().S(`</div></div><div id="filters"`)
//line lib/promscrape/targetstatus.qtpl:132 //line lib/promscrape/targetstatus.qtpl:142
if endpointSearch == "" && labelSearch == "" { if filter.endpointSearch == "" && filter.labelSearch == "" {
//line lib/promscrape/targetstatus.qtpl:132 //line lib/promscrape/targetstatus.qtpl:142
qw422016.N().S(`style="display:none"`) qw422016.N().S(`style="display:none"`)
//line lib/promscrape/targetstatus.qtpl:132 //line lib/promscrape/targetstatus.qtpl:142
} }
//line lib/promscrape/targetstatus.qtpl:132 //line lib/promscrape/targetstatus.qtpl:142
qw422016.N().S(`><form class="form-horizontal"><div class="form-group mb-3"><label for="endpoint_search" class="col-sm-10 control-label">Endpoint filter (<a target="_blank" href="https://github.com/google/re2/wiki/Syntax">Regexp</a> is accepted)</label><div class="col-sm-10"><input type="text" id="endpoint_search" name="endpoint_search"placeholder="For example, 127.0.0.1" class="form-control" value="`) qw422016.N().S(`><form class="form-horizontal"><div class="form-group mb-3"><label for="endpoint_search" class="col-sm-10 control-label">Endpoint filter (<a target="_blank" href="https://github.com/google/re2/wiki/Syntax">Regexp</a> is accepted)</label><div class="col-sm-10"><input type="text" id="endpoint_search" name="endpoint_search"placeholder="For example, 127.0.0.1" class="form-control" value="`)
//line lib/promscrape/targetstatus.qtpl:138 //line lib/promscrape/targetstatus.qtpl:148
qw422016.E().S(endpointSearch) qw422016.E().S(filter.endpointSearch)
//line lib/promscrape/targetstatus.qtpl:138 //line lib/promscrape/targetstatus.qtpl:148
qw422016.N().S(`"/></div></div><div class="form-group mb-3"><label for="label_search" class="col-sm-10 control-label">Labels filter (<a target="_blank" href="https://prometheus.io/docs/prometheus/latest/querying/basics/#time-series-selectors">Arbitrary time series selectors</a> are accepted)</label><div class="col-sm-10"><input type="text" id="label_search" name="label_search"placeholder="For example, {instance=~'.+:9100'}" class="form-control" value="`) qw422016.N().S(`"/></div></div><div class="form-group mb-3"><label for="label_search" class="col-sm-10 control-label">Labels filter (<a target="_blank" href="https://prometheus.io/docs/prometheus/latest/querying/basics/#time-series-selectors">Arbitrary time series selectors</a> are accepted)</label><div class="col-sm-10"><input type="text" id="label_search" name="label_search"placeholder="For example, {instance=~'.+:9100'}" class="form-control" value="`)
//line lib/promscrape/targetstatus.qtpl:145
qw422016.E().S(labelSearch)
//line lib/promscrape/targetstatus.qtpl:145
qw422016.N().S(`"/></div></div><input type="hidden" name="show_only_unhealthy" value="`)
//line lib/promscrape/targetstatus.qtpl:148
qw422016.E().V(showOnlyUnhealthy)
//line lib/promscrape/targetstatus.qtpl:148
qw422016.N().S(`"/><button type="submit" class="btn btn-success mb-3">Submit</button></form></div><hr /><div class="row"><div class="col-12">`)
//line lib/promscrape/targetstatus.qtpl:155 //line lib/promscrape/targetstatus.qtpl:155
for i, js := range jts { qw422016.E().S(filter.labelSearch)
//line lib/promscrape/targetstatus.qtpl:156 //line lib/promscrape/targetstatus.qtpl:155
if showOnlyUnhealthy && js.upCount == js.targetsTotal { qw422016.N().S(`"/></div></div><input type="hidden" name="show_only_unhealthy" value="`)
//line lib/promscrape/targetstatus.qtpl:156 //line lib/promscrape/targetstatus.qtpl:158
continue qw422016.E().V(filter.showOnlyUnhealthy)
//line lib/promscrape/targetstatus.qtpl:156 //line lib/promscrape/targetstatus.qtpl:158
} qw422016.N().S(`"/><input id="tab_input" type="hidden" name="active_tab" value="`)
//line lib/promscrape/targetstatus.qtpl:156 //line lib/promscrape/targetstatus.qtpl:159
qw422016.N().S(`<div class="row mb-4"><div class="col-12"><h4><span class="me-2">`) qw422016.E().S(filter.activeTab)
//line lib/promscrape/targetstatus.qtpl:160 //line lib/promscrape/targetstatus.qtpl:159
qw422016.E().S(js.job) qw422016.N().S(`" /><button type="submit" class="btn btn-success mb-3">Submit</button></form></div><hr /><ul class="nav nav-tabs" id="myTab" role="tablist"><li class="nav-item" role="presentation"><button id="targets-tab" class="nav-link`)
//line lib/promscrape/targetstatus.qtpl:160 //line lib/promscrape/targetstatus.qtpl:166
if filter.activeTab == "targets-tab" {
//line lib/promscrape/targetstatus.qtpl:166
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:160 //line lib/promscrape/targetstatus.qtpl:166
qw422016.N().S(`(`) qw422016.N().S(`active`)
//line lib/promscrape/targetstatus.qtpl:160 //line lib/promscrape/targetstatus.qtpl:166
qw422016.N().D(js.upCount) }
//line lib/promscrape/targetstatus.qtpl:160 //line lib/promscrape/targetstatus.qtpl:166
qw422016.N().S(`/`) qw422016.N().S(`" data-bs-toggle="tab" data-bs-target="#targets" type="button" role="tab" aria-controls="home" aria-selected="true">Targets</button></li><li class="nav-item" role="presentation"><button id="discovery-tab" class="nav-link`)
//line lib/promscrape/targetstatus.qtpl:160 //line lib/promscrape/targetstatus.qtpl:169
qw422016.N().D(js.targetsTotal) if filter.activeTab == "discovery-tab" {
//line lib/promscrape/targetstatus.qtpl:160 //line lib/promscrape/targetstatus.qtpl:169
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:160 //line lib/promscrape/targetstatus.qtpl:169
qw422016.N().S(`up)</span><button type="button" class="btn btn-primary btn-sm me-1"onclick="document.getElementById('table-`) qw422016.N().S(`active`)
//line lib/promscrape/targetstatus.qtpl:162 //line lib/promscrape/targetstatus.qtpl:169
qw422016.N().D(i)
//line lib/promscrape/targetstatus.qtpl:162
qw422016.N().S(`').style.display='none'">collapse</button><button type="button" class="btn btn-secondary btn-sm me-1"onclick="document.getElementById('table-`)
//line lib/promscrape/targetstatus.qtpl:165
qw422016.N().D(i)
//line lib/promscrape/targetstatus.qtpl:165
qw422016.N().S(`').style.display='block'">expand</button></h4><div id="table-`)
//line lib/promscrape/targetstatus.qtpl:168
qw422016.N().D(i)
//line lib/promscrape/targetstatus.qtpl:168
qw422016.N().S(`" class="table-responsive"><table class="table table-striped table-hover table-bordered table-sm"><thead><tr><th scope="col">Endpoint</th><th scope="col">State</th><th scope="col" title="scrape target labels">Labels</th><th scope="col" title="total scrapes">Scrapes</th><th scope="col" title="total scrape errors">Errors</th><th scope="col" title="the time of the last scrape">Last Scrape</th><th scope="col" title="the duration of the last scrape">Duration</th><th scope="col" title="the number of metrics scraped during the last scrape">Samples</th><th scope="col" title="error from the last scrape (if any)">Last error</th></tr></thead><tbody class="list-`)
//line lib/promscrape/targetstatus.qtpl:183
qw422016.N().D(i)
//line lib/promscrape/targetstatus.qtpl:183
qw422016.N().S(`">`)
//line lib/promscrape/targetstatus.qtpl:184
for _, ts := range js.targetsStatus {
//line lib/promscrape/targetstatus.qtpl:186
endpoint := ts.sw.Config.ScrapeURL
targetID := getTargetID(ts.sw)
lastScrapeTime := ts.getDurationFromLastScrape()
//line lib/promscrape/targetstatus.qtpl:190
if showOnlyUnhealthy && ts.up {
//line lib/promscrape/targetstatus.qtpl:190
continue
//line lib/promscrape/targetstatus.qtpl:190
}
//line lib/promscrape/targetstatus.qtpl:190
qw422016.N().S(`<tr`)
//line lib/promscrape/targetstatus.qtpl:191
if !ts.up {
//line lib/promscrape/targetstatus.qtpl:191
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:191
qw422016.N().S(`class="alert alert-danger" role="alert"`)
//line lib/promscrape/targetstatus.qtpl:191
}
//line lib/promscrape/targetstatus.qtpl:191
qw422016.N().S(`><td class="endpoint"><a href="`)
//line lib/promscrape/targetstatus.qtpl:192
qw422016.E().S(endpoint)
//line lib/promscrape/targetstatus.qtpl:192
qw422016.N().S(`" target="_blank">`)
//line lib/promscrape/targetstatus.qtpl:192
qw422016.E().S(endpoint)
//line lib/promscrape/targetstatus.qtpl:192
qw422016.N().S(`</a> (<a href="target_response?id=`)
//line lib/promscrape/targetstatus.qtpl:193
qw422016.E().S(targetID)
//line lib/promscrape/targetstatus.qtpl:193
qw422016.N().S(`" target="_blank"title="click to fetch target response on behalf of the scraper">response</a>)</td><td>`)
//line lib/promscrape/targetstatus.qtpl:197
if ts.up {
//line lib/promscrape/targetstatus.qtpl:197
qw422016.N().S(`UP`)
//line lib/promscrape/targetstatus.qtpl:197
} else {
//line lib/promscrape/targetstatus.qtpl:197
qw422016.N().S(`DOWN`)
//line lib/promscrape/targetstatus.qtpl:197
}
//line lib/promscrape/targetstatus.qtpl:197
qw422016.N().S(`</td><td class="labels"><div title="click to show original labels"onclick="document.getElementById('original_labels_`)
//line lib/promscrape/targetstatus.qtpl:200
qw422016.E().S(targetID)
//line lib/promscrape/targetstatus.qtpl:200
qw422016.N().S(`').style.display='block'">`)
//line lib/promscrape/targetstatus.qtpl:201
streamformatLabel(qw422016, promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels))
//line lib/promscrape/targetstatus.qtpl:201
qw422016.N().S(`</div><div style="display:none" id="original_labels_`)
//line lib/promscrape/targetstatus.qtpl:203
qw422016.E().S(targetID)
//line lib/promscrape/targetstatus.qtpl:203
qw422016.N().S(`">`)
//line lib/promscrape/targetstatus.qtpl:204
streamformatLabel(qw422016, ts.sw.Config.OriginalLabels)
//line lib/promscrape/targetstatus.qtpl:204
qw422016.N().S(`</div></td><td>`)
//line lib/promscrape/targetstatus.qtpl:207
qw422016.N().D(ts.scrapesTotal)
//line lib/promscrape/targetstatus.qtpl:207
qw422016.N().S(`</td><td>`)
//line lib/promscrape/targetstatus.qtpl:208
qw422016.N().D(ts.scrapesFailed)
//line lib/promscrape/targetstatus.qtpl:208
qw422016.N().S(`</td><td>`)
//line lib/promscrape/targetstatus.qtpl:210
if lastScrapeTime < 365*24*time.Hour {
//line lib/promscrape/targetstatus.qtpl:211
qw422016.N().FPrec(lastScrapeTime.Seconds(), 3)
//line lib/promscrape/targetstatus.qtpl:211
qw422016.N().S(`s ago`)
//line lib/promscrape/targetstatus.qtpl:212
} else {
//line lib/promscrape/targetstatus.qtpl:212
qw422016.N().S(`none`)
//line lib/promscrape/targetstatus.qtpl:214
}
//line lib/promscrape/targetstatus.qtpl:214
qw422016.N().S(`<td>`)
//line lib/promscrape/targetstatus.qtpl:215
qw422016.N().D(int(ts.scrapeDuration))
//line lib/promscrape/targetstatus.qtpl:215
qw422016.N().S(`ms</td><td>`)
//line lib/promscrape/targetstatus.qtpl:216
qw422016.N().D(ts.samplesScraped)
//line lib/promscrape/targetstatus.qtpl:216
qw422016.N().S(`</td><td>`)
//line lib/promscrape/targetstatus.qtpl:217
if ts.err != nil {
//line lib/promscrape/targetstatus.qtpl:217
qw422016.E().S(ts.err.Error())
//line lib/promscrape/targetstatus.qtpl:217
}
//line lib/promscrape/targetstatus.qtpl:217
qw422016.N().S(`</td></tr>`)
//line lib/promscrape/targetstatus.qtpl:219
}
//line lib/promscrape/targetstatus.qtpl:219
qw422016.N().S(`</tbody></table></div></div></div>`)
//line lib/promscrape/targetstatus.qtpl:225
} }
//line lib/promscrape/targetstatus.qtpl:225 //line lib/promscrape/targetstatus.qtpl:169
qw422016.N().S(`</div></div>`) qw422016.N().S(`" data-bs-toggle="tab" data-bs-target="#discovery" type="button" role="tab" aria-controls="profile" aria-selected="false">Service Discovery</button></li></ul><div class="tab-content"><div id="targets" class="tab-pane`)
//line lib/promscrape/targetstatus.qtpl:229 //line lib/promscrape/targetstatus.qtpl:173
for _, jobName := range emptyJobs { if filter.activeTab == "targets-tab" {
//line lib/promscrape/targetstatus.qtpl:229 //line lib/promscrape/targetstatus.qtpl:173
qw422016.N().S(`<div><h4><a>`) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:232 //line lib/promscrape/targetstatus.qtpl:173
qw422016.E().S(jobName) qw422016.N().S(`active`)
//line lib/promscrape/targetstatus.qtpl:232 //line lib/promscrape/targetstatus.qtpl:173
qw422016.N().S(`(0/0 up)</a></h4><table class="table table-striped table-hover table-bordered table-sm"><thead><tr><th scope="col">Endpoint</th><th scope="col">State</th><th scope="col">Labels</th><th scope="col">Last Scrape</th><th scope="col">Scrape Duration</th><th scope="col">Samples Scraped</th><th scope="col">Error</th></tr></thead></table></div>`)
//line lib/promscrape/targetstatus.qtpl:248
} }
//line lib/promscrape/targetstatus.qtpl:248 //line lib/promscrape/targetstatus.qtpl:173
qw422016.N().S(`</main></div></div></body></html>`) qw422016.N().S(`" role="tabpanel" aria-labelledby="targets-tab">`)
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:174
StreamTargets(qw422016, targetsStatuses.jobTargetsStatuses, targetsStatuses.emptyJobs, filter.showOnlyUnhealthy)
//line lib/promscrape/targetstatus.qtpl:174
qw422016.N().S(`</div><div id="discovery" class="tab-pane`)
//line lib/promscrape/targetstatus.qtpl:176
if filter.activeTab == "discovery-tab" {
//line lib/promscrape/targetstatus.qtpl:176
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:176
qw422016.N().S(`active`)
//line lib/promscrape/targetstatus.qtpl:176
}
//line lib/promscrape/targetstatus.qtpl:176
qw422016.N().S(`" role="tabpanel" aria-labelledby="profile-tab">`)
//line lib/promscrape/targetstatus.qtpl:177
StreamServiceDiscovery(qw422016, targetsStatuses.jobTargetsStatuses, targetsStatuses.emptyJobs, filter.showOnlyUnhealthy, targetsStatuses.droppedKeyStatuses)
//line lib/promscrape/targetstatus.qtpl:177
qw422016.N().S(`</div></div></main></div></div><script src="static/js/jquery-3.6.0.min.js" type="text/javascript"></script><script src="static/js/bootstrap.bundle.min.js" type="text/javascript"></script><script>(function(){const navBtns = document.querySelectorAll(".nav-link");const tabInput = document.getElementById("tab_input");const unhealthyBtn = document.getElementById("unhealthy-btn");const allBtn = document.getElementById("all-btn");navBtns.forEach((btn) => {if (btn) {btn.addEventListener("click", (e) => {if (window.history.replaceState) {var url = new URL(window.location.href);url.searchParams.set("active_tab", e.target.id);tabInput.value = e.target.id;unhealthyBtn.onclick = () => {url.searchParams.set("show_only_unhealthy", "true");window.location.href=url;};allBtn.onclick = () => {url.searchParams.set("show_only_unhealthy", "false");window.location.href=url;};window.history.replaceState({}, "", url);}});}})})()</script></body></html>`)
//line lib/promscrape/targetstatus.qtpl:215
} }
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
func WriteTargetsResponseHTML(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, endpointSearch, labelSearch string, err error) { func WriteTargetsResponseHTML(qq422016 qtio422016.Writer, scrapeTargets scrapeTargets) {
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
StreamTargetsResponseHTML(qw422016, jts, emptyJobs, showOnlyUnhealthy, endpointSearch, labelSearch, err) StreamTargetsResponseHTML(qw422016, scrapeTargets)
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
} }
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
func TargetsResponseHTML(jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, endpointSearch, labelSearch string, err error) string { func TargetsResponseHTML(scrapeTargets scrapeTargets) string {
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
WriteTargetsResponseHTML(qb422016, jts, emptyJobs, showOnlyUnhealthy, endpointSearch, labelSearch, err) WriteTargetsResponseHTML(qb422016, scrapeTargets)
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
return qs422016 return qs422016
//line lib/promscrape/targetstatus.qtpl:254 //line lib/promscrape/targetstatus.qtpl:215
} }
//line lib/promscrape/targetstatus.qtpl:256 //line lib/promscrape/targetstatus.qtpl:217
func streamqueryArgs(qw422016 *qt422016.Writer, m map[string]string) { func streamqueryArgs(qw422016 *qt422016.Writer, m map[string]string) {
//line lib/promscrape/targetstatus.qtpl:258 //line lib/promscrape/targetstatus.qtpl:219
qa := make(url.Values, len(m)) qa := make(url.Values, len(m))
for k, v := range m { for k, v := range m {
qa[k] = []string{v} qa[k] = []string{v}
} }
//line lib/promscrape/targetstatus.qtpl:263 //line lib/promscrape/targetstatus.qtpl:224
qw422016.E().S(qa.Encode()) qw422016.E().S(qa.Encode())
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
} }
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
func writequeryArgs(qq422016 qtio422016.Writer, m map[string]string) { func writequeryArgs(qq422016 qtio422016.Writer, m map[string]string) {
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
streamqueryArgs(qw422016, m) streamqueryArgs(qw422016, m)
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
} }
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
func queryArgs(m map[string]string) string { func queryArgs(m map[string]string) string {
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
writequeryArgs(qb422016, m) writequeryArgs(qb422016, m)
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
return qs422016 return qs422016
//line lib/promscrape/targetstatus.qtpl:264 //line lib/promscrape/targetstatus.qtpl:225
} }
//line lib/promscrape/targetstatus.qtpl:266 //line lib/promscrape/targetstatus.qtpl:227
func streamformatLabel(qw422016 *qt422016.Writer, labels []prompbmarshal.Label) { func streamformatLabel(qw422016 *qt422016.Writer, labels []prompbmarshal.Label) {
//line lib/promscrape/targetstatus.qtpl:266 //line lib/promscrape/targetstatus.qtpl:227
qw422016.N().S(`{`) qw422016.N().S(`{`)
//line lib/promscrape/targetstatus.qtpl:268 //line lib/promscrape/targetstatus.qtpl:229
for i, label := range labels { for i, label := range labels {
//line lib/promscrape/targetstatus.qtpl:269 //line lib/promscrape/targetstatus.qtpl:230
qw422016.E().S(label.Name) qw422016.E().S(label.Name)
//line lib/promscrape/targetstatus.qtpl:269 //line lib/promscrape/targetstatus.qtpl:230
qw422016.N().S(`=`) qw422016.N().S(`=`)
//line lib/promscrape/targetstatus.qtpl:269 //line lib/promscrape/targetstatus.qtpl:230
qw422016.E().Q(label.Value) qw422016.E().Q(label.Value)
//line lib/promscrape/targetstatus.qtpl:270 //line lib/promscrape/targetstatus.qtpl:231
if i+1 < len(labels) { if i+1 < len(labels) {
//line lib/promscrape/targetstatus.qtpl:270 //line lib/promscrape/targetstatus.qtpl:231
qw422016.N().S(`,`) qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:270 //line lib/promscrape/targetstatus.qtpl:231
qw422016.N().S(` `) qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:270 //line lib/promscrape/targetstatus.qtpl:231
} }
//line lib/promscrape/targetstatus.qtpl:271 //line lib/promscrape/targetstatus.qtpl:232
} }
//line lib/promscrape/targetstatus.qtpl:271 //line lib/promscrape/targetstatus.qtpl:232
qw422016.N().S(`}`) qw422016.N().S(`}`)
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
} }
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
func writeformatLabel(qq422016 qtio422016.Writer, labels []prompbmarshal.Label) { func writeformatLabel(qq422016 qtio422016.Writer, labels []prompbmarshal.Label) {
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
streamformatLabel(qw422016, labels) streamformatLabel(qw422016, labels)
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
} }
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
func formatLabel(labels []prompbmarshal.Label) string { func formatLabel(labels []prompbmarshal.Label) string {
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
writeformatLabel(qb422016, labels) writeformatLabel(qb422016, labels)
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
return qs422016 return qs422016
//line lib/promscrape/targetstatus.qtpl:273 //line lib/promscrape/targetstatus.qtpl:234
} }
//line lib/promscrape/targetstatus.qtpl:275 //line lib/promscrape/targetstatus.qtpl:236
func streamerrorNotification(qw422016 *qt422016.Writer, err error) { func streamerrorNotification(qw422016 *qt422016.Writer, err error) {
//line lib/promscrape/targetstatus.qtpl:275 //line lib/promscrape/targetstatus.qtpl:236
qw422016.N().S(`<div class="alert alert-danger d-flex align-items-center" role="alert"><svg class="bi flex-shrink-0 me-2" width="24" height="24" role="img" aria-label="Danger:"><use xlink:href="#exclamation-triangle-fill"/></svg><div>`) qw422016.N().S(`<div class="alert alert-danger d-flex align-items-center" role="alert"><svg class="bi flex-shrink-0 me-2" width="24" height="24" role="img" aria-label="Danger:"><use xlink:href="#exclamation-triangle-fill"/></svg><div>`)
//line lib/promscrape/targetstatus.qtpl:280 //line lib/promscrape/targetstatus.qtpl:241
qw422016.E().S(err.Error()) qw422016.E().S(err.Error())
//line lib/promscrape/targetstatus.qtpl:280 //line lib/promscrape/targetstatus.qtpl:241
qw422016.N().S(`</div></div>`) qw422016.N().S(`</div></div>`)
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
} }
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
func writeerrorNotification(qq422016 qtio422016.Writer, err error) { func writeerrorNotification(qq422016 qtio422016.Writer, err error) {
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
streamerrorNotification(qw422016, err) streamerrorNotification(qw422016, err)
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
} }
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
func errorNotification(err error) string { func errorNotification(err error) string {
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
writeerrorNotification(qb422016, err) writeerrorNotification(qb422016, err)
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
return qs422016 return qs422016
//line lib/promscrape/targetstatus.qtpl:283 //line lib/promscrape/targetstatus.qtpl:244
} }