Skip to content

Commit ce920a4

Browse files
eduarrrdv-zhuravlev
authored andcommitted
textfile: Allow specifiying multiple directory globs. (prometheus#3135)
We already support reading from multiple directories though only using globs. Now we can specify them outright. Example use case is exporting both static info on a RO FS generated during image building and traditional uses of textfiles (e.g. for R/W service metrics files) without scripting a file copy. * keep flag name for compatibility * clarify flag help text * add test case (replicating the glob one) Signed-off-by: eduarrrd <[email protected]> Signed-off-by: Vitaly Zhuravlev <[email protected]>
1 parent 72456dc commit ce920a4

File tree

2 files changed

+54
-43
lines changed

2 files changed

+54
-43
lines changed

collector/textfile.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ import (
3232
)
3333

3434
var (
35-
textFileDirectory = kingpin.Flag("collector.textfile.directory", "Directory to read text files with metrics from.").Default("").String()
36-
mtimeDesc = prometheus.NewDesc(
35+
textFileDirectories = kingpin.Flag("collector.textfile.directory", "Directory to read text files with metrics from, supports glob matching. (repeatable)").Default("").Strings()
36+
mtimeDesc = prometheus.NewDesc(
3737
"node_textfile_mtime_seconds",
3838
"Unixtime mtime of textfiles successfully read.",
3939
[]string{"file"},
@@ -42,7 +42,7 @@ var (
4242
)
4343

4444
type textFileCollector struct {
45-
path string
45+
paths []string
4646
// Only set for testing to get predictable output.
4747
mtime *float64
4848
logger *slog.Logger
@@ -56,7 +56,7 @@ func init() {
5656
// in the given textfile directory.
5757
func NewTextFileCollector(logger *slog.Logger) (Collector, error) {
5858
c := &textFileCollector{
59-
path: *textFileDirectory,
59+
paths: *textFileDirectories,
6060
logger: logger,
6161
}
6262
return c, nil
@@ -194,11 +194,15 @@ func (c *textFileCollector) Update(ch chan<- prometheus.Metric) error {
194194
metricsNamesToFiles := map[string][]string{}
195195
metricsNamesToHelpTexts := map[string][2]string{}
196196

197-
paths, err := filepath.Glob(c.path)
198-
if err != nil || len(paths) == 0 {
199-
// not glob or not accessible path either way assume single
200-
// directory and let os.ReadDir handle it
201-
paths = []string{c.path}
197+
paths := []string{}
198+
for _, glob := range c.paths {
199+
ps, err := filepath.Glob(glob)
200+
if err != nil || len(ps) == 0 {
201+
// not glob or not accessible path either way assume single
202+
// directory and let os.ReadDir handle it
203+
ps = []string{glob}
204+
}
205+
paths = append(paths, ps...)
202206
}
203207

204208
mtimes := make(map[string]time.Time)

collector/textfile_test.go

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -52,75 +52,82 @@ func (a collectorAdapter) Collect(ch chan<- prometheus.Metric) {
5252

5353
func TestTextfileCollector(t *testing.T) {
5454
tests := []struct {
55-
path string
56-
out string
55+
paths []string
56+
out string
5757
}{
5858
{
59-
path: "fixtures/textfile/no_metric_files",
60-
out: "fixtures/textfile/no_metric_files.out",
59+
paths: []string{"fixtures/textfile/no_metric_files"},
60+
out: "fixtures/textfile/no_metric_files.out",
6161
},
6262
{
63-
path: "fixtures/textfile/two_metric_files",
64-
out: "fixtures/textfile/two_metric_files.out",
63+
paths: []string{"fixtures/textfile/two_metric_files"},
64+
out: "fixtures/textfile/two_metric_files.out",
6565
},
6666
{
67-
path: "fixtures/textfile/nonexistent_path",
68-
out: "fixtures/textfile/nonexistent_path.out",
67+
paths: []string{"fixtures/textfile/nonexistent_path"},
68+
out: "fixtures/textfile/nonexistent_path.out",
6969
},
7070
{
71-
path: "fixtures/textfile/client_side_timestamp",
72-
out: "fixtures/textfile/client_side_timestamp.out",
71+
paths: []string{"fixtures/textfile/client_side_timestamp"},
72+
out: "fixtures/textfile/client_side_timestamp.out",
7373
},
7474
{
75-
path: "fixtures/textfile/different_metric_types",
76-
out: "fixtures/textfile/different_metric_types.out",
75+
paths: []string{"fixtures/textfile/different_metric_types"},
76+
out: "fixtures/textfile/different_metric_types.out",
7777
},
7878
{
79-
path: "fixtures/textfile/inconsistent_metrics",
80-
out: "fixtures/textfile/inconsistent_metrics.out",
79+
paths: []string{"fixtures/textfile/inconsistent_metrics"},
80+
out: "fixtures/textfile/inconsistent_metrics.out",
8181
},
8282
{
83-
path: "fixtures/textfile/histogram",
84-
out: "fixtures/textfile/histogram.out",
83+
paths: []string{"fixtures/textfile/histogram"},
84+
out: "fixtures/textfile/histogram.out",
8585
},
8686
{
87-
path: "fixtures/textfile/histogram_extra_dimension",
88-
out: "fixtures/textfile/histogram_extra_dimension.out",
87+
paths: []string{"fixtures/textfile/histogram_extra_dimension"},
88+
out: "fixtures/textfile/histogram_extra_dimension.out",
8989
},
9090
{
91-
path: "fixtures/textfile/summary",
92-
out: "fixtures/textfile/summary.out",
91+
paths: []string{"fixtures/textfile/summary"},
92+
out: "fixtures/textfile/summary.out",
9393
},
9494
{
95-
path: "fixtures/textfile/summary_extra_dimension",
96-
out: "fixtures/textfile/summary_extra_dimension.out",
95+
paths: []string{"fixtures/textfile/summary_extra_dimension"},
96+
out: "fixtures/textfile/summary_extra_dimension.out",
9797
},
9898
{
99-
path: "fixtures/textfile/*_extra_dimension",
100-
out: "fixtures/textfile/glob_extra_dimension.out",
99+
paths: []string{
100+
"fixtures/textfile/histogram_extra_dimension",
101+
"fixtures/textfile/summary_extra_dimension",
102+
},
103+
out: "fixtures/textfile/glob_extra_dimension.out",
101104
},
102105
{
103-
path: "fixtures/textfile/metrics_merge_empty_help",
104-
out: "fixtures/textfile/metrics_merge_empty_help.out",
106+
paths: []string{"fixtures/textfile/*_extra_dimension"},
107+
out: "fixtures/textfile/glob_extra_dimension.out",
105108
},
106109
{
107-
path: "fixtures/textfile/metrics_merge_no_help",
108-
out: "fixtures/textfile/metrics_merge_no_help.out",
110+
paths: []string{"fixtures/textfile/metrics_merge_empty_help"},
111+
out: "fixtures/textfile/metrics_merge_empty_help.out",
109112
},
110113
{
111-
path: "fixtures/textfile/metrics_merge_same_help",
112-
out: "fixtures/textfile/metrics_merge_same_help.out",
114+
paths: []string{"fixtures/textfile/metrics_merge_no_help"},
115+
out: "fixtures/textfile/metrics_merge_no_help.out",
113116
},
114117
{
115-
path: "fixtures/textfile/metrics_merge_different_help",
116-
out: "fixtures/textfile/metrics_merge_different_help.out",
118+
paths: []string{"fixtures/textfile/metrics_merge_same_help"},
119+
out: "fixtures/textfile/metrics_merge_same_help.out",
120+
},
121+
{
122+
paths: []string{"fixtures/textfile/metrics_merge_different_help"},
123+
out: "fixtures/textfile/metrics_merge_different_help.out",
117124
},
118125
}
119126

120127
for i, test := range tests {
121128
mtime := 1.0
122129
c := &textFileCollector{
123-
path: test.path,
130+
paths: test.paths,
124131
mtime: &mtime,
125132
logger: slog.New(slog.NewTextHandler(io.Discard, nil)),
126133
}
@@ -146,7 +153,7 @@ func TestTextfileCollector(t *testing.T) {
146153
}
147154

148155
if string(want) != got {
149-
t.Fatalf("%d.%q want:\n\n%s\n\ngot:\n\n%s", i, test.path, string(want), got)
156+
t.Fatalf("%d.%q want:\n\n%s\n\ngot:\n\n%s", i, test.paths, string(want), got)
150157
}
151158
}
152159
}

0 commit comments

Comments
 (0)