diff --git a/tensorflow_serving/util/prometheus_exporter.cc b/tensorflow_serving/util/prometheus_exporter.cc index 03a939b347a..58488dc215f 100644 --- a/tensorflow_serving/util/prometheus_exporter.cc +++ b/tensorflow_serving/util/prometheus_exporter.cc @@ -30,12 +30,14 @@ namespace serving { namespace { string SanitizeLabelValue(const string& value) { - // Backslash and double quote have to be escaped. + // Backslash, double quote and line feed have to be escaped. string new_value = value; // Replace \ with \\. RE2::GlobalReplace(&new_value, "\\\\", "\\\\\\\\"); // Replace " with \". RE2::GlobalReplace(&new_value, "\"", "\\\\\""); + // Replace a line feed with \n. + RE2::GlobalReplace(&new_value, "\n", "\\\\n"); return new_value; } diff --git a/tensorflow_serving/util/prometheus_exporter_test.cc b/tensorflow_serving/util/prometheus_exporter_test.cc index 57719f4ce21..762a27056de 100644 --- a/tensorflow_serving/util/prometheus_exporter_test.cc +++ b/tensorflow_serving/util/prometheus_exporter_test.cc @@ -108,6 +108,24 @@ TEST(PrometheusExporterTest, SanitizeLabelValue) { EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_result, http_page); } +TEST(PrometheusExporterTest, SanitizeLabelValueLineFeed) { + auto exporter = absl::make_unique(); + auto counter = absl::WrapUnique( + monitoring::Counter<1>::New("/test/path/total", "A counter.", "name")); + // label value: abcdef + counter->GetCell("abc\ndef")->IncrementBy(2); + + string http_page; + Status status = exporter->GeneratePage(&http_page); + + string expected_result = + absl::StrJoin({"# TYPE :test:path:total counter", + ":test:path:total{name=\"abc\\ndef\"} 2"}, + "\n"); + absl::StrAppend(&expected_result, "\n"); + EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_result, http_page); +} + TEST(PrometheusExporterTest, SanitizeLabelName) { auto exporter = absl::make_unique(); auto counter = absl::WrapUnique(monitoring::Counter<1>::New(