diff --git a/collector/textfile.go b/collector/textfile.go index 5b39609d73..6629eb9d8e 100644 --- a/collector/textfile.go +++ b/collector/textfile.go @@ -293,7 +293,7 @@ func (c *textFileCollector) processFile(dir, name string) (*time.Time, map[strin } defer f.Close() - parser := expfmt.NewTextParser(model.LegacyValidation) + parser := expfmt.NewTextParser(model.UTF8Validation) families, err := parser.TextToMetricFamilies(f) if err != nil { return nil, nil, fmt.Errorf("failed to parse textfile data from %q: %w", path, err) diff --git a/collector/textfile_test.go b/collector/textfile_test.go index 2fb31faca1..222ffa8fee 100644 --- a/collector/textfile_test.go +++ b/collector/textfile_test.go @@ -22,6 +22,7 @@ import ( "net/http" "net/http/httptest" "os" + "path/filepath" "testing" "github.com/alecthomas/kingpin/v2" @@ -156,3 +157,37 @@ func TestTextfileCollector(t *testing.T) { } } } + +func TestTextfileCollectorSupportsUTF8Names(t *testing.T) { + dir := t.TempDir() + const input = `# HELP "my.dotted.metric" A metric with UTF-8 compatible names. +# TYPE "my.dotted.metric" gauge +{"my.dotted.metric", "error.message"="Not Found"} 1 +` + if err := os.WriteFile(filepath.Join(dir, "test.prom"), []byte(input), 0o600); err != nil { + t.Fatal(err) + } + + c := &textFileCollector{ + paths: []string{dir}, + logger: slog.New(slog.NewTextHandler(io.Discard, nil)), + } + registry := prometheus.NewRegistry() + registry.MustRegister(collectorAdapter{c}) + + families, err := registry.Gather() + if err != nil { + t.Fatalf("failed to gather textfile with UTF-8 names: %v", err) + } + + for _, family := range families { + if family.GetName() != "my.dotted.metric" { + continue + } + if got := family.Metric[0].Label[0].GetName(); got != "error.message" { + t.Fatalf("expected dotted label name, got %q", got) + } + return + } + t.Fatalf("expected dotted metric name, got %v", families) +}