lib/promscrape: add ability to show the original labels for discovered targets at /targets page

See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1698
This commit is contained in:
Aliaksandr Valialkin 2021-10-13 15:59:55 +03:00
parent 14995eece6
commit 5b7d90d178
No known key found for this signature in database
GPG Key ID: A72BEC6CD3D0DED1
3 changed files with 102 additions and 66 deletions

View File

@ -7,6 +7,7 @@ sort: 15
## tip ## tip
* FEATURE: vmagent: expose `-promscrape.config` contents at `/config` page as Prometheus does. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1695). * FEATURE: vmagent: expose `-promscrape.config` contents at `/config` page as Prometheus does. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1695).
* FEATURE: vmagent: add `show original labels` button per each scrape target displayed at `http://vmagent;8429/targets` page. This should improve debuggability for service discovery issues similar to [this one](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1664). See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1698).
* FEATURE: vmagent: shard targets among cluster nodes after the relabeling is applied. This should guarantee that targets with the same set of labels go to the same `vmagent` node in the cluster. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1687). * FEATURE: vmagent: shard targets among cluster nodes after the relabeling is applied. This should guarantee that targets with the same set of labels go to the same `vmagent` node in the cluster. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1687).
* FEATURE: add trigonometric functions, which are going to be added in [Prometheus 2.31](https://github.com/prometheus/prometheus/pull/9239): [acosh](https://docs.victoriametrics.com/MetricsQL.html#acosh), [asinh](https://docs.victoriametrics.com/MetricsQL.html#asinh), [atan](https://docs.victoriametrics.com/MetricsQL.html#atan), [atanh](https://docs.victoriametrics.com/MetricsQL.html#atanh), [cosh](https://docs.victoriametrics.com/MetricsQL.html#cosh), [deg](https://docs.victoriametrics.com/MetricsQL.html#deg), [rad](https://docs.victoriametrics.com/MetricsQL.html#rad), [sinh](https://docs.victoriametrics.com/MetricsQL.html#sinh), [tan](https://docs.victoriametrics.com/MetricsQL.html#tan), [tanh](https://docs.victoriametrics.com/MetricsQL.html#tanh). Also add `atan2` binary operator. See [this pull request](https://github.com/prometheus/prometheus/pull/9248). * FEATURE: add trigonometric functions, which are going to be added in [Prometheus 2.31](https://github.com/prometheus/prometheus/pull/9239): [acosh](https://docs.victoriametrics.com/MetricsQL.html#acosh), [asinh](https://docs.victoriametrics.com/MetricsQL.html#asinh), [atan](https://docs.victoriametrics.com/MetricsQL.html#atan), [atanh](https://docs.victoriametrics.com/MetricsQL.html#atanh), [cosh](https://docs.victoriametrics.com/MetricsQL.html#cosh), [deg](https://docs.victoriametrics.com/MetricsQL.html#deg), [rad](https://docs.victoriametrics.com/MetricsQL.html#rad), [sinh](https://docs.victoriametrics.com/MetricsQL.html#sinh), [tan](https://docs.victoriametrics.com/MetricsQL.html#tan), [tanh](https://docs.victoriametrics.com/MetricsQL.html#tanh). Also add `atan2` binary operator. See [this pull request](https://github.com/prometheus/prometheus/pull/9248).
* FEATURE: consistently return the same set of time series from [limitk](https://docs.victoriametrics.com/MetricsQL.html#limitk) function. This improves the usability of periodically refreshed graphs. * FEATURE: consistently return the same set of time series from [limitk](https://docs.victoriametrics.com/MetricsQL.html#limitk) function. This improves the usability of periodically refreshed graphs.

View File

@ -53,7 +53,7 @@ job={%q= jobName %} (0/0 up)
Unhealthy Unhealthy
</button> </button>
</div> </div>
{% for _, js := range jts %} {% for i, js := range jts %}
{% if onlyUnhealthy && js.upCount == js.targetsTotal %}{% continue %}{% endif %} {% if onlyUnhealthy && js.upCount == js.targetsTotal %}{% continue %}{% endif %}
<div> <div>
<h4> <h4>
@ -72,13 +72,18 @@ job={%q= jobName %} (0/0 up)
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for _, ts := range js.targetsStatus %} {% for j, ts := range js.targetsStatus %}
{% if onlyUnhealthy && ts.up %}{% continue %}{% endif %} {% if onlyUnhealthy && ts.up %}{% continue %}{% endif %}
<tr {% if !ts.up %}{%space%}class="alert alert-danger" role="alert"{% endif %}> <tr {% if !ts.up %}{%space%}class="alert alert-danger" role="alert"{% endif %}>
<td><a href="{%s ts.endpoint %}">{%s ts.endpoint %}</a><br></td> <td><a href="{%s ts.endpoint %}">{%s ts.endpoint %}</a><br></td>
<td>{% if ts.up %}UP{% else %}DOWN{% endif %}</td> <td>{% if ts.up %}UP{% else %}DOWN{% endif %}</td>
<td title="Original labels: {%= formatLabel(ts.originalLabels) %}"> <td>
<button type="button" class="btn btn-sm btn-outline-info" onclick="document.getElementById('original_labels_{%d i %}_{%d j %}').style.display='block'">show original labels</button>{% space %}
{%= formatLabel(ts.labels) %} {%= formatLabel(ts.labels) %}
<div style="display:none" id="original_labels_{%d i %}_{%d j %}">
<button type="button" class="btn btn-sm btn-outline-info" onclick="document.getElementById('original_labels_{%d i %}_{%d j %}').style.display='none'">hide original labels</button>{% space %}
{%= formatLabel(ts.originalLabels) %}
</div>
</td> </td>
<td>{%f.3 ts.lastScrapeTime.Seconds() %}s ago</td> <td>{%f.3 ts.lastScrapeTime.Seconds() %}s ago</td>
<td>{%f.3 ts.scrapeDuration.Seconds() %}s</td> <td>{%f.3 ts.scrapeDuration.Seconds() %}s</td>
@ -119,7 +124,7 @@ job={%q= jobName %} (0/0 up)
{ {
{% for i, label := range labels %} {% for i, label := range labels %}
{%s label.Name %}={%q label.Value %} {%s label.Name %}={%q label.Value %}
{% if i+1 < len(labels) %},{% endif %} {% if i+1 < len(labels) %},{% space %}{% endif %}
{% endfor %} {% endfor %}
} }
{% endfunc %} {% endfunc %}

View File

@ -225,7 +225,7 @@ func StreamTargetsResponseHTML(qw422016 *qt422016.Writer, jts []jobTargetsStatus
//line lib/promscrape/targets_response.qtpl:52 //line lib/promscrape/targets_response.qtpl:52
qw422016.N().S(`>Unhealthy</button></div>`) qw422016.N().S(`>Unhealthy</button></div>`)
//line lib/promscrape/targets_response.qtpl:56 //line lib/promscrape/targets_response.qtpl:56
for _, js := range jts { for i, js := range jts {
//line lib/promscrape/targets_response.qtpl:57 //line lib/promscrape/targets_response.qtpl:57
if onlyUnhealthy && js.upCount == js.targetsTotal { if onlyUnhealthy && js.upCount == js.targetsTotal {
//line lib/promscrape/targets_response.qtpl:57 //line lib/promscrape/targets_response.qtpl:57
@ -247,7 +247,7 @@ func StreamTargetsResponseHTML(qw422016 *qt422016.Writer, jts []jobTargetsStatus
//line lib/promscrape/targets_response.qtpl:60 //line lib/promscrape/targets_response.qtpl:60
qw422016.N().S(`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><tbody>`) qw422016.N().S(`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><tbody>`)
//line lib/promscrape/targets_response.qtpl:75 //line lib/promscrape/targets_response.qtpl:75
for _, ts := range js.targetsStatus { for j, ts := range js.targetsStatus {
//line lib/promscrape/targets_response.qtpl:76 //line lib/promscrape/targets_response.qtpl:76
if onlyUnhealthy && ts.up { if onlyUnhealthy && ts.up {
//line lib/promscrape/targets_response.qtpl:76 //line lib/promscrape/targets_response.qtpl:76
@ -285,125 +285,155 @@ func StreamTargetsResponseHTML(qw422016 *qt422016.Writer, jts []jobTargetsStatus
//line lib/promscrape/targets_response.qtpl:79 //line lib/promscrape/targets_response.qtpl:79
} }
//line lib/promscrape/targets_response.qtpl:79 //line lib/promscrape/targets_response.qtpl:79
qw422016.N().S(`</td><td title="Original labels:`) qw422016.N().S(`</td><td><button type="button" class="btn btn-sm btn-outline-info" onclick="document.getElementById('original_labels_`)
//line lib/promscrape/targets_response.qtpl:80
streamformatLabel(qw422016, ts.originalLabels)
//line lib/promscrape/targets_response.qtpl:80
qw422016.N().S(`">`)
//line lib/promscrape/targets_response.qtpl:81 //line lib/promscrape/targets_response.qtpl:81
qw422016.N().D(i)
//line lib/promscrape/targets_response.qtpl:81
qw422016.N().S(`_`)
//line lib/promscrape/targets_response.qtpl:81
qw422016.N().D(j)
//line lib/promscrape/targets_response.qtpl:81
qw422016.N().S(`').style.display='block'">show original labels</button>`)
//line lib/promscrape/targets_response.qtpl:81
qw422016.N().S(` `)
//line lib/promscrape/targets_response.qtpl:82
streamformatLabel(qw422016, ts.labels) streamformatLabel(qw422016, ts.labels)
//line lib/promscrape/targets_response.qtpl:81 //line lib/promscrape/targets_response.qtpl:82
qw422016.N().S(`</td><td>`) qw422016.N().S(`<div style="display:none" id="original_labels_`)
//line lib/promscrape/targets_response.qtpl:83 //line lib/promscrape/targets_response.qtpl:83
qw422016.N().D(i)
//line lib/promscrape/targets_response.qtpl:83
qw422016.N().S(`_`)
//line lib/promscrape/targets_response.qtpl:83
qw422016.N().D(j)
//line lib/promscrape/targets_response.qtpl:83
qw422016.N().S(`"><button type="button" class="btn btn-sm btn-outline-info" onclick="document.getElementById('original_labels_`)
//line lib/promscrape/targets_response.qtpl:84
qw422016.N().D(i)
//line lib/promscrape/targets_response.qtpl:84
qw422016.N().S(`_`)
//line lib/promscrape/targets_response.qtpl:84
qw422016.N().D(j)
//line lib/promscrape/targets_response.qtpl:84
qw422016.N().S(`').style.display='none'">hide original labels</button>`)
//line lib/promscrape/targets_response.qtpl:84
qw422016.N().S(` `)
//line lib/promscrape/targets_response.qtpl:85
streamformatLabel(qw422016, ts.originalLabels)
//line lib/promscrape/targets_response.qtpl:85
qw422016.N().S(`</div></td><td>`)
//line lib/promscrape/targets_response.qtpl:88
qw422016.N().FPrec(ts.lastScrapeTime.Seconds(), 3) qw422016.N().FPrec(ts.lastScrapeTime.Seconds(), 3)
//line lib/promscrape/targets_response.qtpl:83 //line lib/promscrape/targets_response.qtpl:88
qw422016.N().S(`s ago</td><td>`) qw422016.N().S(`s ago</td><td>`)
//line lib/promscrape/targets_response.qtpl:84 //line lib/promscrape/targets_response.qtpl:89
qw422016.N().FPrec(ts.scrapeDuration.Seconds(), 3) qw422016.N().FPrec(ts.scrapeDuration.Seconds(), 3)
//line lib/promscrape/targets_response.qtpl:84 //line lib/promscrape/targets_response.qtpl:89
qw422016.N().S(`s</td><td>`) qw422016.N().S(`s</td><td>`)
//line lib/promscrape/targets_response.qtpl:85 //line lib/promscrape/targets_response.qtpl:90
qw422016.N().D(ts.samplesScraped) qw422016.N().D(ts.samplesScraped)
//line lib/promscrape/targets_response.qtpl:85 //line lib/promscrape/targets_response.qtpl:90
qw422016.N().S(`</td><td>`) qw422016.N().S(`</td><td>`)
//line lib/promscrape/targets_response.qtpl:86 //line lib/promscrape/targets_response.qtpl:91
qw422016.E().S(ts.errMsg) qw422016.E().S(ts.errMsg)
//line lib/promscrape/targets_response.qtpl:86 //line lib/promscrape/targets_response.qtpl:91
qw422016.N().S(`</td></tr>`) qw422016.N().S(`</td></tr>`)
//line lib/promscrape/targets_response.qtpl:88 //line lib/promscrape/targets_response.qtpl:93
} }
//line lib/promscrape/targets_response.qtpl:88 //line lib/promscrape/targets_response.qtpl:93
qw422016.N().S(`</tbody></table></div>`) qw422016.N().S(`</tbody></table></div>`)
//line lib/promscrape/targets_response.qtpl:92 //line lib/promscrape/targets_response.qtpl:97
} }
//line lib/promscrape/targets_response.qtpl:94 //line lib/promscrape/targets_response.qtpl:99
for _, jobName := range emptyJobs { for _, jobName := range emptyJobs {
//line lib/promscrape/targets_response.qtpl:94 //line lib/promscrape/targets_response.qtpl:99
qw422016.N().S(`<div><h4><a>`) qw422016.N().S(`<div><h4><a>`)
//line lib/promscrape/targets_response.qtpl:97 //line lib/promscrape/targets_response.qtpl:102
qw422016.E().S(jobName) qw422016.E().S(jobName)
//line lib/promscrape/targets_response.qtpl:97 //line lib/promscrape/targets_response.qtpl:102
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>`) 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_response.qtpl:113 //line lib/promscrape/targets_response.qtpl:118
} }
//line lib/promscrape/targets_response.qtpl:113 //line lib/promscrape/targets_response.qtpl:118
qw422016.N().S(`</body></html>`) qw422016.N().S(`</body></html>`)
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
} }
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
func WriteTargetsResponseHTML(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, redirectPath string, onlyUnhealthy bool) { func WriteTargetsResponseHTML(qq422016 qtio422016.Writer, jts []jobTargetsStatuses, emptyJobs []string, redirectPath string, onlyUnhealthy bool) {
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
StreamTargetsResponseHTML(qw422016, jts, emptyJobs, redirectPath, onlyUnhealthy) StreamTargetsResponseHTML(qw422016, jts, emptyJobs, redirectPath, onlyUnhealthy)
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
} }
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
func TargetsResponseHTML(jts []jobTargetsStatuses, emptyJobs []string, redirectPath string, onlyUnhealthy bool) string { func TargetsResponseHTML(jts []jobTargetsStatuses, emptyJobs []string, redirectPath string, onlyUnhealthy bool) string {
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
WriteTargetsResponseHTML(qb422016, jts, emptyJobs, redirectPath, onlyUnhealthy) WriteTargetsResponseHTML(qb422016, jts, emptyJobs, redirectPath, onlyUnhealthy)
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
return qs422016 return qs422016
//line lib/promscrape/targets_response.qtpl:116 //line lib/promscrape/targets_response.qtpl:121
} }
//line lib/promscrape/targets_response.qtpl:118 //line lib/promscrape/targets_response.qtpl:123
func streamformatLabel(qw422016 *qt422016.Writer, labels []prompbmarshal.Label) { func streamformatLabel(qw422016 *qt422016.Writer, labels []prompbmarshal.Label) {
//line lib/promscrape/targets_response.qtpl:118 //line lib/promscrape/targets_response.qtpl:123
qw422016.N().S(`{`) qw422016.N().S(`{`)
//line lib/promscrape/targets_response.qtpl:120 //line lib/promscrape/targets_response.qtpl:125
for i, label := range labels { for i, label := range labels {
//line lib/promscrape/targets_response.qtpl:121 //line lib/promscrape/targets_response.qtpl:126
qw422016.E().S(label.Name) qw422016.E().S(label.Name)
//line lib/promscrape/targets_response.qtpl:121 //line lib/promscrape/targets_response.qtpl:126
qw422016.N().S(`=`) qw422016.N().S(`=`)
//line lib/promscrape/targets_response.qtpl:121 //line lib/promscrape/targets_response.qtpl:126
qw422016.E().Q(label.Value) qw422016.E().Q(label.Value)
//line lib/promscrape/targets_response.qtpl:122 //line lib/promscrape/targets_response.qtpl:127
if i+1 < len(labels) { if i+1 < len(labels) {
//line lib/promscrape/targets_response.qtpl:122 //line lib/promscrape/targets_response.qtpl:127
qw422016.N().S(`,`) qw422016.N().S(`,`)
//line lib/promscrape/targets_response.qtpl:122 //line lib/promscrape/targets_response.qtpl:127
qw422016.N().S(` `)
//line lib/promscrape/targets_response.qtpl:127
} }
//line lib/promscrape/targets_response.qtpl:123 //line lib/promscrape/targets_response.qtpl:128
} }
//line lib/promscrape/targets_response.qtpl:123 //line lib/promscrape/targets_response.qtpl:128
qw422016.N().S(`}`) qw422016.N().S(`}`)
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
} }
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
func writeformatLabel(qq422016 qtio422016.Writer, labels []prompbmarshal.Label) { func writeformatLabel(qq422016 qtio422016.Writer, labels []prompbmarshal.Label) {
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
streamformatLabel(qw422016, labels) streamformatLabel(qw422016, labels)
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
} }
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
func formatLabel(labels []prompbmarshal.Label) string { func formatLabel(labels []prompbmarshal.Label) string {
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
writeformatLabel(qb422016, labels) writeformatLabel(qb422016, labels)
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
return qs422016 return qs422016
//line lib/promscrape/targets_response.qtpl:125 //line lib/promscrape/targets_response.qtpl:130
} }