2424import org .apache .hadoop .metrics2 .MetricsSystem ;
2525import org .apache .hadoop .metrics2 .annotation .Metric ;
2626import org .apache .hadoop .metrics2 .annotation .Metrics ;
27+ import org .apache .hadoop .metrics2 .annotation .Metric .Type ;
2728import org .apache .hadoop .metrics2 .lib .DefaultMetricsSystem ;
2829import org .apache .hadoop .metrics2 .lib .MutableCounterLong ;
2930
@@ -48,7 +49,6 @@ public void testPublish() throws IOException {
4849 TestMetrics testMetrics = metrics
4950 .register ("TestMetrics" , "Testing metrics" , new TestMetrics ());
5051
51- metrics .start ();
5252 testMetrics .numBucketCreateFails .incr ();
5353 metrics .publishMetricsNow ();
5454 ByteArrayOutputStream stream = new ByteArrayOutputStream ();
@@ -67,6 +67,104 @@ public void testPublish() throws IOException {
6767 "test_metrics_num_bucket_create_fails{context=\" dfs\" " )
6868 );
6969
70+ metrics .unregisterSource ("TestMetrics" );
71+ metrics .stop ();
72+ metrics .shutdown ();
73+ }
74+
75+ /**
76+ * Fix for HADOOP-17804, make sure Prometheus metrics get deduped based on metric
77+ * and tags, not just the metric.
78+ */
79+ @ Test
80+ public void testPublishMultiple () throws IOException {
81+ //GIVEN
82+ MetricsSystem metrics = DefaultMetricsSystem .instance ();
83+
84+ metrics .init ("test" );
85+ PrometheusMetricsSink sink = new PrometheusMetricsSink ();
86+ metrics .register ("Prometheus" , "Prometheus" , sink );
87+ TestMetrics testMetrics1 = metrics
88+ .register ("TestMetrics1" , "Testing metrics" , new TestMetrics ("1" ));
89+ TestMetrics testMetrics2 = metrics
90+ .register ("TestMetrics2" , "Testing metrics" , new TestMetrics ("2" ));
91+
92+ testMetrics1 .numBucketCreateFails .incr ();
93+ testMetrics2 .numBucketCreateFails .incr ();
94+ metrics .publishMetricsNow ();
95+ ByteArrayOutputStream stream = new ByteArrayOutputStream ();
96+ OutputStreamWriter writer = new OutputStreamWriter (stream , UTF_8 );
97+
98+ //WHEN
99+ sink .writeMetrics (writer );
100+ writer .flush ();
101+
102+ //THEN
103+ String writtenMetrics = stream .toString (UTF_8 .name ());
104+ System .out .println (writtenMetrics );
105+ Assert .assertTrue (
106+ "The expected first metric line is missing from prometheus metrics output" ,
107+ writtenMetrics .contains (
108+ "test_metrics_num_bucket_create_fails{context=\" dfs\" ,testtag=\" testTagValue1\" " )
109+ );
110+ Assert .assertTrue (
111+ "The expected second metric line is missing from prometheus metrics output" ,
112+ writtenMetrics .contains (
113+ "test_metrics_num_bucket_create_fails{context=\" dfs\" ,testtag=\" testTagValue2\" " )
114+ );
115+
116+ metrics .unregisterSource ("TestMetrics1" );
117+ metrics .unregisterSource ("TestMetrics2" );
118+ metrics .stop ();
119+ metrics .shutdown ();
120+ }
121+
122+ /**
123+ * Fix for HADOOP-17804, make sure Prometheus metrics start fresh after each flush.
124+ */
125+ @ Test
126+ public void testPublishFlush () throws IOException {
127+ //GIVEN
128+ MetricsSystem metrics = DefaultMetricsSystem .instance ();
129+
130+ metrics .init ("test" );
131+ PrometheusMetricsSink sink = new PrometheusMetricsSink ();
132+ metrics .register ("Prometheus" , "Prometheus" , sink );
133+ TestMetrics testMetrics = metrics
134+ .register ("TestMetrics" , "Testing metrics" , new TestMetrics ("1" ));
135+
136+ testMetrics .numBucketCreateFails .incr ();
137+ metrics .publishMetricsNow ();
138+
139+ metrics .unregisterSource ("TestMetrics" );
140+ testMetrics = metrics
141+ .register ("TestMetrics" , "Testing metrics" , new TestMetrics ("2" ));
142+
143+ testMetrics .numBucketCreateFails .incr ();
144+ metrics .publishMetricsNow ();
145+
146+ ByteArrayOutputStream stream = new ByteArrayOutputStream ();
147+ OutputStreamWriter writer = new OutputStreamWriter (stream , UTF_8 );
148+
149+ //WHEN
150+ sink .writeMetrics (writer );
151+ writer .flush ();
152+
153+ //THEN
154+ String writtenMetrics = stream .toString (UTF_8 .name ());
155+ System .out .println (writtenMetrics );
156+ Assert .assertFalse (
157+ "The first metric should not exist after flushing" ,
158+ writtenMetrics .contains (
159+ "test_metrics_num_bucket_create_fails{context=\" dfs\" ,testtag=\" testTagValue1\" " )
160+ );
161+ Assert .assertTrue (
162+ "The expected metric line is missing from prometheus metrics output" ,
163+ writtenMetrics .contains (
164+ "test_metrics_num_bucket_create_fails{context=\" dfs\" ,testtag=\" testTagValue2\" " )
165+ );
166+
167+ metrics .unregisterSource ("TestMetrics" );
70168 metrics .stop ();
71169 metrics .shutdown ();
72170 }
@@ -126,6 +224,20 @@ public void testNamingWhitespaces() {
126224 */
127225 @ Metrics (about = "Test Metrics" , context = "dfs" )
128226 private static class TestMetrics {
227+ private String id ;
228+
229+ TestMetrics () {
230+ this ("1" );
231+ }
232+
233+ TestMetrics (String id ) {
234+ this .id = id ;
235+ }
236+
237+ @ Metric (value ={"testTag" , "" }, type =Type .TAG )
238+ String testTag1 () {
239+ return "testTagValue" + id ;
240+ }
129241
130242 @ Metric
131243 private MutableCounterLong numBucketCreateFails ;
0 commit comments