Treat custom textfile metric timestamps as errors (#769)

This is clearer behavior and users will notice and fix their textfiles faster
than if we just output a warning.
pull/844/head
Julius Volz 2018-02-28 01:43:38 +07:00 committed by Ben Kochie
parent c504c7e264
commit 864a6ee935
5 changed files with 30 additions and 8 deletions

View File

@ -0,0 +1,3 @@
# 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

View File

@ -0,0 +1,2 @@
metric_with_custom_timestamp 1 1441205977284
normal_metric 2

View File

@ -1,2 +1,2 @@
testmetric2_1{foo="bar"} 30 1441205977284 testmetric2_1{foo="bar"} 30
testmetric2_2{foo="baz"} 40 1441205977284 testmetric2_2{foo="baz"} 40

View File

@ -191,9 +191,11 @@ func (c *textFileCollector) Update(ch chan<- prometheus.Metric) error {
// Iterate over files and accumulate their metrics. // Iterate over files and accumulate their metrics.
files, err := ioutil.ReadDir(c.path) files, err := ioutil.ReadDir(c.path)
if err != nil && c.path != "" { if err != nil && c.path != "" {
log.Errorf("Error reading textfile collector directory %s: %s", c.path, err) log.Errorf("Error reading textfile collector directory %q: %s", c.path, err)
error = 1.0 error = 1.0
} }
fileLoop:
for _, f := range files { for _, f := range files {
if !strings.HasSuffix(f.Name(), ".prom") { if !strings.HasSuffix(f.Name(), ".prom") {
continue continue
@ -201,7 +203,7 @@ func (c *textFileCollector) Update(ch chan<- prometheus.Metric) error {
path := filepath.Join(c.path, f.Name()) path := filepath.Join(c.path, f.Name())
file, err := os.Open(path) file, err := os.Open(path)
if err != nil { if err != nil {
log.Errorf("Error opening %s: %v", path, err) log.Errorf("Error opening %q: %v", path, err)
error = 1.0 error = 1.0
continue continue
} }
@ -209,18 +211,29 @@ func (c *textFileCollector) Update(ch chan<- prometheus.Metric) error {
parsedFamilies, err := parser.TextToMetricFamilies(file) parsedFamilies, err := parser.TextToMetricFamilies(file)
file.Close() file.Close()
if err != nil { if err != nil {
log.Errorf("Error parsing %s: %v", path, err) log.Errorf("Error parsing %q: %v", path, err)
error = 1.0 error = 1.0
continue continue
} }
// Only set this once it has been parsed, so that
// a failure does not appear fresh.
mtimes[f.Name()] = f.ModTime()
for _, mf := range parsedFamilies { for _, mf := range parsedFamilies {
for _, m := range mf.Metric {
if m.TimestampMs != nil {
log.Errorf("Textfile %q contains unsupported client-side timestamps, skipping entire file", path)
error = 1.0
continue fileLoop
}
}
if mf.Help == nil { if mf.Help == nil {
help := fmt.Sprintf("Metric read from %s", path) help := fmt.Sprintf("Metric read from %s", path)
mf.Help = &help mf.Help = &help
} }
}
// Only set this once it has been parsed and validated, so that
// a failure does not appear fresh.
mtimes[f.Name()] = f.ModTime()
for _, mf := range parsedFamilies {
convertMetricFamily(mf, ch) convertMetricFamily(mf, ch)
} }
} }

View File

@ -62,6 +62,10 @@ func TestTextfileCollector(t *testing.T) {
path: "fixtures/textfile/nonexistent_path", path: "fixtures/textfile/nonexistent_path",
out: "fixtures/textfile/nonexistent_path.out", out: "fixtures/textfile/nonexistent_path.out",
}, },
{
path: "fixtures/textfile/client_side_timestamp",
out: "fixtures/textfile/client_side_timestamp.out",
},
{ {
path: "fixtures/textfile/different_metric_types", path: "fixtures/textfile/different_metric_types",
out: "fixtures/textfile/different_metric_types.out", out: "fixtures/textfile/different_metric_types.out",