|
@@ -0,0 +1,138 @@
|
|
|
+/*
|
|
|
+ * Licensed to the Apache Software Foundation (ASF) under one
|
|
|
+ * or more contributor license agreements. See the NOTICE file
|
|
|
+ * distributed with this work for additional information
|
|
|
+ * regarding copyright ownership. The ASF licenses this file
|
|
|
+ * to you under the Apache License, Version 2.0 (the
|
|
|
+ * "License"); you may not use this file except in compliance
|
|
|
+ * with the License. You may obtain a copy of the License at
|
|
|
+ *
|
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
|
+ *
|
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
+ * See the License for the specific language governing permissions and
|
|
|
+ * limitations under the License.
|
|
|
+ */
|
|
|
+
|
|
|
+package org.apache.hadoop.metrics2.sink;
|
|
|
+
|
|
|
+import java.io.ByteArrayOutputStream;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+
|
|
|
+import org.apache.hadoop.io.IOUtils;
|
|
|
+import org.apache.hadoop.metrics2.MetricsSystem;
|
|
|
+import org.apache.hadoop.metrics2.annotation.Metric;
|
|
|
+import org.apache.hadoop.metrics2.annotation.Metrics;
|
|
|
+import org.apache.hadoop.metrics2.annotation.Metric.Type;
|
|
|
+import org.apache.hadoop.metrics2.impl.ConfigBuilder;
|
|
|
+import org.apache.hadoop.metrics2.impl.MetricsSystemImpl;
|
|
|
+import org.apache.hadoop.metrics2.impl.TestMetricsConfig;
|
|
|
+import org.apache.hadoop.metrics2.lib.MutableGaugeInt;
|
|
|
+import org.junit.After;
|
|
|
+import org.junit.Test;
|
|
|
+import static org.junit.Assert.*;
|
|
|
+
|
|
|
+public class TestFileSink {
|
|
|
+
|
|
|
+ private File outFile;
|
|
|
+
|
|
|
+ // The 2 sample metric classes:
|
|
|
+ @Metrics(name="testRecord1", context="test1")
|
|
|
+ static class MyMetrics1 {
|
|
|
+ @Metric(value={"testTag1", ""}, type=Type.TAG)
|
|
|
+ String testTag1() { return "testTagValue1"; }
|
|
|
+
|
|
|
+ @Metric(value={"testTag2", ""}, type=Type.TAG)
|
|
|
+ String gettestTag2() { return "testTagValue2"; }
|
|
|
+
|
|
|
+ @Metric(value={"testMetric1", "An integer gauge"},always=true)
|
|
|
+ MutableGaugeInt testMetric1;
|
|
|
+
|
|
|
+ @Metric(value={"testMetric2", "An integer gauge"},always=true)
|
|
|
+ MutableGaugeInt testMetric2;
|
|
|
+
|
|
|
+ public MyMetrics1 registerWith(MetricsSystem ms) {
|
|
|
+ return ms.register("m1", null, this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Metrics(name="testRecord2", context="test1")
|
|
|
+ static class MyMetrics2 {
|
|
|
+ @Metric(value={"testTag22", ""}, type=Type.TAG)
|
|
|
+ String testTag1() { return "testTagValue22"; }
|
|
|
+
|
|
|
+ public MyMetrics2 registerWith(MetricsSystem ms) {
|
|
|
+ return ms.register("m2", null, this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private File getTestTempFile(String prefix, String suffix) throws IOException {
|
|
|
+ String tmpPath = System.getProperty("java.io.tmpdir", "/tmp");
|
|
|
+ String user = System.getProperty("user.name", "unknown-user");
|
|
|
+ File dir = new File(tmpPath + "/" + user);
|
|
|
+ dir.mkdirs();
|
|
|
+ return File.createTempFile(prefix, suffix, dir);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test(timeout=6000)
|
|
|
+ public void testFileSink() throws IOException {
|
|
|
+ outFile = getTestTempFile("test-file-sink-", ".out");
|
|
|
+ final String outPath = outFile.getAbsolutePath();
|
|
|
+
|
|
|
+ // NB: specify large period to avoid multiple metrics snapshotting:
|
|
|
+ new ConfigBuilder().add("*.period", 10000)
|
|
|
+ .add("test.sink.mysink0.class", FileSink.class.getName())
|
|
|
+ .add("test.sink.mysink0.filename", outPath)
|
|
|
+ // NB: we filter by context to exclude "metricssystem" context metrics:
|
|
|
+ .add("test.sink.mysink0.context", "test1")
|
|
|
+ .save(TestMetricsConfig.getTestFilename("hadoop-metrics2-test"));
|
|
|
+ MetricsSystemImpl ms = new MetricsSystemImpl("test");
|
|
|
+ ms.start();
|
|
|
+
|
|
|
+ final MyMetrics1 mm1
|
|
|
+ = new MyMetrics1().registerWith(ms);
|
|
|
+ new MyMetrics2().registerWith(ms);
|
|
|
+
|
|
|
+ mm1.testMetric1.incr();
|
|
|
+ mm1.testMetric2.incr(2);
|
|
|
+
|
|
|
+ ms.publishMetricsNow(); // publish the metrics
|
|
|
+ ms.stop();
|
|
|
+ ms.shutdown();
|
|
|
+
|
|
|
+ InputStream is = new FileInputStream(outFile);
|
|
|
+ ByteArrayOutputStream baos = new ByteArrayOutputStream((int)outFile.length());
|
|
|
+ IOUtils.copyBytes(is, baos, 1024, true);
|
|
|
+ String outFileContent = new String(baos.toByteArray(), "UTF-8");
|
|
|
+
|
|
|
+ // Check the out file content. Should be something like the following:
|
|
|
+ //1360244820087 test1.testRecord1: Context=test1, testTag1=testTagValue1, testTag2=testTagValue2, Hostname=myhost, testMetric1=1, testMetric2=2
|
|
|
+ //1360244820089 test1.testRecord2: Context=test1, testTag22=testTagValue22, Hostname=myhost
|
|
|
+
|
|
|
+ // Note that in the below expression we allow tags and metrics to go in arbitrary order.
|
|
|
+ Pattern expectedContentPattern = Pattern.compile(
|
|
|
+ // line #1:
|
|
|
+ "^\\d+\\s+test1.testRecord1:\\s+Context=test1,\\s+" +
|
|
|
+ "(testTag1=testTagValue1,\\s+testTag2=testTagValue2|testTag2=testTagValue2,\\s+testTag1=testTagValue1)," +
|
|
|
+ "\\s+Hostname=.*,\\s+(testMetric1=1,\\s+testMetric2=2|testMetric2=2,\\s+testMetric1=1)" +
|
|
|
+ // line #2:
|
|
|
+ "$[\\n\\r]*^\\d+\\s+test1.testRecord2:\\s+Context=test1," +
|
|
|
+ "\\s+testTag22=testTagValue22,\\s+Hostname=.*$[\\n\\r]*",
|
|
|
+ Pattern.MULTILINE);
|
|
|
+ assertTrue(expectedContentPattern.matcher(outFileContent).matches());
|
|
|
+ }
|
|
|
+
|
|
|
+ @After
|
|
|
+ public void after() {
|
|
|
+ if (outFile != null) {
|
|
|
+ outFile.delete();
|
|
|
+ assertTrue(!outFile.exists());
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|