lib/promscrape: Enable filters for endpoint and labels (#2466)

* lib/promscrape: Enable filters for endpoint and labels

* lib/promscrape: cleanup

* lib/promscrape: update template

* lib/promscrape: move logic filter logic to backend

* lib/promscrape: updated placeholder

* lib/promscrape: updated placeholder

* lib/promscrape: use two different fields for filters, updated form, added error on parsing queries

* lib/promscrape: rename functions

* lib/promscrape: removed unused values

* wip

* wip

* wip

Co-authored-by: Aliaksandr Valialkin <valyala@victoriametrics.com>
This commit is contained in:
Dmytro Kozlov 2022-04-19 18:26:21 +03:00 committed by Aliaksandr Valialkin
parent 7a622a71ea
commit 17552dba8b
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
6 changed files with 795 additions and 424 deletions

View file

@ -15,6 +15,7 @@ The following tip changes can be tested by building VictoriaMetrics components f
## tip
* FEATUREL [vmagent](https://docs.victoriametrics.com/vmagent.html): allow filtering targets by target url and by target labels with [time series selector](https://prometheus.io/docs/prometheus/latest/querying/basics/#time-series-selectors) on `http://vmagent:8429/targets` page. This may be useful when `vmagent` scrapes big number of targets. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1796).
* FEATURE: [vmagent](https://docs.victoriametrics.com/vmagent.html): reduce `-promscrape.config` reload duration when the config contains big number of jobs (aka [scrape_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config) sections) and only a few of them are changed. Previously all the jobs were restarted. Now only the jobs with changed configs are restarted. This should reduce the probability of data miss because of slow config reload. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2270).
* FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert.html): add support for DNS-based discovery for notifiers in the same way as Prometheus does. See [these docs](https://docs.victoriametrics.com/vmalert.html#notifier-configuration-file) and [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2460).
* FEATURE: allow specifying TLS cipher suites for incoming https requests via `-tlsCipherSuites` command-line flag. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/2404).

View file

@ -17,26 +17,34 @@ type IfExpression struct {
lfs []*labelFilter
}
// Parse parses `if` expression from s and stores it to ie.
func (ie *IfExpression) Parse(s string) error {
expr, err := metricsql.Parse(s)
if err != nil {
return err
}
me, ok := expr.(*metricsql.MetricExpr)
if !ok {
return fmt.Errorf("expecting series selector; got %q", expr.AppendString(nil))
}
lfs, err := metricExprToLabelFilters(me)
if err != nil {
return fmt.Errorf("cannot parse series selector: %w", err)
}
ie.s = s
ie.lfs = lfs
return nil
}
// UnmarshalYAML unmarshals ie from YAML passed to f.
func (ie *IfExpression) UnmarshalYAML(f func(interface{}) error) error {
var s string
if err := f(&s); err != nil {
return fmt.Errorf("cannot unmarshal `if` option: %w", err)
}
expr, err := metricsql.Parse(s)
if err != nil {
if err := ie.Parse(s); err != nil {
return fmt.Errorf("cannot parse `if` series selector: %w", err)
}
me, ok := expr.(*metricsql.MetricExpr)
if !ok {
return fmt.Errorf("expecting `if` series selector; got %q", expr.AppendString(nil))
}
lfs, err := metricExprToLabelFilters(me)
if err != nil {
return fmt.Errorf("cannot parse `if` filters: %w", err)
}
ie.s = s
ie.lfs = lfs
return nil
}

View file

@ -10,6 +10,32 @@ import (
"gopkg.in/yaml.v2"
)
func TestIfExpressionParseFailure(t *testing.T) {
f := func(s string) {
t.Helper()
var ie IfExpression
if err := ie.Parse(s); err == nil {
t.Fatalf("expecting non-nil error when parsing %q", s)
}
}
f(`{`)
f(`{foo`)
f(`foo{`)
}
func TestIfExpressionParseSuccess(t *testing.T) {
f := func(s string) {
t.Helper()
var ie IfExpression
if err := ie.Parse(s); err != nil {
t.Fatalf("unexpected error: %s", err)
}
}
f(`foo`)
f(`{foo="bar"}`)
f(`foo{bar=~"baz", x!="y"}`)
}
func TestIfExpressionUnmarshalFailure(t *testing.T) {
f := func(s string) {
t.Helper()

View file

@ -5,6 +5,7 @@ import (
"fmt"
"io"
"net/http"
"regexp"
"sort"
"strconv"
"strings"
@ -45,12 +46,14 @@ func WriteTargetResponse(w http.ResponseWriter, r *http.Request) error {
func WriteHumanReadableTargetsStatus(w http.ResponseWriter, r *http.Request) {
showOriginalLabels, _ := strconv.ParseBool(r.FormValue("show_original_labels"))
showOnlyUnhealthy, _ := strconv.ParseBool(r.FormValue("show_only_unhealthy"))
endpointSearch := strings.TrimSpace(r.FormValue("endpoint_search"))
labelSearch := strings.TrimSpace(r.FormValue("label_search"))
if accept := r.Header.Get("Accept"); strings.Contains(accept, "text/html") {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
tsmGlobal.WriteTargetsHTML(w, showOnlyUnhealthy)
tsmGlobal.WriteTargetsHTML(w, showOnlyUnhealthy, endpointSearch, labelSearch)
} else {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
tsmGlobal.WriteTargetsPlain(w, showOriginalLabels)
tsmGlobal.WriteTargetsPlain(w, showOriginalLabels, showOnlyUnhealthy, endpointSearch, labelSearch)
}
}
@ -318,7 +321,7 @@ type jobTargetsStatuses struct {
targetsStatus []targetStatus
}
func (tsm *targetStatusMap) getTargetsStatusByJob() ([]jobTargetsStatuses, []string) {
func (tsm *targetStatusMap) getTargetsStatusByJob(endpointSearch, labelSearch string) ([]jobTargetsStatuses, []string, error) {
byJob := make(map[string][]targetStatus)
tsm.mu.Lock()
for _, st := range tsm.m {
@ -352,7 +355,78 @@ func (tsm *targetStatusMap) getTargetsStatusByJob() ([]jobTargetsStatuses, []str
return jts[i].job < jts[j].job
})
emptyJobs := getEmptyJobs(jts, jobNames)
return jts, emptyJobs
var err error
jts, err = filterTargets(jts, endpointSearch, labelSearch)
if len(endpointSearch) > 0 || len(labelSearch) > 0 {
// Do not show empty jobs if target filters are set.
emptyJobs = nil
}
return jts, emptyJobs, err
}
func filterTargetsByEndpoint(jts []jobTargetsStatuses, searchQuery string) ([]jobTargetsStatuses, error) {
if searchQuery == "" {
return jts, nil
}
finder, err := regexp.Compile(searchQuery)
if err != nil {
return nil, fmt.Errorf("cannot parse %s: %w", searchQuery, err)
}
var jtsFiltered []jobTargetsStatuses
for _, job := range jts {
var tss []targetStatus
for _, ts := range job.targetsStatus {
if finder.MatchString(ts.sw.Config.ScrapeURL) {
tss = append(tss, ts)
}
}
if len(tss) == 0 {
// Skip jobs with zero targets after filtering, so users could see only the requested targets
continue
}
job.targetsStatus = tss
jtsFiltered = append(jtsFiltered, job)
}
return jtsFiltered, nil
}
func filterTargetsByLabels(jts []jobTargetsStatuses, searchQuery string) ([]jobTargetsStatuses, error) {
if searchQuery == "" {
return jts, nil
}
var ie promrelabel.IfExpression
if err := ie.Parse(searchQuery); err != nil {
return nil, fmt.Errorf("cannot parse %s: %w", searchQuery, err)
}
var jtsFiltered []jobTargetsStatuses
for _, job := range jts {
var tss []targetStatus
for _, ts := range job.targetsStatus {
if ie.Match(ts.sw.Config.Labels) {
tss = append(tss, ts)
}
}
if len(tss) == 0 {
// Skip jobs with zero targets after filtering, so users could see only the requested targets
continue
}
job.targetsStatus = tss
jtsFiltered = append(jtsFiltered, job)
}
return jtsFiltered, nil
}
func filterTargets(jts []jobTargetsStatuses, endpointQuery, labelQuery string) ([]jobTargetsStatuses, error) {
var err error
jts, err = filterTargetsByEndpoint(jts, endpointQuery)
if err != nil {
return nil, err
}
jts, err = filterTargetsByLabels(jts, labelQuery)
if err != nil {
return nil, err
}
return jts, nil
}
func getEmptyJobs(jts []jobTargetsStatuses, jobNames []string) []string {
@ -373,14 +447,14 @@ func getEmptyJobs(jts []jobTargetsStatuses, jobNames []string) []string {
// WriteTargetsHTML writes targets status grouped by job into writer w in html table,
// accepts filter to show only unhealthy targets.
func (tsm *targetStatusMap) WriteTargetsHTML(w io.Writer, showOnlyUnhealthy bool) {
jss, emptyJobs := tsm.getTargetsStatusByJob()
WriteTargetsResponseHTML(w, jss, emptyJobs, showOnlyUnhealthy)
func (tsm *targetStatusMap) WriteTargetsHTML(w io.Writer, showOnlyUnhealthy bool, endpointSearch, labelSearch string) {
jss, emptyJobs, err := tsm.getTargetsStatusByJob(endpointSearch, labelSearch)
WriteTargetsResponseHTML(w, jss, emptyJobs, showOnlyUnhealthy, endpointSearch, labelSearch, err)
}
// WriteTargetsPlain writes targets grouped by job into writer w in plain text,
// accept filter to show original labels.
func (tsm *targetStatusMap) WriteTargetsPlain(w io.Writer, showOriginalLabels bool) {
jss, emptyJobs := tsm.getTargetsStatusByJob()
WriteTargetsResponsePlain(w, jss, emptyJobs, showOriginalLabels)
func (tsm *targetStatusMap) WriteTargetsPlain(w io.Writer, showOriginalLabels, showOnlyUnhealthy bool, endpointSearch, labelSearch string) {
jss, emptyJobs, err := tsm.getTargetsStatusByJob(endpointSearch, labelSearch)
WriteTargetsResponsePlain(w, jss, emptyJobs, showOriginalLabels, showOnlyUnhealthy, err)
}

View file

@ -1,4 +1,5 @@
{% import (
"net/url"
"time"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
@ -6,25 +7,32 @@
{% stripspace %}
{% func TargetsResponsePlain(jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels bool) %}
{% func TargetsResponsePlain(jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels, showOnlyUnhealthy bool, err error) %}
{% if err != nil %}
{%s= err.Error() %}
{% return %}
{% endif %}
{% for _, js := range jts %}
job={%q= js.job %} ({%d js.upCount %}/{%d js.targetsTotal %}{% space %}up)
{% newline %}
{% for _, ts := range js.targetsStatus %}
{%s= "\t" %}
state={% if ts.up %}up{% else %}down{% endif %},{% space %}
endpoint={%s= ts.sw.Config.ScrapeURL %},{% space %}
labels={%s= promLabelsString(promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels)) %},{% space %}
{% if showOriginLabels %}originalLabels={%s= promLabelsString(ts.sw.Config.OriginalLabels) %},{% space %}{% endif %}
scrapes_total={%d ts.scrapesTotal %},{% space %}
scrapes_failed={%d ts.scrapesFailed %},{% space %}
last_scrape={%f.3 ts.getDurationFromLastScrape().Seconds() %}s ago,{% space %}
scrape_duration={%d int(ts.scrapeDuration) %}ms,{% space %}
samples_scraped={%d ts.samplesScraped %},{% space %}
error={% if ts.err != nil %}{%s= ts.err.Error() %}{% endif %}
{% newline %}
{% endfor %}
{% if showOnlyUnhealthy && js.upCount == js.targetsTotal %}{% continue %}{% endif %}
job={%q= js.job %} ({%d js.upCount %}/{%d js.targetsTotal %}{% space %}up)
{% newline %}
{% for _, ts := range js.targetsStatus %}
{% if showOnlyUnhealthy && ts.up %}{% continue %}{% endif %}
{%s= "\t" %}
state={% if ts.up %}up{% else %}down{% endif %},{% space %}
endpoint={%s= ts.sw.Config.ScrapeURL %},{% space %}
labels={%s= promLabelsString(promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels)) %},{% space %}
{% if showOriginLabels %}originalLabels={%s= promLabelsString(ts.sw.Config.OriginalLabels) %},{% space %}{% endif %}
scrapes_total={%d ts.scrapesTotal %},{% space %}
scrapes_failed={%d ts.scrapesFailed %},{% space %}
last_scrape={%f.3 ts.getDurationFromLastScrape().Seconds() %}s ago,{% space %}
scrape_duration={%d int(ts.scrapeDuration) %}ms,{% space %}
samples_scraped={%d ts.samplesScraped %},{% space %}
error={% if ts.err != nil %}{%s= ts.err.Error() %}{% endif %}
{% newline %}
{% endfor %}
{% endfor %}
{% for _, jobName := range emptyJobs %}
@ -34,7 +42,7 @@ job={%q= jobName %} (0/0 up)
{% endfunc %}
{% func TargetsResponseHTML(jts []jobTargetsStatuses, emptyJobs []string, onlyUnhealthy bool) %}
{% func TargetsResponseHTML(jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, endpointSearch, labelSearch string, err error) %}
<!DOCTYPE html>
<html lang="en">
<head>
@ -63,109 +71,194 @@ function expand_all() {
}
</script>
</head>
<body class="m-3">
<h1>Scrape targets</h1>
<div style="padding: 3px">
<button type="button" class="btn{% space %}{% if !onlyUnhealthy %}btn-primary{% else %}btn-secondary{% endif %}" onclick="location.href='targets'">
All
</button>
<button type="button" class="btn{% space %}{% if onlyUnhealthy %}btn-primary{% else %}btn-secondary{% endif %}" onclick="location.href='targets?show_only_unhealthy=true'">
Unhealthy
</button>
<button type="button" class="btn btn-primary" onclick="collapse_all()">
Collapse all
</button>
<button type="button" class="btn btn-secondary" onclick="expand_all()">
Expand all
</button>
</div>
{% for i, js := range jts %}
{% if onlyUnhealthy && js.upCount == js.targetsTotal %}{% continue %}{% endif %}
<div>
<h4>
{%s js.job %}{% space %}({%d js.upCount %}/{%d js.targetsTotal %}{% space %}up)
<button type="button" class="btn btn-primary" onclick="document.getElementById('table-{%d i %}').style.display='none'">collapse</button>
<button type="button" class="btn btn-secondary" onclick="document.getElementById('table-{%d i %}').style.display='block'">expand</button>
</h4>
<div id="table-{%d i %}">
<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>
{% for _, ts := range js.targetsStatus %}
{% code
endpoint := ts.sw.Config.ScrapeURL
targetID := getTargetID(ts.sw)
lastScrapeTime := ts.getDurationFromLastScrape()
%}
{% if onlyUnhealthy && ts.up %}{% continue %}{% endif %}
<tr {% if !ts.up %}{%space%}class="alert alert-danger" role="alert"{% endif %}>
<td><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>
<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)) %}
<body class="py-3">
<div class="container-fluid">
{% if err != nil %}
{%= errorNotification(err) %}
{% endif %}
<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{% space %}{% if !showOnlyUnhealthy %}btn-primary{% else %}btn-secondary{% endif %}" onclick="location.href='?{%= queryArgs(map[string]string{
"show_only_unhealthy": "false",
"endpoint_search": endpointSearch,
"label_search": labelSearch,
}) %}'">
All
</button>
</div>
<div class="col-auto">
<button type="button" class="btn{% space %}{% if showOnlyUnhealthy %}btn-primary{% else %}btn-secondary{% endif %}" onclick="location.href='?{%= queryArgs(map[string]string{
"show_only_unhealthy": "true",
"endpoint_search": endpointSearch,
"label_search": labelSearch,
}) %}'">
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">
{% if endpointSearch == "" && labelSearch == "" %}
<button type="button" class="btn btn-primary" onclick="document.getElementById('filters').style.display='block'">
Filter targets
</button>
{% else %}
<button type="button" class="btn btn-primary" onclick="location.href='?'">
Clear target filters
</button>
{% endif %}
</div>
</div>
<div style="display:none" id="original_labels_{%s targetID %}">
{%= formatLabel(ts.sw.Config.OriginalLabels) %}
<div id="filters" {% if endpointSearch == "" && labelSearch == "" %}style="display:none"{% endif %}>
<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="{%s endpointSearch %}"/>
</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="{%s labelSearch %}"/>
</div>
</div>
<input type="hidden" name="show_only_unhealthy" value="{%v showOnlyUnhealthy %}"/>
<button type="submit" class="btn btn-success mb-3">Submit</button>
</form>
</div>
<hr />
<div class="row">
<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>
{%s js.job %}{% space %}({%d js.upCount %}/{%d js.targetsTotal %}{% space %}up)
</h4>
<div class="row mb-2">
<div class="col-12">
<button type="button" class="btn btn-primary me-1"
onclick="document.getElementById('table-{%d i %}').style.display='none'">collapse
</button>
<button type="button" class="btn btn-secondary me-1"
onclick="document.getElementById('table-{%d i %}').style.display='block'">expand
</button>
</div>
</div>
<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>
</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>
{% endfor %}
{% 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>
{% 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>
</div>
</div>
{% endfor %}
</body>
</html>
{% endfunc %}
{% func queryArgs(m map[string]string) %}
{% code
qa := make(url.Values, len(m))
for k, v := range m {
qa[k] = []string{v}
}
%}
{%s qa.Encode() %}
{% endfunc %}
{% func formatLabel(labels []prompbmarshal.Label) %}
{
{% for i, label := range labels %}
@ -175,4 +268,14 @@ function expand_all() {
}
{% endfunc %}
{% func errorNotification(err error) %}
<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>
{%s err.Error() %}
</div>
</div>
{% endfunc %}
{% endstripspace %}

View file

@ -8,467 +8,626 @@ package promscrape
import (
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
"net/url"
"time"
)
//line lib/promscrape/targetstatus.qtpl:9
//line lib/promscrape/targetstatus.qtpl:10
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line lib/promscrape/targetstatus.qtpl:9
//line lib/promscrape/targetstatus.qtpl:10
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line lib/promscrape/targetstatus.qtpl:9
func StreamTargetsResponsePlain(qw422016 *qt422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels bool) {
//line lib/promscrape/targetstatus.qtpl:11
for _, js := range jts {
//line lib/promscrape/targetstatus.qtpl:11
qw422016.N().S(`job=`)
//line lib/promscrape/targetstatus.qtpl:10
func StreamTargetsResponsePlain(qw422016 *qt422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels, showOnlyUnhealthy bool, err error) {
//line lib/promscrape/targetstatus.qtpl:12
qw422016.N().Q(js.job)
//line lib/promscrape/targetstatus.qtpl:12
qw422016.N().S(`(`)
//line lib/promscrape/targetstatus.qtpl:12
qw422016.N().D(js.upCount)
//line lib/promscrape/targetstatus.qtpl:12
qw422016.N().S(`/`)
//line lib/promscrape/targetstatus.qtpl:12
qw422016.N().D(js.targetsTotal)
//line lib/promscrape/targetstatus.qtpl:12
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:12
qw422016.N().S(`up)`)
if err != nil {
//line lib/promscrape/targetstatus.qtpl:13
qw422016.N().S(err.Error())
//line lib/promscrape/targetstatus.qtpl:14
return
//line lib/promscrape/targetstatus.qtpl:15
}
//line lib/promscrape/targetstatus.qtpl:17
for _, js := range jts {
//line lib/promscrape/targetstatus.qtpl:18
if showOnlyUnhealthy && js.upCount == js.targetsTotal {
//line lib/promscrape/targetstatus.qtpl:18
continue
//line lib/promscrape/targetstatus.qtpl:18
}
//line lib/promscrape/targetstatus.qtpl:18
qw422016.N().S(`job=`)
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().Q(js.job)
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().S(`(`)
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().D(js.upCount)
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().S(`/`)
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().D(js.targetsTotal)
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().S(`up)`)
//line lib/promscrape/targetstatus.qtpl:20
qw422016.N().S(`
`)
//line lib/promscrape/targetstatus.qtpl:14
//line lib/promscrape/targetstatus.qtpl:21
for _, ts := range js.targetsStatus {
//line lib/promscrape/targetstatus.qtpl:15
//line lib/promscrape/targetstatus.qtpl:22
if showOnlyUnhealthy && ts.up {
//line lib/promscrape/targetstatus.qtpl:22
continue
//line lib/promscrape/targetstatus.qtpl:22
}
//line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S("\t")
//line lib/promscrape/targetstatus.qtpl:15
//line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S(`state=`)
//line lib/promscrape/targetstatus.qtpl:16
//line lib/promscrape/targetstatus.qtpl:24
if ts.up {
//line lib/promscrape/targetstatus.qtpl:16
//line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(`up`)
//line lib/promscrape/targetstatus.qtpl:16
//line lib/promscrape/targetstatus.qtpl:24
} else {
//line lib/promscrape/targetstatus.qtpl:16
//line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(`down`)
//line lib/promscrape/targetstatus.qtpl:16
//line lib/promscrape/targetstatus.qtpl:24
}
//line lib/promscrape/targetstatus.qtpl:16
//line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:16
//line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:16
//line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(`endpoint=`)
//line lib/promscrape/targetstatus.qtpl:17
//line lib/promscrape/targetstatus.qtpl:25
qw422016.N().S(ts.sw.Config.ScrapeURL)
//line lib/promscrape/targetstatus.qtpl:17
//line lib/promscrape/targetstatus.qtpl:25
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:17
//line lib/promscrape/targetstatus.qtpl:25
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:17
//line lib/promscrape/targetstatus.qtpl:25
qw422016.N().S(`labels=`)
//line lib/promscrape/targetstatus.qtpl:18
qw422016.N().S(promLabelsString(promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels)))
//line lib/promscrape/targetstatus.qtpl:18
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:18
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:19
if showOriginLabels {
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().S(`originalLabels=`)
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().S(promLabelsString(ts.sw.Config.OriginalLabels))
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:19
}
//line lib/promscrape/targetstatus.qtpl:19
qw422016.N().S(`scrapes_total=`)
//line lib/promscrape/targetstatus.qtpl:20
qw422016.N().D(ts.scrapesTotal)
//line lib/promscrape/targetstatus.qtpl:20
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:20
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:20
qw422016.N().S(`scrapes_failed=`)
//line lib/promscrape/targetstatus.qtpl:21
qw422016.N().D(ts.scrapesFailed)
//line lib/promscrape/targetstatus.qtpl:21
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:21
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:21
qw422016.N().S(`last_scrape=`)
//line lib/promscrape/targetstatus.qtpl:22
qw422016.N().FPrec(ts.getDurationFromLastScrape().Seconds(), 3)
//line lib/promscrape/targetstatus.qtpl:22
qw422016.N().S(`s ago,`)
//line lib/promscrape/targetstatus.qtpl:22
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:22
qw422016.N().S(`scrape_duration=`)
//line lib/promscrape/targetstatus.qtpl:23
qw422016.N().D(int(ts.scrapeDuration))
//line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S(`ms,`)
//line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:23
qw422016.N().S(`samples_scraped=`)
//line lib/promscrape/targetstatus.qtpl:24
qw422016.N().D(ts.samplesScraped)
//line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:24
qw422016.N().S(`error=`)
//line lib/promscrape/targetstatus.qtpl:25
if ts.err != nil {
//line lib/promscrape/targetstatus.qtpl:25
qw422016.N().S(ts.err.Error())
//line lib/promscrape/targetstatus.qtpl:25
}
//line lib/promscrape/targetstatus.qtpl:26
qw422016.N().S(promLabelsString(promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels)))
//line lib/promscrape/targetstatus.qtpl:26
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:26
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:27
if showOriginLabels {
//line lib/promscrape/targetstatus.qtpl:27
qw422016.N().S(`originalLabels=`)
//line lib/promscrape/targetstatus.qtpl:27
qw422016.N().S(promLabelsString(ts.sw.Config.OriginalLabels))
//line lib/promscrape/targetstatus.qtpl:27
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:27
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:27
}
//line lib/promscrape/targetstatus.qtpl:27
qw422016.N().S(`scrapes_total=`)
//line lib/promscrape/targetstatus.qtpl:28
qw422016.N().D(ts.scrapesTotal)
//line lib/promscrape/targetstatus.qtpl:28
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:28
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:28
qw422016.N().S(`scrapes_failed=`)
//line lib/promscrape/targetstatus.qtpl:29
qw422016.N().D(ts.scrapesFailed)
//line lib/promscrape/targetstatus.qtpl:29
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:29
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:29
qw422016.N().S(`last_scrape=`)
//line lib/promscrape/targetstatus.qtpl:30
qw422016.N().FPrec(ts.getDurationFromLastScrape().Seconds(), 3)
//line lib/promscrape/targetstatus.qtpl:30
qw422016.N().S(`s ago,`)
//line lib/promscrape/targetstatus.qtpl:30
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:30
qw422016.N().S(`scrape_duration=`)
//line lib/promscrape/targetstatus.qtpl:31
qw422016.N().D(int(ts.scrapeDuration))
//line lib/promscrape/targetstatus.qtpl:31
qw422016.N().S(`ms,`)
//line lib/promscrape/targetstatus.qtpl:31
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:31
qw422016.N().S(`samples_scraped=`)
//line lib/promscrape/targetstatus.qtpl:32
qw422016.N().D(ts.samplesScraped)
//line lib/promscrape/targetstatus.qtpl:32
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:32
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:32
qw422016.N().S(`error=`)
//line lib/promscrape/targetstatus.qtpl:33
if ts.err != nil {
//line lib/promscrape/targetstatus.qtpl:33
qw422016.N().S(ts.err.Error())
//line lib/promscrape/targetstatus.qtpl:33
}
//line lib/promscrape/targetstatus.qtpl:34
qw422016.N().S(`
`)
//line lib/promscrape/targetstatus.qtpl:27
//line lib/promscrape/targetstatus.qtpl:35
}
//line lib/promscrape/targetstatus.qtpl:28
//line lib/promscrape/targetstatus.qtpl:36
}
//line lib/promscrape/targetstatus.qtpl:30
//line lib/promscrape/targetstatus.qtpl:38
for _, jobName := range emptyJobs {
//line lib/promscrape/targetstatus.qtpl:30
//line lib/promscrape/targetstatus.qtpl:38
qw422016.N().S(`job=`)
//line lib/promscrape/targetstatus.qtpl:31
//line lib/promscrape/targetstatus.qtpl:39
qw422016.N().Q(jobName)
//line lib/promscrape/targetstatus.qtpl:31
//line lib/promscrape/targetstatus.qtpl:39
qw422016.N().S(`(0/0 up)`)
//line lib/promscrape/targetstatus.qtpl:32
//line lib/promscrape/targetstatus.qtpl:40
qw422016.N().S(`
`)
//line lib/promscrape/targetstatus.qtpl:33
//line lib/promscrape/targetstatus.qtpl:41
}
//line lib/promscrape/targetstatus.qtpl:35
//line lib/promscrape/targetstatus.qtpl:43
}
//line lib/promscrape/targetstatus.qtpl:35
func WriteTargetsResponsePlain(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels bool) {
//line lib/promscrape/targetstatus.qtpl:35
//line lib/promscrape/targetstatus.qtpl:43
func WriteTargetsResponsePlain(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels, showOnlyUnhealthy bool, err error) {
//line lib/promscrape/targetstatus.qtpl:43
qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targetstatus.qtpl:35
StreamTargetsResponsePlain(qw422016, jts, emptyJobs, showOriginLabels)
//line lib/promscrape/targetstatus.qtpl:35
//line lib/promscrape/targetstatus.qtpl:43
StreamTargetsResponsePlain(qw422016, jts, emptyJobs, showOriginLabels, showOnlyUnhealthy, err)
//line lib/promscrape/targetstatus.qtpl:43
qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targetstatus.qtpl:35
//line lib/promscrape/targetstatus.qtpl:43
}
//line lib/promscrape/targetstatus.qtpl:35
func TargetsResponsePlain(jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels bool) string {
//line lib/promscrape/targetstatus.qtpl:35
//line lib/promscrape/targetstatus.qtpl:43
func TargetsResponsePlain(jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels, showOnlyUnhealthy bool, err error) string {
//line lib/promscrape/targetstatus.qtpl:43
qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targetstatus.qtpl:35
WriteTargetsResponsePlain(qb422016, jts, emptyJobs, showOriginLabels)
//line lib/promscrape/targetstatus.qtpl:35
//line lib/promscrape/targetstatus.qtpl:43
WriteTargetsResponsePlain(qb422016, jts, emptyJobs, showOriginLabels, showOnlyUnhealthy, err)
//line lib/promscrape/targetstatus.qtpl:43
qs422016 := string(qb422016.B)
//line lib/promscrape/targetstatus.qtpl:35
//line lib/promscrape/targetstatus.qtpl:43
qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targetstatus.qtpl:35
//line lib/promscrape/targetstatus.qtpl:43
return qs422016
//line lib/promscrape/targetstatus.qtpl:35
//line lib/promscrape/targetstatus.qtpl:43
}
//line lib/promscrape/targetstatus.qtpl:37
func StreamTargetsResponseHTML(qw422016 *qt422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, onlyUnhealthy bool) {
//line lib/promscrape/targetstatus.qtpl:37
//line lib/promscrape/targetstatus.qtpl:45
func StreamTargetsResponseHTML(qw422016 *qt422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, endpointSearch, labelSearch string, err error) {
//line lib/promscrape/targetstatus.qtpl:45
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="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"><title>Scrape targets</title><script>function collapse_all() {for (var i = 0; i <`)
//line lib/promscrape/targetstatus.qtpl:47
//line lib/promscrape/targetstatus.qtpl:55
qw422016.N().D(len(jts))
//line lib/promscrape/targetstatus.qtpl:47
//line lib/promscrape/targetstatus.qtpl:55
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:56
//line lib/promscrape/targetstatus.qtpl:64
qw422016.N().D(len(jts))
//line lib/promscrape/targetstatus.qtpl:56
qw422016.N().S(`; i++) {let el = document.getElementById("table-" + i);if (!el) {continue;}el.style.display = 'block';}}</script></head><body class="m-3"><h1>Scrape targets</h1><div style="padding: 3px"><button type="button" class="btn`)
//line lib/promscrape/targetstatus.qtpl:69
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:69
if !onlyUnhealthy {
//line lib/promscrape/targetstatus.qtpl:69
qw422016.N().S(`btn-primary`)
//line lib/promscrape/targetstatus.qtpl:69
} else {
//line lib/promscrape/targetstatus.qtpl:69
qw422016.N().S(`btn-secondary`)
//line lib/promscrape/targetstatus.qtpl:69
//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 class="py-3"><div class="container-fluid">`)
//line lib/promscrape/targetstatus.qtpl:76
if err != nil {
//line lib/promscrape/targetstatus.qtpl:77
streamerrorNotification(qw422016, err)
//line lib/promscrape/targetstatus.qtpl:78
}
//line lib/promscrape/targetstatus.qtpl:69
qw422016.N().S(`" onclick="location.href='targets'">All</button><button type="button" class="btn`)
//line lib/promscrape/targetstatus.qtpl:72
//line lib/promscrape/targetstatus.qtpl:78
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:85
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:72
if onlyUnhealthy {
//line lib/promscrape/targetstatus.qtpl:72
//line lib/promscrape/targetstatus.qtpl:85
if !showOnlyUnhealthy {
//line lib/promscrape/targetstatus.qtpl:85
qw422016.N().S(`btn-primary`)
//line lib/promscrape/targetstatus.qtpl:72
//line lib/promscrape/targetstatus.qtpl:85
} else {
//line lib/promscrape/targetstatus.qtpl:72
//line lib/promscrape/targetstatus.qtpl:85
qw422016.N().S(`btn-secondary`)
//line lib/promscrape/targetstatus.qtpl:72
//line lib/promscrape/targetstatus.qtpl:85
}
//line lib/promscrape/targetstatus.qtpl:72
qw422016.N().S(`" onclick="location.href='targets?show_only_unhealthy=true'">Unhealthy</button><button type="button" class="btn btn-primary" onclick="collapse_all()">Collapse all</button><button type="button" class="btn btn-secondary" onclick="expand_all()">Expand all</button></div>`)
//line lib/promscrape/targetstatus.qtpl:82
//line lib/promscrape/targetstatus.qtpl:85
qw422016.N().S(`" onclick="location.href='?`)
//line lib/promscrape/targetstatus.qtpl:85
streamqueryArgs(qw422016, map[string]string{
"show_only_unhealthy": "false",
"endpoint_search": endpointSearch,
"label_search": labelSearch,
})
//line lib/promscrape/targetstatus.qtpl:89
qw422016.N().S(`'">All</button></div><div class="col-auto"><button type="button" class="btn`)
//line lib/promscrape/targetstatus.qtpl:94
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:94
if showOnlyUnhealthy {
//line lib/promscrape/targetstatus.qtpl:94
qw422016.N().S(`btn-primary`)
//line lib/promscrape/targetstatus.qtpl:94
} else {
//line lib/promscrape/targetstatus.qtpl:94
qw422016.N().S(`btn-secondary`)
//line lib/promscrape/targetstatus.qtpl:94
}
//line lib/promscrape/targetstatus.qtpl:94
qw422016.N().S(`" onclick="location.href='?`)
//line lib/promscrape/targetstatus.qtpl:94
streamqueryArgs(qw422016, map[string]string{
"show_only_unhealthy": "true",
"endpoint_search": endpointSearch,
"label_search": labelSearch,
})
//line lib/promscrape/targetstatus.qtpl:98
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:113
if endpointSearch == "" && labelSearch == "" {
//line lib/promscrape/targetstatus.qtpl:113
qw422016.N().S(`<button type="button" class="btn btn-primary" onclick="document.getElementById('filters').style.display='block'">Filter targets</button>`)
//line lib/promscrape/targetstatus.qtpl:117
} else {
//line lib/promscrape/targetstatus.qtpl:117
qw422016.N().S(`<button type="button" class="btn btn-primary" onclick="location.href='?'">Clear target filters</button>`)
//line lib/promscrape/targetstatus.qtpl:121
}
//line lib/promscrape/targetstatus.qtpl:121
qw422016.N().S(`</div></div><div id="filters"`)
//line lib/promscrape/targetstatus.qtpl:124
if endpointSearch == "" && labelSearch == "" {
//line lib/promscrape/targetstatus.qtpl:124
qw422016.N().S(`style="display:none"`)
//line lib/promscrape/targetstatus.qtpl:124
}
//line lib/promscrape/targetstatus.qtpl:124
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:130
qw422016.E().S(endpointSearch)
//line lib/promscrape/targetstatus.qtpl:130
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:137
qw422016.E().S(labelSearch)
//line lib/promscrape/targetstatus.qtpl:137
qw422016.N().S(`"/></div></div><input type="hidden" name="show_only_unhealthy" value="`)
//line lib/promscrape/targetstatus.qtpl:140
qw422016.E().V(showOnlyUnhealthy)
//line lib/promscrape/targetstatus.qtpl:140
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:147
for i, js := range jts {
//line lib/promscrape/targetstatus.qtpl:83
if onlyUnhealthy && js.upCount == js.targetsTotal {
//line lib/promscrape/targetstatus.qtpl:83
//line lib/promscrape/targetstatus.qtpl:148
if showOnlyUnhealthy && js.upCount == js.targetsTotal {
//line lib/promscrape/targetstatus.qtpl:148
continue
//line lib/promscrape/targetstatus.qtpl:83
//line lib/promscrape/targetstatus.qtpl:148
}
//line lib/promscrape/targetstatus.qtpl:83
qw422016.N().S(`<div><h4>`)
//line lib/promscrape/targetstatus.qtpl:86
//line lib/promscrape/targetstatus.qtpl:148
qw422016.N().S(`<div class="row mb-4"><div class="col-12"><h4>`)
//line lib/promscrape/targetstatus.qtpl:152
qw422016.E().S(js.job)
//line lib/promscrape/targetstatus.qtpl:86
//line lib/promscrape/targetstatus.qtpl:152
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:86
//line lib/promscrape/targetstatus.qtpl:152
qw422016.N().S(`(`)
//line lib/promscrape/targetstatus.qtpl:86
//line lib/promscrape/targetstatus.qtpl:152
qw422016.N().D(js.upCount)
//line lib/promscrape/targetstatus.qtpl:86
//line lib/promscrape/targetstatus.qtpl:152
qw422016.N().S(`/`)
//line lib/promscrape/targetstatus.qtpl:86
//line lib/promscrape/targetstatus.qtpl:152
qw422016.N().D(js.targetsTotal)
//line lib/promscrape/targetstatus.qtpl:86
//line lib/promscrape/targetstatus.qtpl:152
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:86
qw422016.N().S(`up)<button type="button" class="btn btn-primary" onclick="document.getElementById('table-`)
//line lib/promscrape/targetstatus.qtpl:87
//line lib/promscrape/targetstatus.qtpl:152
qw422016.N().S(`up)</h4><div class="row mb-2"><div class="col-12"><button type="button" class="btn btn-primary me-1"onclick="document.getElementById('table-`)
//line lib/promscrape/targetstatus.qtpl:157
qw422016.N().D(i)
//line lib/promscrape/targetstatus.qtpl:87
qw422016.N().S(`').style.display='none'">collapse</button><button type="button" class="btn btn-secondary" onclick="document.getElementById('table-`)
//line lib/promscrape/targetstatus.qtpl:88
//line lib/promscrape/targetstatus.qtpl:157
qw422016.N().S(`').style.display='none'">collapse</button><button type="button" class="btn btn-secondary me-1"onclick="document.getElementById('table-`)
//line lib/promscrape/targetstatus.qtpl:160
qw422016.N().D(i)
//line lib/promscrape/targetstatus.qtpl:88
qw422016.N().S(`').style.display='block'">expand</button></h4><div id="table-`)
//line lib/promscrape/targetstatus.qtpl:90
//line lib/promscrape/targetstatus.qtpl:160
qw422016.N().S(`').style.display='block'">expand</button></div></div><div id="table-`)
//line lib/promscrape/targetstatus.qtpl:164
qw422016.N().D(i)
//line lib/promscrape/targetstatus.qtpl:90
qw422016.N().S(`"><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>`)
//line lib/promscrape/targetstatus.qtpl:106
//line lib/promscrape/targetstatus.qtpl:164
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:179
qw422016.N().D(i)
//line lib/promscrape/targetstatus.qtpl:179
qw422016.N().S(`">`)
//line lib/promscrape/targetstatus.qtpl:180
for _, ts := range js.targetsStatus {
//line lib/promscrape/targetstatus.qtpl:108
//line lib/promscrape/targetstatus.qtpl:182
endpoint := ts.sw.Config.ScrapeURL
targetID := getTargetID(ts.sw)
lastScrapeTime := ts.getDurationFromLastScrape()
//line lib/promscrape/targetstatus.qtpl:112
if onlyUnhealthy && ts.up {
//line lib/promscrape/targetstatus.qtpl:112
//line lib/promscrape/targetstatus.qtpl:186
if showOnlyUnhealthy && ts.up {
//line lib/promscrape/targetstatus.qtpl:186
continue
//line lib/promscrape/targetstatus.qtpl:112
//line lib/promscrape/targetstatus.qtpl:186
}
//line lib/promscrape/targetstatus.qtpl:112
//line lib/promscrape/targetstatus.qtpl:186
qw422016.N().S(`<tr`)
//line lib/promscrape/targetstatus.qtpl:113
//line lib/promscrape/targetstatus.qtpl:187
if !ts.up {
//line lib/promscrape/targetstatus.qtpl:113
//line lib/promscrape/targetstatus.qtpl:187
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:113
//line lib/promscrape/targetstatus.qtpl:187
qw422016.N().S(`class="alert alert-danger" role="alert"`)
//line lib/promscrape/targetstatus.qtpl:113
//line lib/promscrape/targetstatus.qtpl:187
}
//line lib/promscrape/targetstatus.qtpl:113
qw422016.N().S(`><td><a href="`)
//line lib/promscrape/targetstatus.qtpl:114
//line lib/promscrape/targetstatus.qtpl:187
qw422016.N().S(`><td class="endpoint"><a href="`)
//line lib/promscrape/targetstatus.qtpl:188
qw422016.E().S(endpoint)
//line lib/promscrape/targetstatus.qtpl:114
//line lib/promscrape/targetstatus.qtpl:188
qw422016.N().S(`" target="_blank">`)
//line lib/promscrape/targetstatus.qtpl:114
//line lib/promscrape/targetstatus.qtpl:188
qw422016.E().S(endpoint)
//line lib/promscrape/targetstatus.qtpl:114
//line lib/promscrape/targetstatus.qtpl:188
qw422016.N().S(`</a> (<a href="target_response?id=`)
//line lib/promscrape/targetstatus.qtpl:115
//line lib/promscrape/targetstatus.qtpl:189
qw422016.E().S(targetID)
//line lib/promscrape/targetstatus.qtpl:115
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:117
//line lib/promscrape/targetstatus.qtpl:189
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:193
if ts.up {
//line lib/promscrape/targetstatus.qtpl:117
//line lib/promscrape/targetstatus.qtpl:193
qw422016.N().S(`UP`)
//line lib/promscrape/targetstatus.qtpl:117
//line lib/promscrape/targetstatus.qtpl:193
} else {
//line lib/promscrape/targetstatus.qtpl:117
//line lib/promscrape/targetstatus.qtpl:193
qw422016.N().S(`DOWN`)
//line lib/promscrape/targetstatus.qtpl:117
//line lib/promscrape/targetstatus.qtpl:193
}
//line lib/promscrape/targetstatus.qtpl:117
qw422016.N().S(`</td><td><div title="click to show original labels" onclick="document.getElementById('original_labels_`)
//line lib/promscrape/targetstatus.qtpl:119
//line lib/promscrape/targetstatus.qtpl:193
qw422016.N().S(`</td><td class="labels"><div title="click to show original labels"onclick="document.getElementById('original_labels_`)
//line lib/promscrape/targetstatus.qtpl:196
qw422016.E().S(targetID)
//line lib/promscrape/targetstatus.qtpl:119
//line lib/promscrape/targetstatus.qtpl:196
qw422016.N().S(`').style.display='block'">`)
//line lib/promscrape/targetstatus.qtpl:120
//line lib/promscrape/targetstatus.qtpl:197
streamformatLabel(qw422016, promrelabel.FinalizeLabels(nil, ts.sw.Config.Labels))
//line lib/promscrape/targetstatus.qtpl:120
//line lib/promscrape/targetstatus.qtpl:197
qw422016.N().S(`</div><div style="display:none" id="original_labels_`)
//line lib/promscrape/targetstatus.qtpl:122
//line lib/promscrape/targetstatus.qtpl:199
qw422016.E().S(targetID)
//line lib/promscrape/targetstatus.qtpl:122
//line lib/promscrape/targetstatus.qtpl:199
qw422016.N().S(`">`)
//line lib/promscrape/targetstatus.qtpl:123
//line lib/promscrape/targetstatus.qtpl:200
streamformatLabel(qw422016, ts.sw.Config.OriginalLabels)
//line lib/promscrape/targetstatus.qtpl:123
//line lib/promscrape/targetstatus.qtpl:200
qw422016.N().S(`</div></td><td>`)
//line lib/promscrape/targetstatus.qtpl:126
//line lib/promscrape/targetstatus.qtpl:203
qw422016.N().D(ts.scrapesTotal)
//line lib/promscrape/targetstatus.qtpl:126
//line lib/promscrape/targetstatus.qtpl:203
qw422016.N().S(`</td><td>`)
//line lib/promscrape/targetstatus.qtpl:127
//line lib/promscrape/targetstatus.qtpl:204
qw422016.N().D(ts.scrapesFailed)
//line lib/promscrape/targetstatus.qtpl:127
//line lib/promscrape/targetstatus.qtpl:204
qw422016.N().S(`</td><td>`)
//line lib/promscrape/targetstatus.qtpl:129
//line lib/promscrape/targetstatus.qtpl:206
if lastScrapeTime < 365*24*time.Hour {
//line lib/promscrape/targetstatus.qtpl:130
//line lib/promscrape/targetstatus.qtpl:207
qw422016.N().FPrec(lastScrapeTime.Seconds(), 3)
//line lib/promscrape/targetstatus.qtpl:130
//line lib/promscrape/targetstatus.qtpl:207
qw422016.N().S(`s ago`)
//line lib/promscrape/targetstatus.qtpl:131
//line lib/promscrape/targetstatus.qtpl:208
} else {
//line lib/promscrape/targetstatus.qtpl:131
//line lib/promscrape/targetstatus.qtpl:208
qw422016.N().S(`none`)
//line lib/promscrape/targetstatus.qtpl:133
//line lib/promscrape/targetstatus.qtpl:210
}
//line lib/promscrape/targetstatus.qtpl:133
//line lib/promscrape/targetstatus.qtpl:210
qw422016.N().S(`<td>`)
//line lib/promscrape/targetstatus.qtpl:134
//line lib/promscrape/targetstatus.qtpl:211
qw422016.N().D(int(ts.scrapeDuration))
//line lib/promscrape/targetstatus.qtpl:134
//line lib/promscrape/targetstatus.qtpl:211
qw422016.N().S(`ms</td><td>`)
//line lib/promscrape/targetstatus.qtpl:135
//line lib/promscrape/targetstatus.qtpl:212
qw422016.N().D(ts.samplesScraped)
//line lib/promscrape/targetstatus.qtpl:135
//line lib/promscrape/targetstatus.qtpl:212
qw422016.N().S(`</td><td>`)
//line lib/promscrape/targetstatus.qtpl:136
//line lib/promscrape/targetstatus.qtpl:213
if ts.err != nil {
//line lib/promscrape/targetstatus.qtpl:136
//line lib/promscrape/targetstatus.qtpl:213
qw422016.E().S(ts.err.Error())
//line lib/promscrape/targetstatus.qtpl:136
//line lib/promscrape/targetstatus.qtpl:213
}
//line lib/promscrape/targetstatus.qtpl:136
//line lib/promscrape/targetstatus.qtpl:213
qw422016.N().S(`</td></tr>`)
//line lib/promscrape/targetstatus.qtpl:138
//line lib/promscrape/targetstatus.qtpl:215
}
//line lib/promscrape/targetstatus.qtpl:138
qw422016.N().S(`</tbody></table></div></div>`)
//line lib/promscrape/targetstatus.qtpl:143
//line lib/promscrape/targetstatus.qtpl:215
qw422016.N().S(`</tbody></table></div></div></div>`)
//line lib/promscrape/targetstatus.qtpl:221
}
//line lib/promscrape/targetstatus.qtpl:145
//line lib/promscrape/targetstatus.qtpl:221
qw422016.N().S(`</div></div>`)
//line lib/promscrape/targetstatus.qtpl:225
for _, jobName := range emptyJobs {
//line lib/promscrape/targetstatus.qtpl:145
//line lib/promscrape/targetstatus.qtpl:225
qw422016.N().S(`<div><h4><a>`)
//line lib/promscrape/targetstatus.qtpl:148
//line lib/promscrape/targetstatus.qtpl:228
qw422016.E().S(jobName)
//line lib/promscrape/targetstatus.qtpl:148
//line lib/promscrape/targetstatus.qtpl:228
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:164
//line lib/promscrape/targetstatus.qtpl:244
}
//line lib/promscrape/targetstatus.qtpl:164
qw422016.N().S(`</body></html>`)
//line lib/promscrape/targetstatus.qtpl:167
//line lib/promscrape/targetstatus.qtpl:244
qw422016.N().S(`</main></div></div></body></html>`)
//line lib/promscrape/targetstatus.qtpl:250
}
//line lib/promscrape/targetstatus.qtpl:167
func WriteTargetsResponseHTML(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, onlyUnhealthy bool) {
//line lib/promscrape/targetstatus.qtpl:167
//line lib/promscrape/targetstatus.qtpl:250
func WriteTargetsResponseHTML(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, endpointSearch, labelSearch string, err error) {
//line lib/promscrape/targetstatus.qtpl:250
qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targetstatus.qtpl:167
StreamTargetsResponseHTML(qw422016, jts, emptyJobs, onlyUnhealthy)
//line lib/promscrape/targetstatus.qtpl:167
//line lib/promscrape/targetstatus.qtpl:250
StreamTargetsResponseHTML(qw422016, jts, emptyJobs, showOnlyUnhealthy, endpointSearch, labelSearch, err)
//line lib/promscrape/targetstatus.qtpl:250
qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targetstatus.qtpl:167
//line lib/promscrape/targetstatus.qtpl:250
}
//line lib/promscrape/targetstatus.qtpl:167
func TargetsResponseHTML(jts []jobTargetsStatuses, emptyJobs []string, onlyUnhealthy bool) string {
//line lib/promscrape/targetstatus.qtpl:167
//line lib/promscrape/targetstatus.qtpl:250
func TargetsResponseHTML(jts []jobTargetsStatuses, emptyJobs []string, showOnlyUnhealthy bool, endpointSearch, labelSearch string, err error) string {
//line lib/promscrape/targetstatus.qtpl:250
qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targetstatus.qtpl:167
WriteTargetsResponseHTML(qb422016, jts, emptyJobs, onlyUnhealthy)
//line lib/promscrape/targetstatus.qtpl:167
//line lib/promscrape/targetstatus.qtpl:250
WriteTargetsResponseHTML(qb422016, jts, emptyJobs, showOnlyUnhealthy, endpointSearch, labelSearch, err)
//line lib/promscrape/targetstatus.qtpl:250
qs422016 := string(qb422016.B)
//line lib/promscrape/targetstatus.qtpl:167
//line lib/promscrape/targetstatus.qtpl:250
qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targetstatus.qtpl:167
//line lib/promscrape/targetstatus.qtpl:250
return qs422016
//line lib/promscrape/targetstatus.qtpl:167
//line lib/promscrape/targetstatus.qtpl:250
}
//line lib/promscrape/targetstatus.qtpl:169
//line lib/promscrape/targetstatus.qtpl:252
func streamqueryArgs(qw422016 *qt422016.Writer, m map[string]string) {
//line lib/promscrape/targetstatus.qtpl:254
qa := make(url.Values, len(m))
for k, v := range m {
qa[k] = []string{v}
}
//line lib/promscrape/targetstatus.qtpl:259
qw422016.E().S(qa.Encode())
//line lib/promscrape/targetstatus.qtpl:260
}
//line lib/promscrape/targetstatus.qtpl:260
func writequeryArgs(qq422016 qtio422016.Writer, m map[string]string) {
//line lib/promscrape/targetstatus.qtpl:260
qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targetstatus.qtpl:260
streamqueryArgs(qw422016, m)
//line lib/promscrape/targetstatus.qtpl:260
qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targetstatus.qtpl:260
}
//line lib/promscrape/targetstatus.qtpl:260
func queryArgs(m map[string]string) string {
//line lib/promscrape/targetstatus.qtpl:260
qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targetstatus.qtpl:260
writequeryArgs(qb422016, m)
//line lib/promscrape/targetstatus.qtpl:260
qs422016 := string(qb422016.B)
//line lib/promscrape/targetstatus.qtpl:260
qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targetstatus.qtpl:260
return qs422016
//line lib/promscrape/targetstatus.qtpl:260
}
//line lib/promscrape/targetstatus.qtpl:262
func streamformatLabel(qw422016 *qt422016.Writer, labels []prompbmarshal.Label) {
//line lib/promscrape/targetstatus.qtpl:169
//line lib/promscrape/targetstatus.qtpl:262
qw422016.N().S(`{`)
//line lib/promscrape/targetstatus.qtpl:171
//line lib/promscrape/targetstatus.qtpl:264
for i, label := range labels {
//line lib/promscrape/targetstatus.qtpl:172
//line lib/promscrape/targetstatus.qtpl:265
qw422016.E().S(label.Name)
//line lib/promscrape/targetstatus.qtpl:172
//line lib/promscrape/targetstatus.qtpl:265
qw422016.N().S(`=`)
//line lib/promscrape/targetstatus.qtpl:172
//line lib/promscrape/targetstatus.qtpl:265
qw422016.E().Q(label.Value)
//line lib/promscrape/targetstatus.qtpl:173
//line lib/promscrape/targetstatus.qtpl:266
if i+1 < len(labels) {
//line lib/promscrape/targetstatus.qtpl:173
//line lib/promscrape/targetstatus.qtpl:266
qw422016.N().S(`,`)
//line lib/promscrape/targetstatus.qtpl:173
//line lib/promscrape/targetstatus.qtpl:266
qw422016.N().S(` `)
//line lib/promscrape/targetstatus.qtpl:173
//line lib/promscrape/targetstatus.qtpl:266
}
//line lib/promscrape/targetstatus.qtpl:174
//line lib/promscrape/targetstatus.qtpl:267
}
//line lib/promscrape/targetstatus.qtpl:174
//line lib/promscrape/targetstatus.qtpl:267
qw422016.N().S(`}`)
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
}
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
func writeformatLabel(qq422016 qtio422016.Writer, labels []prompbmarshal.Label) {
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
streamformatLabel(qw422016, labels)
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
}
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
func formatLabel(labels []prompbmarshal.Label) string {
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
writeformatLabel(qb422016, labels)
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
qs422016 := string(qb422016.B)
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
return qs422016
//line lib/promscrape/targetstatus.qtpl:176
//line lib/promscrape/targetstatus.qtpl:269
}
//line lib/promscrape/targetstatus.qtpl:271
func streamerrorNotification(qw422016 *qt422016.Writer, err error) {
//line lib/promscrape/targetstatus.qtpl:271
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:276
qw422016.E().S(err.Error())
//line lib/promscrape/targetstatus.qtpl:276
qw422016.N().S(`</div></div>`)
//line lib/promscrape/targetstatus.qtpl:279
}
//line lib/promscrape/targetstatus.qtpl:279
func writeerrorNotification(qq422016 qtio422016.Writer, err error) {
//line lib/promscrape/targetstatus.qtpl:279
qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targetstatus.qtpl:279
streamerrorNotification(qw422016, err)
//line lib/promscrape/targetstatus.qtpl:279
qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targetstatus.qtpl:279
}
//line lib/promscrape/targetstatus.qtpl:279
func errorNotification(err error) string {
//line lib/promscrape/targetstatus.qtpl:279
qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targetstatus.qtpl:279
writeerrorNotification(qb422016, err)
//line lib/promscrape/targetstatus.qtpl:279
qs422016 := string(qb422016.B)
//line lib/promscrape/targetstatus.qtpl:279
qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targetstatus.qtpl:279
return qs422016
//line lib/promscrape/targetstatus.qtpl:279
}