Skip to content

Commit

Permalink
Support white black lists (#57)
Browse files Browse the repository at this point in the history
* added whitelist

* added black list
  • Loading branch information
yyyogev authored Sep 18, 2019
1 parent c53f458 commit 2a7190a
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 14 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,9 @@ graphite {

metricsPollingIntervalInSeconds = 30
metricsPollingIntervalInSeconds = ${?INTERVAL_IN_SEC}

filter {
whitelistRegEx = ${?WHITE_LIST_REGEX}
blacklistRegEx = ${?BLACK_LIST_REGEX}
}

2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.logz</groupId>
<artifactId>jmx2graphite</artifactId>
<version>1.3.2</version>
<version>1.4.0</version>

<build>
<plugins>
Expand Down
15 changes: 8 additions & 7 deletions src/main/java/io/logz/jmx2graphite/GraphiteClient.java
Original file line number Diff line number Diff line change
@@ -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);
Expand Down
35 changes: 33 additions & 2 deletions src/main/java/io/logz/jmx2graphite/Jmx2GraphiteConfiguration.java
Original file line number Diff line number Diff line change
@@ -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<Pattern> whiteListPattern;
private Optional<Pattern> blackListPattern;
/* Short name of the sampled service, required = false */
private String serviceName = null;

Expand All @@ -40,6 +44,14 @@ public GraphiteProtocol getGraphiteProtocol() {
return graphiteProtocol;
}

public Optional<Pattern> getWhiteListPattern() {
return whiteListPattern;
}

public Optional<Pattern> getBlackListPattern() {
return blackListPattern;
}

public enum MetricClientType {
JOLOKIA,
MBEAN_PLATFORM
Expand Down Expand Up @@ -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");
Expand All @@ -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;
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/io/logz/jmx2graphite/Jmx2GraphiteJavaAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
20 changes: 19 additions & 1 deletion src/main/java/io/logz/jmx2graphite/MetricsPipeline.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -18,6 +20,9 @@
public class MetricsPipeline {
private static final Logger logger = LoggerFactory.getLogger(MetricsPipeline.class);

private final Optional<Pattern> beansWhiteListPattern;
private final Optional<Pattern> beansBlackListPattern;

private int pollingIntervalSeconds;

private GraphiteClient graphiteClient;
Expand All @@ -31,19 +36,32 @@ 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<MetricBean> getFilteredBeans(List<MetricBean> 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<MetricValue> poll() {
try {
long pollingWindowStartSeconds = getPollingWindowStartSeconds();
Stopwatch sw = Stopwatch.createStarted();
List<MetricBean> 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<MetricBean> filteredBeans = getFilteredBeans(beans);
logger.info("Filtered out {} metrics out of {} after white/blacklisting", beans.size() - filteredBeans.size(), beans.size());

sw.reset().start();
List<MetricValue> metrics = client.getMetrics(beans);
List<MetricValue> 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);
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/javaagent.conf
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ graphite {
protocol = ${?GRAPHITE_PROTOCOL}
}

filter {
whitelistRegEx = ${?WHITE_LIST_REGEX}
blacklistRegEx = ${?BLACK_LIST_REGEX}
}

metricsPollingIntervalInSeconds = ${?INTERVAL_IN_SEC}

logLevel = ${?LOG_LEVEL}

0 comments on commit 2a7190a

Please sign in to comment.