diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 8e4ea7b22d..f23b9ad170 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -9,6 +9,7 @@ sort: 15 * FEATURE: vmagent: add service discovery for DigitalOcean (aka [digitalocean_sd_config](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#digitalocean_sd_config)). See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1367). * FEATURE: vmagent: show the number of samples the target returned during the last scrape on `/targets` and `/api/v1/targets` pages. This should simplify debugging targets, which may return too big or too low number of samples. See [this feature request](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1377). * FEATURE: vmagent: change the default value for `-remoteWrite.queues` from 4 to `2 * numCPUs`. This should reduce scrape duration for highly loaded vmagent, which scrapes tens of thousands of targets. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/1385). +* FEATURE: vmagent: show jobs with zero discovered targets on `/targets` page. This should help debugging improperly configured scrape configs. * BUGFIX: prevent from adding new samples to deleted time series after the rotation of the inverted index (the rotation is performed once per `-retentionPeriod`). See [this comment](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1347#issuecomment-861232136) for details. diff --git a/lib/promscrape/config.go b/lib/promscrape/config.go index 6316971d1e..02af9abc83 100644 --- a/lib/promscrape/config.go +++ b/lib/promscrape/config.go @@ -67,6 +67,8 @@ func (cfg *Config) mustStart() { for i := range cfg.ScrapeConfigs { cfg.ScrapeConfigs[i].mustStart(cfg.baseDir) } + jobNames := cfg.getJobNames() + tsmGlobal.registerJobNames(jobNames) logger.Infof("started service discovery routines in %.3f seconds", time.Since(startTime).Seconds()) } @@ -79,6 +81,15 @@ func (cfg *Config) mustStop() { logger.Infof("stopped service discovery routines in %.3f seconds", time.Since(startTime).Seconds()) } +// getJobNames returns all the scrape job names from the cfg. +func (cfg *Config) getJobNames() []string { + a := make([]string, 0, len(cfg.ScrapeConfigs)) + for i := range cfg.ScrapeConfigs { + a = append(a, cfg.ScrapeConfigs[i].JobName) + } + return a +} + // GlobalConfig represents essential parts for `global` section of Prometheus config. // // See https://prometheus.io/docs/prometheus/latest/configuration/configuration/ diff --git a/lib/promscrape/targets_response.qtpl b/lib/promscrape/targets_response.qtpl index 6120e3678d..9583130e91 100644 --- a/lib/promscrape/targets_response.qtpl +++ b/lib/promscrape/targets_response.qtpl @@ -1,9 +1,9 @@ {% import "github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal" %} -{% collapsespace %} +{% stripspace %} -{% func TargetsResponsePlain (jts []jobTargetsStatuses, showOriginLabels bool) -%} +{% func TargetsResponsePlain(jts []jobTargetsStatuses, emptyJobs []string, showOriginLabels bool) %} {% for _, js := range jts %} job={%q= js.job %} ({%d js.upCount %}/{%d js.targetsTotal %} up) @@ -13,22 +13,26 @@ job={%q= js.job %} ({%d js.upCount %}/{%d js.targetsTotal %} up) labels := promLabelsString(ts.labels) ol := promLabelsString(ts.originalLabels) %} -{%s= "\t" %}state={% if ts.up %}up{% else %}down{% endif %}, - endpoint={%s= ts.endpoint %}, +{%s= "\t" %}state={% if ts.up %}up{% else %}down{% endif %},{% space %} + endpoint={%s= ts.endpoint %},{ %space %} labels={%s= labels %} - {% if showOriginLabels %}, originalLabels={%s= ol %}{% endif %}, - last_scrape={%f.3 ts.lastScrapeTime.Seconds() %}s ago, - scrape_duration={%f.3 ts.scrapeDuration.Seconds() %}s, - samples_scraped={%d ts.samplesScraped %}, + {% if showOriginLabels %}, originalLabels={%s= ol %}{% endif %},{% space %} + last_scrape={%f.3 ts.lastScrapeTime.Seconds() %}s ago,{% space %} + scrape_duration={%f.3 ts.scrapeDuration.Seconds() %}s,{% space %} + samples_scraped={%d ts.samplesScraped %},{% space %} error={%q= ts.errMsg %} {% newline %} {% endfor %} {% endfor %} + +{% for _, jobName := range emptyJobs %} +job={%q= jobName %} (0/0 up) {% newline %} +{% endfor %} {% endfunc %} -{% func TargetsResponseHTML(jts []jobTargetsStatuses, redirectPath string, onlyUnhealthy bool) %} +{% func TargetsResponseHTML(jts []jobTargetsStatuses, emptyJobs []string, redirectPath string, onlyUnhealthy bool) %}
@@ -49,7 +53,7 @@ job={%q= js.job %} ({%d js.upCount %}/{%d js.targetsTotal %} up) Unhealthy - {% for _,js :=range jts %} + {% for _, js := range jts %} {% if onlyUnhealthy && js.upCount == js.targetsTotal %}{% continue %}{% endif %}Endpoint | +State | +Labels | +Last Scrape | +Scrape Duration | +Samples Scraped | +Error | +
---|
Endpoint | State | Labels | Last Scrape | Scrape Duration | Samples Scraped | Error |
---|
Endpoint | State | Labels | Last Scrape | Scrape Duration | Samples Scraped | Error | |||||
---|---|---|---|---|---|---|---|---|---|---|---|
`)
-//line lib/promscrape/targets_response.qtpl:74
+//line lib/promscrape/targets_response.qtpl:78
qw422016.E().S(ts.endpoint)
-//line lib/promscrape/targets_response.qtpl:74
- qw422016.N().S(` | `)
-//line lib/promscrape/targets_response.qtpl:75
+//line lib/promscrape/targets_response.qtpl:78
+ qw422016.N().S(` | `) +//line lib/promscrape/targets_response.qtpl:79 if ts.up { -//line lib/promscrape/targets_response.qtpl:75 +//line lib/promscrape/targets_response.qtpl:79 qw422016.N().S(`UP`) -//line lib/promscrape/targets_response.qtpl:75 +//line lib/promscrape/targets_response.qtpl:79 } else { -//line lib/promscrape/targets_response.qtpl:75 +//line lib/promscrape/targets_response.qtpl:79 qw422016.N().S(`DOWN`) -//line lib/promscrape/targets_response.qtpl:75 +//line lib/promscrape/targets_response.qtpl:79 } -//line lib/promscrape/targets_response.qtpl:75 - qw422016.N().S(` | `) -//line lib/promscrape/targets_response.qtpl:77 +//line lib/promscrape/targets_response.qtpl:80 + qw422016.N().S(`">`) +//line lib/promscrape/targets_response.qtpl:81 streamformatLabel(qw422016, ts.labels) -//line lib/promscrape/targets_response.qtpl:77 - qw422016.N().S(` | `) -//line lib/promscrape/targets_response.qtpl:79 +//line lib/promscrape/targets_response.qtpl:81 + qw422016.N().S(` | `) +//line lib/promscrape/targets_response.qtpl:83 qw422016.N().FPrec(ts.lastScrapeTime.Seconds(), 3) -//line lib/promscrape/targets_response.qtpl:79 - qw422016.N().S(`s ago | `) -//line lib/promscrape/targets_response.qtpl:80 +//line lib/promscrape/targets_response.qtpl:83 + qw422016.N().S(`s ago | `) +//line lib/promscrape/targets_response.qtpl:84 qw422016.N().FPrec(ts.scrapeDuration.Seconds(), 3) -//line lib/promscrape/targets_response.qtpl:80 - qw422016.N().S(`s | `) -//line lib/promscrape/targets_response.qtpl:81 +//line lib/promscrape/targets_response.qtpl:84 + qw422016.N().S(`s | `) +//line lib/promscrape/targets_response.qtpl:85 qw422016.N().D(ts.samplesScraped) -//line lib/promscrape/targets_response.qtpl:81 - qw422016.N().S(` | `) -//line lib/promscrape/targets_response.qtpl:82 +//line lib/promscrape/targets_response.qtpl:85 + qw422016.N().S(` | `) +//line lib/promscrape/targets_response.qtpl:86 qw422016.E().S(ts.errMsg) -//line lib/promscrape/targets_response.qtpl:82 - qw422016.N().S(` |
Endpoint | State | Labels | Last Scrape | Scrape Duration | Samples Scraped | Error |
---|