package com.etsy.statsd.profiler;
import com.etsy.statsd.profiler.profilers.CPUTracingProfiler;
import com.etsy.statsd.profiler.profilers.MemoryProfiler;
import com.etsy.statsd.profiler.reporter.Reporter;
import com.etsy.statsd.profiler.reporter.StatsDReporter;
import com.google.common.base.Optional;
import java.util.*;
/**
* Represents arguments to the profiler
*
* @author Andrew Johnson
*/
public final class Arguments {
private static final String SERVER = "server";
private static final String PORT = "port";
private static final String METRICS_PREFIX = "prefix";
private static final String PROFILERS = "profilers";
private static final String REPORTER = "reporter";
private static final String HTTP_PORT = "httpPort";
private static final String HTTP_SEVER_ENABLED = "httpServerEnabled";
private static final Collection<String> REQUIRED = Arrays.asList(SERVER, PORT);
public String server;
public int port;
public String metricsPrefix;
public Set<Class<? extends Profiler>> profilers;
public Map<String, String> remainingArgs;
public Class<? extends Reporter<?>> reporter;
public int httpPort;
public boolean httpServerEnabled;
private Arguments(Map<String, String> parsedArgs) {
server = parsedArgs.get(SERVER);
port = Integer.parseInt(parsedArgs.get(PORT));
metricsPrefix = Optional.fromNullable(parsedArgs.get(METRICS_PREFIX)).or("statsd-jvm-profiler");
profilers = parseProfilerArg(parsedArgs.get(PROFILERS));
reporter = parserReporterArg(parsedArgs.get(REPORTER));
httpPort = Integer.parseInt(Optional.fromNullable(parsedArgs.get(HTTP_PORT)).or("5005"));
httpServerEnabled = Boolean.parseBoolean(Optional.fromNullable(parsedArgs.get(HTTP_SEVER_ENABLED)).or("true"));
parsedArgs.remove(SERVER);
parsedArgs.remove(PORT);
parsedArgs.remove(METRICS_PREFIX);
parsedArgs.remove(PROFILERS);
remainingArgs = parsedArgs;
}
/**
* Parses arguments into an Arguments object
*
* @param args A String containing comma-delimited args in k=v form
* @return An Arguments object representing the given arguments
*/
public static Arguments parseArgs(final String args) {
Map<String, String> parsed = new HashMap<>();
for (String argPair : args.split(",")) {
String[] tokens = argPair.split("=");
if (tokens.length != 2) {
throw new IllegalArgumentException("statsd-jvm-profiler takes a comma-delimited list of arguments in k=v form");
}
parsed.put(tokens[0], tokens[1]);
}
for (String requiredArg : REQUIRED) {
if (!parsed.containsKey(requiredArg)) {
throw new IllegalArgumentException(String.format("%s argument was not supplied", requiredArg));
}
}
return new Arguments(parsed);
}
@SuppressWarnings("unchecked")
private static Class<? extends Reporter<?>> parserReporterArg(String reporterArg) {
if (reporterArg == null) {
return StatsDReporter.class;
} else {
try {
return (Class<? extends Reporter<?>>) Class.forName(reporterArg);
} catch (ClassNotFoundException e) {
// This might indicate the package was left off, so we'll try with the default package
try {
return (Class<? extends Reporter<?>>) Class.forName("com.etsy.statsd.profiler.reporter." + reporterArg);
} catch (ClassNotFoundException inner) {
throw new IllegalArgumentException("Reporter " + reporterArg + " not found", inner);
}
}
}
}
@SuppressWarnings("unchecked")
private static Set<Class<? extends Profiler>> parseProfilerArg(String profilerArg) {
Set<Class<? extends Profiler>> parsedProfilers = new HashSet<>();
if (profilerArg == null) {
parsedProfilers.add(CPUTracingProfiler.class);
parsedProfilers.add(MemoryProfiler.class);
} else {
for (String p : profilerArg.split(":")) {
try {
parsedProfilers.add((Class<? extends Profiler>) Class.forName(p));
} catch (ClassNotFoundException e) {
// This might indicate the package was left off, so we'll try with the default package
try {
parsedProfilers.add((Class<? extends Profiler>) Class.forName("com.etsy.statsd.profiler.profilers." + p));
} catch (ClassNotFoundException inner) {
throw new IllegalArgumentException("Profiler " + p + " not found", inner);
}
}
}
}
if (parsedProfilers.isEmpty()) {
throw new IllegalArgumentException("At least one profiler must be specified");
}
return parsedProfilers;
}
}