diff --git a/src/main/java/org/datadog/jmxfetch/App.java b/src/main/java/org/datadog/jmxfetch/App.java index b4cd7e5ef..203fc3fca 100644 --- a/src/main/java/org/datadog/jmxfetch/App.java +++ b/src/main/java/org/datadog/jmxfetch/App.java @@ -136,6 +136,12 @@ private static void clearInstances(List instances) { void start() { // Main Loop that will periodically collect metrics from the JMX Server while (true) { + // Exit on exit file trigger + if (appConfig.getExitWatcher().shouldExit()){ + LOGGER.info("Exit file detected: stopping JMXFetch."); + System.exit(0); + } + long start = System.currentTimeMillis(); if (instances.size() > 0) { doIteration(); @@ -288,7 +294,7 @@ private void reportStatus(AppConfig appConfig, Reporter reporter, Instance insta instance.getServiceCheckTags()); appConfig.getStatus().addInstanceStats(checkName, instance.getName(), - metricCount, reporter.getServiceCheckCount(checkName), + metricCount, reporter.getServiceCheckCount(checkName), message, status); reporter.resetServiceCheckCount(checkName); } diff --git a/src/main/java/org/datadog/jmxfetch/AppConfig.java b/src/main/java/org/datadog/jmxfetch/AppConfig.java index 4b395a7cf..528d521f0 100644 --- a/src/main/java/org/datadog/jmxfetch/AppConfig.java +++ b/src/main/java/org/datadog/jmxfetch/AppConfig.java @@ -2,6 +2,7 @@ import java.util.Arrays; import java.util.List; +import org.datadog.jmxfetch.converter.ExitWatcherConverter; import org.datadog.jmxfetch.converter.ReporterConverter; import org.datadog.jmxfetch.converter.StatusConverter; import org.datadog.jmxfetch.reporter.ConsoleReporter; @@ -71,6 +72,12 @@ class AppConfig { required = false) private Status status = new Status(); + @Parameter(names = {"--exit_file_location", "-e"}, + description = "Absolute path of the trigger file to watch to exit. (default to null = no exit on file)", + converter = ExitWatcherConverter.class, + required = false) + private ExitWatcher exitWatcher = new ExitWatcher(); + @Parameter(description = "Action to take, should be in [help, collect, " + "list_everything, list_collected_attributes, list_matching_attributes, " + "list_not_matching_attributes, list_limited_attributes]", @@ -93,6 +100,10 @@ public Status getStatus() { return status; } + public ExitWatcher getExitWatcher(){ + return exitWatcher; + } + public int getCheckPeriod() { return checkPeriod; } diff --git a/src/main/java/org/datadog/jmxfetch/ExitWatcher.java b/src/main/java/org/datadog/jmxfetch/ExitWatcher.java new file mode 100644 index 000000000..40a1d4cc5 --- /dev/null +++ b/src/main/java/org/datadog/jmxfetch/ExitWatcher.java @@ -0,0 +1,37 @@ +package org.datadog.jmxfetch; + +import java.io.File; + +public class ExitWatcher { + + private String exitFileLocation; + private boolean isEnabled; + + public ExitWatcher(){ + this(null); + } + + public ExitWatcher(String exitFileLocation) { + this.exitFileLocation = exitFileLocation; + this.isEnabled = this.exitFileLocation != null; + } + + public String getExitFileLocation() { + return exitFileLocation; + } + + public boolean isEnabled() { + return isEnabled; + } + + public boolean shouldExit(){ + if (isEnabled()) { + File f = new File(exitFileLocation); + if(f.exists() && !f.isDirectory()) { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/org/datadog/jmxfetch/converter/ExitWatcherConverter.java b/src/main/java/org/datadog/jmxfetch/converter/ExitWatcherConverter.java new file mode 100644 index 000000000..9d22372ad --- /dev/null +++ b/src/main/java/org/datadog/jmxfetch/converter/ExitWatcherConverter.java @@ -0,0 +1,11 @@ +package org.datadog.jmxfetch.converter; + +import com.beust.jcommander.IStringConverter; +import org.datadog.jmxfetch.ExitWatcher; + +public class ExitWatcherConverter implements IStringConverter { + + public ExitWatcher convert(String value) { + return new ExitWatcher(value); + } +} diff --git a/src/test/java/org/datadog/jmxfetch/TestApp.java b/src/test/java/org/datadog/jmxfetch/TestApp.java index da477ed14..9594d4700 100644 --- a/src/test/java/org/datadog/jmxfetch/TestApp.java +++ b/src/test/java/org/datadog/jmxfetch/TestApp.java @@ -13,6 +13,7 @@ import javax.management.MBeanServer; import javax.management.ObjectName; +import java.io.File; import java.lang.management.ManagementFactory; import java.util.Arrays; import java.util.HashMap; @@ -401,12 +402,12 @@ public void testServiceCheckCounter() throws Exception { // Let's check that the counter is null assertEquals(0, repo.getServiceCheckCount("jmx")); - + // Let's put a service check in the pipeline (we cannot call doIteration() - // here unfortunately because it would call reportStatus which will flush - // the count to the jmx_status.yaml file and reset the counter. + // here unfortunately because it would call reportStatus which will flush + // the count to the jmx_status.yaml file and reset the counter. repo.sendServiceCheck("jmx", Status.STATUS_OK, "This is a test", "jmx_test_instance", null); - + // Let's check that the counter has been updated assertEquals(1, repo.getServiceCheckCount("jmx")); @@ -430,6 +431,21 @@ public void testPrefixFormatter() throws Exception { assertEquals(data[i][1], Reporter.formatServiceCheckPrefix(data[i][0])); } + @Test + public void testExitWatcher() throws Exception { + // Test the ExitWatcher logic + + // Create a temp file + File temp = File.createTempFile("exit-jmxfetch-file-name", ".tmp"); + temp.deleteOnExit(); + + ExitWatcher exitWatcher = new ExitWatcher(temp.getAbsolutePath()); + assertTrue(exitWatcher.shouldExit()); + + temp.delete(); + assertFalse(exitWatcher.shouldExit()); + } + @Test public void testApp() throws Exception { // We expose a few metrics through JMX diff --git a/src/test/java/org/datadog/jmxfetch/TestParsingJCommander.java b/src/test/java/org/datadog/jmxfetch/TestParsingJCommander.java index 209126b80..2c6eb8389 100644 --- a/src/test/java/org/datadog/jmxfetch/TestParsingJCommander.java +++ b/src/test/java/org/datadog/jmxfetch/TestParsingJCommander.java @@ -21,7 +21,8 @@ public class TestParsingJCommander { private static final String REPORTER_CONSOLE = "console"; private static final String SINGLE_CHECK = "jmx.yaml"; private static final List MULTI_CHECK = Arrays.asList("jmx.yaml", "jmx-2.yaml"); - private static final String STATUS_LOCATION = "/status/loaction"; + private static final String STATUS_LOCATION = "/status/status_location"; + private static final String EXIT_FILE_LOCATION = "/status/exit_locationt"; private static AppConfig testCommand(String[] params) throws ParameterException { AppConfig appConfig = new AppConfig(); @@ -235,6 +236,21 @@ public void testParsingStatus() { assertTrue(appConfig.getStatus().isEnabled()); } + @Test + public void testParsingExitWatcher() { + String[] params = new String[]{ + "--reporter", REPORTER_CONSOLE, + "--check", SINGLE_CHECK, + "--conf_directory", CONF_DIR, + "--exit_file_location", EXIT_FILE_LOCATION, + AppConfig.ACTION_COLLECT + }; + AppConfig appConfig = testCommand(params); + assertNotNull(appConfig.getExitWatcher()); + assertEquals(EXIT_FILE_LOCATION, appConfig.getExitWatcher().getExitFileLocation()); + assertTrue(appConfig.getExitWatcher().isEnabled()); + } + @Test public void testParsingAction() { // Positive cases