diff --git a/README.md b/README.md index ab3748f..cfae9a3 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,10 @@ there are two ways to specify the host in the jolokia URL so this URL will be re - GRAPHITE_PORT: Protocol port of graphite. Defaults to 2004. - SERVICE_HOST: By default the host is taken from Jolokia URL and serves as the service host, unless you use this variable. - INTERVAL_IN_SEC: By default 30 seconds unless you use this variable. +- LOG_LEVEL: Configure Log Level [any of OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL] +- WHITE_LIST_REGEX: filter out unwanted metrics with whitelist regex. +- BLACK_LIST_REGEX: filter out unwanted metrics with blacklist regex. + ### Docker with config file Create a .conf file, set the input parameter and provide it to the docker. @@ -92,9 +96,7 @@ This lib can also get the metrics from MBean Platform instead of jolokia. In ord - The parameters are key-value pairs, in the format of key=value;key=value;... or key=value,key=value,... - The parameters names and functions are exactly as described in Environment Variables section. (Except no need to specify JOLOKIA_URL of course) - The javaagent.jar is an "Uber-Jar" that shades all of its dependencies inside, to prevent class collisions -- For example: java -javaagent:jmx2graphite.jar=GRAPHITE_HOSTNAME=graphite.example.com,SERVICE_NAME=PROD.MyAwesomeCategory example.jar -- To configure Log Level add the configuration LOG_LEVEL=[any of OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL] - +- For example: java -javaagent:jmx2graphite.jar=GRAPHITE_HOSTNAME=graphite.example.com,SERVICE_NAME=PROD.MyAwesomeCategory example.jar # How to expose JMX Metrics using Jolokia Agent @@ -246,6 +248,10 @@ docker push logzio/jmx2graphite # Changelog +- v1.4.0 + - add an option to filter out unwanted metrics with white/black-list regex +- v1.3.2 + - add an option to configure the omitted log level. - v1.3.1 - support external config file when using with jolokia agent - provide docker for jmx2graphite when using with jolokia agent diff --git a/application.conf b/application.conf index 3008ccf..79144e3 100644 --- a/application.conf +++ b/application.conf @@ -45,3 +45,9 @@ graphite { metricsPollingIntervalInSeconds = 30 metricsPollingIntervalInSeconds = ${?INTERVAL_IN_SEC} + +filter { + whitelistRegEx = ${?WHITE_LIST_REGEX} + blacklistRegEx = ${?BLACK_LIST_REGEX} +} + diff --git a/pom.xml b/pom.xml index e9b7b42..6b88ee3 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.logz jmx2graphite - 1.3.2 + 1.4.0 diff --git a/src/main/java/io/logz/jmx2graphite/GraphiteClient.java b/src/main/java/io/logz/jmx2graphite/GraphiteClient.java index e4810b1..454e8ee 100644 --- a/src/main/java/io/logz/jmx2graphite/GraphiteClient.java +++ b/src/main/java/io/logz/jmx2graphite/GraphiteClient.java @@ -1,24 +1,25 @@ package io.logz.jmx2graphite; -import static io.logz.jmx2graphite.GraphiteProtocol.TCP; -import static io.logz.jmx2graphite.GraphiteProtocol.UDP; - import com.codahale.metrics.graphite.Graphite; import com.codahale.metrics.graphite.GraphiteSender; import com.codahale.metrics.graphite.GraphiteUDP; import com.google.common.base.Joiner; import com.google.common.collect.Lists; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.SocketFactory; import java.io.Closeable; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; -import java.net.SocketException; import java.net.UnknownHostException; +import java.net.SocketException; import java.util.List; -import javax.net.SocketFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; + +import static io.logz.jmx2graphite.GraphiteProtocol.TCP; +import static io.logz.jmx2graphite.GraphiteProtocol.UDP; public class GraphiteClient implements Closeable { private static final Logger logger = LoggerFactory.getLogger(GraphiteClient.class); diff --git a/src/main/java/io/logz/jmx2graphite/Jmx2GraphiteConfiguration.java b/src/main/java/io/logz/jmx2graphite/Jmx2GraphiteConfiguration.java index f9235b8..c51b1ea 100644 --- a/src/main/java/io/logz/jmx2graphite/Jmx2GraphiteConfiguration.java +++ b/src/main/java/io/logz/jmx2graphite/Jmx2GraphiteConfiguration.java @@ -1,23 +1,27 @@ package io.logz.jmx2graphite; import com.typesafe.config.Config; +import com.typesafe.config.ConfigException; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; import java.net.UnknownHostException; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.logging.Level; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; /** * @author amesika */ public class Jmx2GraphiteConfiguration { - private String jolokiaFullUrl; private Graphite graphite; - + private Optional whiteListPattern; + private Optional blackListPattern; /* Short name of the sampled service, required = false */ private String serviceName = null; @@ -40,6 +44,14 @@ public GraphiteProtocol getGraphiteProtocol() { return graphiteProtocol; } + public Optional getWhiteListPattern() { + return whiteListPattern; + } + + public Optional getBlackListPattern() { + return blackListPattern; + } + public enum MetricClientType { JOLOKIA, MBEAN_PLATFORM @@ -104,6 +116,7 @@ else if (config.hasPath("service.poller.mbean-direct")) { } else { graphiteWriteTimeoutMs = Math.round(0.7f * TimeUnit.SECONDS.toMillis(metricsPollingIntervalInSeconds)); } + parseFilterPatterns(config); if(config.hasPath("log.level")) { logLevel = config.getString("log.level"); @@ -121,6 +134,24 @@ private GraphiteProtocol getGraphiteProtocol(Config config) { return null; } + private void parseFilterPatterns(Config config) { + try { + whiteListPattern = Optional.of(Pattern.compile(config.getString("filter.whitelistRegEx"))); + } catch (PatternSyntaxException | ConfigException.WrongType e) { + throw new IllegalArgumentException("can't parse whitelist regex:" + e.getMessage(), e); + } catch (ConfigException.Missing e) { + whiteListPattern = Optional.empty(); + } + + try { + blackListPattern = Optional.of(Pattern.compile(config.getString("filter.blacklistRegEx"))); + } catch (PatternSyntaxException | ConfigException.WrongType e) { + throw new IllegalArgumentException("can't parse blacklist regex:" + e.getMessage(), e); + } catch (ConfigException.Missing e) { + blackListPattern = Optional.empty(); + } + } + public String getJolokiaFullUrl() { return jolokiaFullUrl; } diff --git a/src/main/java/io/logz/jmx2graphite/Jmx2GraphiteJavaAgent.java b/src/main/java/io/logz/jmx2graphite/Jmx2GraphiteJavaAgent.java index ec3623f..68a64fd 100644 --- a/src/main/java/io/logz/jmx2graphite/Jmx2GraphiteJavaAgent.java +++ b/src/main/java/io/logz/jmx2graphite/Jmx2GraphiteJavaAgent.java @@ -91,6 +91,10 @@ private static String getArgumentConfigurationRepresentation(String key) throws return "graphite.protocol"; case "LOG_LEVEL": return "log.level"; + case "WHITE_LIST_REGEX": + return "filter.whitelistRegEx"; + case "BLACK_LIST_REGEX": + return "filter.blacklistRegEx"; default: throw new IllegalConfiguration("Unknown configuration option: " + key); } diff --git a/src/main/java/io/logz/jmx2graphite/MetricsPipeline.java b/src/main/java/io/logz/jmx2graphite/MetricsPipeline.java index 6cf2bbe..7484fe4 100644 --- a/src/main/java/io/logz/jmx2graphite/MetricsPipeline.java +++ b/src/main/java/io/logz/jmx2graphite/MetricsPipeline.java @@ -8,7 +8,9 @@ import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.Optional; import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; import java.util.stream.Collectors; /** @@ -18,6 +20,9 @@ public class MetricsPipeline { private static final Logger logger = LoggerFactory.getLogger(MetricsPipeline.class); + private final Optional beansWhiteListPattern; + private final Optional beansBlackListPattern; + private int pollingIntervalSeconds; private GraphiteClient graphiteClient; @@ -31,6 +36,16 @@ public MetricsPipeline(Jmx2GraphiteConfiguration conf, MBeanClient client) { conf.getGraphiteProtocol()); this.client = client; this.pollingIntervalSeconds = conf.getMetricsPollingIntervalInSeconds(); + this.beansWhiteListPattern = conf.getWhiteListPattern(); + this.beansBlackListPattern = conf.getBlackListPattern(); + + } + + public List getFilteredBeans(List beans) { + return beans.stream() + .filter(bean -> beansWhiteListPattern.isPresent() ? beansWhiteListPattern.get().matcher(bean.getName()).find() : true) + .filter(bean -> beansBlackListPattern.isPresent() ? !beansBlackListPattern.get().matcher(bean.getName()).find() : true) + .collect(Collectors.toList()); } private List poll() { @@ -38,12 +53,15 @@ private List poll() { long pollingWindowStartSeconds = getPollingWindowStartSeconds(); Stopwatch sw = Stopwatch.createStarted(); List beans = client.getBeans(); + logger.info("Found {} metric beans. Time = {}ms, for {}", beans.size(), sw.stop().elapsed(TimeUnit.MILLISECONDS), new Date(TimeUnit.SECONDS.toMillis(pollingWindowStartSeconds))); + List filteredBeans = getFilteredBeans(beans); + logger.info("Filtered out {} metrics out of {} after white/blacklisting", beans.size() - filteredBeans.size(), beans.size()); sw.reset().start(); - List metrics = client.getMetrics(beans); + List metrics = client.getMetrics(filteredBeans); logger.info("metrics fetched. Time: {} ms; Metrics: {}", sw.stop().elapsed(TimeUnit.MILLISECONDS), metrics.size()); if (logger.isTraceEnabled()) printToFile(metrics); return changeTimeTo(pollingWindowStartSeconds, metrics); diff --git a/src/main/resources/javaagent.conf b/src/main/resources/javaagent.conf index 2f950fd..b2dd418 100644 --- a/src/main/resources/javaagent.conf +++ b/src/main/resources/javaagent.conf @@ -22,6 +22,11 @@ graphite { protocol = ${?GRAPHITE_PROTOCOL} } +filter { + whitelistRegEx = ${?WHITE_LIST_REGEX} + blacklistRegEx = ${?BLACK_LIST_REGEX} +} + metricsPollingIntervalInSeconds = ${?INTERVAL_IN_SEC} logLevel = ${?LOG_LEVEL} \ No newline at end of file