From 3c5c932b945475d4b406378cd26fa92af0fbe464 Mon Sep 17 00:00:00 2001 From: Pranshu Srivastava Date: Sun, 24 Mar 2024 11:13:03 +0530 Subject: [PATCH] collector/textfile: Avoid inconsistent help-texts (#2962) Avoid metrics with inconsistent help-texts. The earlier behaviour has been preserved in the sense that the first encountered instance is still used to generate metrics, whereas the subsequent inconsistent ones are ignored along with a few peripheral changes. ``` # HELP node_scrape_collector_duration_seconds node_exporter: Duration of a collector scrape. #TYPE node_scrape_collector_duration_seconds gauge node_scrape_collector_duration_seconds{collector="textfile"} 0.0004005 # HELP node_scrape_collector_success node_exporter: Whether a collector succeeded. # TYPE node_scrape_collector_success gauge node_scrape_collector_success{collector="textfile"} 1 # HELP node_textfile_mtime_seconds Unixtime mtime of textfiles successfully read. # TYPE node_textfile_mtime_seconds gauge node_textfile_mtime_seconds{file="/Users/rexagod/repositories/misc/node_exporter/ne-bar.prom"} 1.710812009e+09 node_textfile_mtime_seconds{file="/Users/rexagod/repositories/misc/node_exporter/ne-foo.prom"} 1.710811982e+09 # HELP node_textfile_scrape_error 1 if there was an error opening or reading a file, 0 otherwise # TYPE node_textfile_scrape_error gauge node_textfile_scrape_error 1 # HELP promhttp_metric_handler_errors_total Total number of internal errors encountered by the promhttp metric handler. # TYPE promhttp_metric_handler_errors_total counter promhttp_metric_handler_errors_total{cause="encoding"} 0 promhttp_metric_handler_errors_total{cause="gathering"} 0 # HELP promhttp_metric_handler_requests_in_flight Current number of scrapes being served. # TYPE promhttp_metric_handler_requests_in_flight gauge promhttp_metric_handler_requests_in_flight 1 # HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code. # TYPE promhttp_metric_handler_requests_total counter promhttp_metric_handler_requests_total{code="200"} 0 promhttp_metric_handler_requests_total{code="500"} 0 promhttp_metric_handler_requests_total{code="503"} 0 # HELP tau_infrastructure_performing_maintenance_task At what timestamp a given task started or stopped, the last time it was run. # TYPE tau_infrastructure_performing_maintenance_task gauge tau_infrastructure_performing_maintenance_task{main_task="nightly",start_or_stop="start",sub_task="main"} 1.64728080198446e+09 ``` Fixes: #2317 Signed-off-by: Pranshu Srivastava Signed-off-by: Vitaly Zhuravlev --- .../textfile/metrics_merge_different_help.out | 2 +- collector/textfile.go | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/collector/fixtures/textfile/metrics_merge_different_help.out b/collector/fixtures/textfile/metrics_merge_different_help.out index ba161f0779..b9385a752a 100644 --- a/collector/fixtures/textfile/metrics_merge_different_help.out +++ b/collector/fixtures/textfile/metrics_merge_different_help.out @@ -8,4 +8,4 @@ node_textfile_mtime_seconds{file="fixtures/textfile/metrics_merge_different_help node_textfile_mtime_seconds{file="fixtures/textfile/metrics_merge_different_help/b.prom"} 1 # HELP node_textfile_scrape_error 1 if there was an error opening or reading a file, 0 otherwise # TYPE node_textfile_scrape_error gauge -node_textfile_scrape_error 0 +node_textfile_scrape_error 1 diff --git a/collector/textfile.go b/collector/textfile.go index 48133f7c98..4f1fd0b8c7 100644 --- a/collector/textfile.go +++ b/collector/textfile.go @@ -193,6 +193,7 @@ func (c *textFileCollector) Update(ch chan<- prometheus.Metric) error { var errored bool var parsedFamilies []*dto.MetricFamily metricsNamesToFiles := map[string][]string{} + metricsNamesToHelpTexts := map[string][2]string{} paths, err := filepath.Glob(c.path) if err != nil || len(paths) == 0 { @@ -218,6 +219,23 @@ func (c *textFileCollector) Update(ch chan<- prometheus.Metric) error { mtime, families, err := c.processFile(path, f.Name(), ch) for _, mf := range families { + // Check for metrics with inconsistent help texts and take the first help text occurrence. + if helpTexts, seen := metricsNamesToHelpTexts[*mf.Name]; seen { + if mf.Help != nil && helpTexts[0] != *mf.Help || helpTexts[1] != "" { + metricsNamesToHelpTexts[*mf.Name] = [2]string{helpTexts[0], *mf.Help} + errored = true + level.Error(c.logger).Log("msg", "inconsistent metric help text", + "metric", *mf.Name, + "original_help_text", helpTexts[0], + "new_help_text", *mf.Help, + // Only the first file path will be recorded in case of two or more inconsistent help texts. + "file", metricsNamesToFiles[*mf.Name][0]) + continue + } + } + if mf.Help != nil { + metricsNamesToHelpTexts[*mf.Name] = [2]string{*mf.Help} + } metricsNamesToFiles[*mf.Name] = append(metricsNamesToFiles[*mf.Name], metricsFilePath) parsedFamilies = append(parsedFamilies, mf) }