Merge branch 'ManfredKarrer-monitor-nits' into monitor

This commit is contained in:
Florian Reimair 2018-12-30 10:56:18 +01:00
commit 32650f13ac
17 changed files with 158 additions and 115 deletions

2
.gitignore vendored
View File

@ -29,3 +29,5 @@ desktop.ini
*.class
deploy
*/releases/*
/monitor/TorHiddenServiceStartupTimeTests/*
/monitor/monitor-tor/*

View File

@ -325,6 +325,8 @@ configure(project(':monitor')) {
compile "org.slf4j:slf4j-api:$slf4jVersion"
compile "ch.qos.logback:logback-core:$logbackVersion"
compile "ch.qos.logback:logback-classic:$logbackVersion"
compile 'com.google.guava:guava:20.0'
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"

View File

@ -36,11 +36,11 @@ TorStartupTime.enabled=true
TorStartupTime.run.interval=100
TorStartupTime.run.socksPort=90500 # so that there is no interference with a system Tor
#TorRoundtripTime Metric
TorRoundtripTime.enabled=true
TorRoundtripTime.run.interval=100
TorRoundtripTime.run.sampleSize=5
TorRoundtripTime.run.hosts=http://expyuzz4wqqyqhjn.onion:80 # torproject.org hidden service
#TorRoundTripTime Metric
TorRoundTripTime.enabled=true
TorRoundTripTime.run.interval=100
TorRoundTripTime.run.sampleSize=5
TorRoundTripTime.run.hosts=http://expyuzz4wqqyqhjn.onion:80 # torproject.org hidden service
#TorHiddenServiceStartupTime Metric
TorHiddenServiceStartupTime.enabled=true
@ -54,4 +54,4 @@ TorHiddenServiceStartupTime.run.servicePort=90511 # so that there is no interfer
#GraphiteReporter
GraphiteReporter.serviceUrl=http://yourHiddenService.onion:2003
```
```

View File

@ -20,8 +20,8 @@ package bisq.monitor;
import java.util.Properties;
/**
* Does some precomputation for a configurable class.
*
* Does some pre-computation for a configurable class.
*
* @author Florian Reimair
*/
public abstract class Configurable {
@ -42,7 +42,7 @@ public abstract class Configurable {
* example, a property <code>MyName.answer=42</code> is made available as
* <code>configuration.getProperty("answer")</code> resulting in
* <code>42</code>.
*
*
* @param properties a set of configuration properties
*/
public void configure(final Properties properties) {
@ -65,7 +65,7 @@ public abstract class Configurable {
/**
* Set the name used to filter through configuration properties. See
* {@link Configurable#configure(Properties)}.
*
*
* @param name
*/
protected void setName(String name) {

View File

@ -26,7 +26,7 @@ import lombok.extern.slf4j.Slf4j;
* it down gracefully. Furthermore, configuration updates and execution are done
* in a thread-save manner. Implementing classes only have to implement the
* {@link Metric#execute()} method.
*
*
* @author Florian Reimair
*/
@Slf4j
@ -102,7 +102,7 @@ public abstract class Metric extends Configurable implements Runnable {
else if (!configuration.containsKey(INTERVAL))
log.error("{} is missing mandatory '" + INTERVAL + "' property. Will not run.", getName());
else
log.error("{} is misconfigured. Will not run.", getName());
log.error("{} is mis-configured. Will not run.", getName());
} else if (!enabled() && configuration.getProperty("enabled", "false").equals("true")) {
// check if this Metric got activated after being disabled.
// if so, resume execution

View File

@ -17,26 +17,32 @@
package bisq.monitor;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import bisq.monitor.metric.TorHiddenServiceStartupTime;
import bisq.monitor.metric.TorRoundTripTime;
import bisq.monitor.metric.TorStartupTime;
import bisq.monitor.reporter.GraphiteReporter;
import org.berndpruenster.netlayer.tor.NativeTor;
import org.berndpruenster.netlayer.tor.Tor;
import bisq.monitor.metric.TorStartupTime;
import bisq.monitor.reporter.ConsoleReporter;
import bisq.monitor.reporter.GraphiteReporter;
import bisq.monitor.metric.TorRoundtripTime;
import bisq.monitor.metric.TorHiddenServiceStartupTime;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkNotNull;
import sun.misc.Signal;
/**
* Monitor executable for the Bisq network.
*
*
* @author Florian Reimair
*/
@Slf4j
@ -52,16 +58,16 @@ public class Monitor {
/**
* A list of all active {@link Metric}s
*/
private List<Metric> metrics = new ArrayList<>();
private final List<Metric> metrics = new ArrayList<>();
/**
* Starts up all configured Metrics.
*
*
* @throws Exception
*/
private void start() throws Throwable {
// start Tor
Tor.setDefault(new NativeTor(new File("monitor-tor"), null, null, false));
Tor.setDefault(new NativeTor(new File("monitor/monitor-tor"), null, null, false));
// assemble Metrics
// - create reporters
@ -70,7 +76,7 @@ public class Monitor {
// - add available metrics with their reporters
metrics.add(new TorStartupTime(graphiteReporter));
metrics.add(new TorRoundtripTime(graphiteReporter));
metrics.add(new TorRoundTripTime(graphiteReporter));
metrics.add(new TorHiddenServiceStartupTime(graphiteReporter));
// prepare configuration reload
@ -104,7 +110,9 @@ public class Monitor {
}
log.info("shutting down tor");
Tor.getDefault().shutdown();
Tor tor = Tor.getDefault();
checkNotNull(tor, "tor must not be null");
tor.shutdown();
log.info("system halt");
}
@ -132,7 +140,7 @@ public class Monitor {
/**
* Overloads a default set of properties with a file if given
*
*
* @return a set of properties
* @throws Exception
*/
@ -142,7 +150,7 @@ public class Monitor {
Properties result = new Properties(defaults);
if(args.length > 0)
if (args.length > 0)
result.load(new FileInputStream(args[0]));
return result;

View File

@ -22,39 +22,40 @@ import java.util.Map;
/**
* Reports findings to a specific service/file/place using the proper means to
* do so.
*
*
* @author Florian Reimair
*/
public abstract class Reporter extends Configurable {
public Reporter() {
protected Reporter() {
setName(this.getClass().getSimpleName());
}
/**
* Report our findings.
*
*
* @param value
*/
public abstract void report(long value);
/**
* Report our findings
*
* @param l
*
* @param value
* @param prefix
*/
public abstract void report(long value, String prefix);
/**
* Report our findings.
*
*
* @param values Map<metric name, metric value>
*/
public abstract void report(Map<String, String> values);
/**
* Report our findings.
*
*
* @param values Map<metric name, metric value>
* @param prefix for example "bisq.torStartupTime"
*/

View File

@ -17,19 +17,19 @@
package bisq.monitor.metric;
import java.io.File;
import java.io.IOException;
import bisq.monitor.Metric;
import bisq.monitor.Reporter;
import org.berndpruenster.netlayer.tor.HiddenServiceSocket;
import bisq.monitor.Metric;
import bisq.monitor.Reporter;
import java.io.File;
import lombok.extern.slf4j.Slf4j;
/**
* A Metric to measure the startup time of a Tor Hidden Service on a already
* running Tor.
*
*
* @author Florian Reimair
*/
@Slf4j
@ -39,7 +39,7 @@ public class TorHiddenServiceStartupTime extends Metric {
private static final String LOCAL_PORT = "run.localPort";
private final String hiddenServiceDirectory = "metric_" + getName();
public TorHiddenServiceStartupTime(Reporter reporter) throws IOException {
public TorHiddenServiceStartupTime(Reporter reporter) {
super(reporter);
}
@ -66,12 +66,12 @@ public class TorHiddenServiceStartupTime extends Metric {
@Override
protected void execute() {
// prepare settings. Fetch them everytime we run the Metric so we do not have to
// prepare settings. Fetch them every time we run the Metric so we do not have to
// restart on a config update
int localPort = Integer.parseInt(configuration.getProperty(LOCAL_PORT, "9998"));
int servicePort = Integer.parseInt(configuration.getProperty(SERVICE_PORT, "9999"));
// clear directory so we get a new onion address everytime
// clear directory so we get a new onion address every time
new File(hiddenServiceDirectory).delete();
log.debug("creating the hidden service");
@ -90,8 +90,8 @@ public class TorHiddenServiceStartupTime extends Metric {
});
await();
log.debug("going to unpublish the hidden service...");
log.debug("going to revoke the hidden service...");
hiddenServiceSocket.close();
log.debug("[going to unpublish the hidden service...] done");
log.debug("[going to revoke the hidden service...] done");
}
}

View File

@ -17,8 +17,19 @@
package bisq.monitor.metric;
import java.io.IOException;
import bisq.monitor.Metric;
import bisq.monitor.Reporter;
import org.berndpruenster.netlayer.tor.Tor;
import org.berndpruenster.netlayer.tor.TorCtlException;
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
import com.runjva.sourceforge.jsocks.protocol.SocksSocket;
import java.net.URL;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -26,34 +37,30 @@ import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.Map;
import org.berndpruenster.netlayer.tor.Tor;
import org.berndpruenster.netlayer.tor.TorCtlException;
import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;
import com.runjva.sourceforge.jsocks.protocol.SocksSocket;
import bisq.monitor.Metric;
import bisq.monitor.Reporter;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A Metric to measure the round-trip time to the Bisq seednodes via plain tor.
*
* A Metric to measure the round-trip time to the Bisq seed nodes via plain tor.
*
* @author Florian Reimair
*/
public class TorRoundtripTime extends Metric {
public class TorRoundTripTime extends Metric {
private static final String SAMPLE_SIZE = "run.sampleSize";
private static final String HOSTS = "run.hosts";
public TorRoundtripTime(Reporter reporter) {
public TorRoundTripTime(Reporter reporter) {
super(reporter);
}
@Override
protected void execute() {
SocksSocket socket = null;
SocksSocket socket;
try {
// fetch proxy
Socks5Proxy proxy = Tor.getDefault().getProxy();
Tor tor = Tor.getDefault();
checkNotNull(tor, "tor must not be null");
Socks5Proxy proxy = tor.getProxy();
// for each configured host
for (String current : configuration.getProperty(HOSTS, "").split(",")) {
@ -80,7 +87,7 @@ public class TorRoundtripTime extends Metric {
// aftermath
Collections.sort(samples);
// - average, max, min , samplesize
// - average, max, min , sample size
LongSummaryStatistics statistics = samples.stream().mapToLong(val -> val).summaryStatistics();
Map<String, String> results = new HashMap<>();
@ -91,7 +98,7 @@ public class TorRoundtripTime extends Metric {
// - p25, median, p75
Integer[] percentiles = new Integer[]{25, 50, 75};
for(Integer percentile : percentiles) {
for (Integer percentile : percentiles) {
double rank = statistics.getCount() * percentile / 100;
Long percentileValue;
if (samples.size() <= rank + 1)
@ -101,7 +108,7 @@ public class TorRoundtripTime extends Metric {
else
percentileValue = Math.round(samples.get((int) Math.floor(rank))
+ (samples.get((int) (Math.floor(rank) + 1)) - samples.get((int) Math.floor(rank)))
/ (rank - Math.floor(rank)));
/ (rank - Math.floor(rank)));
results.put("p" + percentile, String.valueOf(percentileValue));
}

View File

@ -17,23 +17,24 @@
package bisq.monitor.metric;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Properties;
import bisq.monitor.Metric;
import bisq.monitor.Reporter;
import org.berndpruenster.netlayer.tor.NativeTor;
import org.berndpruenster.netlayer.tor.Tor;
import org.berndpruenster.netlayer.tor.TorCtlException;
import org.berndpruenster.netlayer.tor.Torrc;
import bisq.monitor.Metric;
import bisq.monitor.Reporter;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Properties;
/**
* A Metric to measure the deployment and startup time of the packaged Tor
* binaries.
*
*
* @author Florian Reimair
*/
public class TorStartupTime extends Metric {
@ -51,7 +52,7 @@ public class TorStartupTime extends Metric {
super.configure(properties);
synchronized (this) {
LinkedHashMap<String, String> overrides = new LinkedHashMap<String, String>();
LinkedHashMap<String, String> overrides = new LinkedHashMap<>();
overrides.put("SOCKSPort", configuration.getProperty(SOCKS_PORT, "90500"));
try {

View File

@ -17,21 +17,21 @@
package bisq.monitor.reporter;
import bisq.monitor.Reporter;
import java.util.HashMap;
import java.util.Map;
import bisq.monitor.Reporter;
/**
* A simple console reporter.
*
*
* @author Florian Reimair
*/
public class ConsoleReporter extends Reporter {
@Override
public void report(long value, String prefix) {
HashMap<String, String> result = new HashMap<String, String>();
HashMap<String, String> result = new HashMap<>();
result.put("", String.valueOf(value));
report(result, "bisq");
@ -39,7 +39,7 @@ public class ConsoleReporter extends Reporter {
@Override
public void report(long value) {
HashMap<String, String> result = new HashMap<String, String>();
HashMap<String, String> result = new HashMap<>();
result.put("", String.valueOf(value));
report(result);
}

View File

@ -17,25 +17,27 @@
package bisq.monitor.reporter;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import bisq.monitor.Reporter;
import org.berndpruenster.netlayer.tor.TorSocket;
import bisq.monitor.Reporter;
import java.net.URL;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Reports our findings to a graphite service.
*
*
* @author Florian Reimair
*/
public class GraphiteReporter extends Reporter {
@Override
public void report(long value, String prefix) {
HashMap<String, String> result = new HashMap<String, String>();
HashMap<String, String> result = new HashMap<>();
result.put("", String.valueOf(value));
report(result, prefix);

View File

@ -12,11 +12,11 @@ TorStartupTime.enabled=true
TorStartupTime.run.interval=100
TorStartupTime.run.socksPort=90500
TorRoundtripTime.enabled=true
TorRoundtripTime.run.interval=100
TorRoundtripTime.run.sampleSize=3
TorRoundTripTime.enabled=true
TorRoundTripTime.run.interval=100
TorRoundTripTime.run.sampleSize=3
# torproject.org hidden service
TorRoundtripTime.run.hosts=http://expyuzz4wqqyqhjn.onion:80
TorRoundTripTime.run.hosts=http://expyuzz4wqqyqhjn.onion:80
#TorHiddenServiceStartupTime Metric
TorHiddenServiceStartupTime.enabled=true
@ -32,4 +32,4 @@ Another.run.interval=5
## In contrast to Metrics, Reporters do not have a minimal set of properties.
#GraphiteReporter
GraphiteReporter.serviceUrl=http://k6evlhg44acpchtc.onion:2003
GraphiteReporter.serviceUrl=http://k6evlhg44acpchtc.onion:2003

View File

@ -17,6 +17,8 @@
package bisq.monitor;
import bisq.monitor.reporter.ConsoleReporter;
import java.util.HashMap;
import java.util.Properties;
@ -25,8 +27,6 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import bisq.monitor.reporter.ConsoleReporter;
public class MonitorInfrastructureTests {
/**
@ -50,7 +50,7 @@ public class MonitorInfrastructureTests {
@ParameterizedTest
@ValueSource(strings = { "empty", "no interval", "typo" })
public void basicConfigurationError(String configuration) throws Exception {
public void basicConfigurationError(String configuration) {
HashMap<String, Properties> lut = new HashMap<>();
lut.put("empty", new Properties());
Properties noInterval = new Properties();
@ -58,6 +58,7 @@ public class MonitorInfrastructureTests {
lut.put("no interval", noInterval);
Properties typo = new Properties();
typo.put("Dummy.enabled", "true");
//noinspection SpellCheckingInspection
typo.put("Dummy.run.inteval", "1");
lut.put("typo", typo);

View File

@ -17,23 +17,29 @@
package bisq.monitor;
import java.io.File;
import java.util.Map;
import java.util.Properties;
import bisq.monitor.metric.TorHiddenServiceStartupTime;
import org.berndpruenster.netlayer.tor.NativeTor;
import org.berndpruenster.netlayer.tor.Tor;
import org.berndpruenster.netlayer.tor.TorCtlException;
import java.io.File;
import java.util.Map;
import java.util.Properties;
import org.junit.Assert;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import bisq.monitor.metric.TorHiddenServiceStartupTime;
import static com.google.common.base.Preconditions.checkNotNull;
@Disabled // Ignore for normal test runs as the tests take lots of time
public class TorHiddenServiceStartupTimeTests {
private final static File torWorkingDirectory = new File(TorHiddenServiceStartupTimeTests.class.getSimpleName());
private final static File torWorkingDirectory = new File("monitor/" + TorHiddenServiceStartupTimeTests.class.getSimpleName());
/**
* A dummy Reporter for development purposes.
@ -96,7 +102,9 @@ public class TorHiddenServiceStartupTimeTests {
@AfterAll
public static void cleanup() {
Tor.getDefault().shutdown();
Tor tor = Tor.getDefault();
checkNotNull(tor, "tor must not be null");
tor.shutdown();
torWorkingDirectory.delete();
}
}

View File

@ -17,27 +17,33 @@
package bisq.monitor;
import java.io.File;
import java.util.Map;
import java.util.Properties;
import bisq.monitor.metric.TorRoundTripTime;
import org.berndpruenster.netlayer.tor.NativeTor;
import org.berndpruenster.netlayer.tor.Tor;
import org.berndpruenster.netlayer.tor.TorCtlException;
import java.io.File;
import java.util.Map;
import java.util.Properties;
import org.junit.Assert;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import bisq.monitor.metric.TorRoundtripTime;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Test the roundtrip time metric against the hidden service of torproject.org.
*
* Test the round trip time metric against the hidden service of tor project.org.
*
* @author Florian Reimair
*/
public class TorRoundtripTimeTests {
@Disabled // Ignore for normal test runs as the tests take lots of time
public class TorRoundTripTimeTests {
/**
* A dummy Reporter for development purposes.
@ -71,7 +77,7 @@ public class TorRoundtripTimeTests {
}
}
private static File workingDirectory = new File(TorRoundtripTimeTests.class.getSimpleName());
private static final File workingDirectory = new File(TorRoundTripTimeTests.class.getSimpleName());
@BeforeAll
public static void setup() throws TorCtlException {
@ -80,20 +86,20 @@ public class TorRoundtripTimeTests {
}
@ParameterizedTest
@ValueSource(strings = { "default", "3", "4", "10" })
@ValueSource(strings = {"default", "3", "4", "10"})
public void run(String sampleSize) throws Exception {
DummyReporter reporter = new DummyReporter();
// configure
Properties configuration = new Properties();
configuration.put("TorRoundtripTime.enabled", "true");
configuration.put("TorRoundtripTime.run.interval", "2");
configuration.put("TorRoundTripTime.enabled", "true");
configuration.put("TorRoundTripTime.run.interval", "2");
if (!"default".equals(sampleSize))
configuration.put("TorRoundtripTime.run.sampleSize", sampleSize);
configuration.put("TorRoundTripTime.run.sampleSize", sampleSize);
// torproject.org hidden service
configuration.put("TorRoundtripTime.run.hosts", "http://expyuzz4wqqyqhjn.onion:80");
configuration.put("TorRoundTripTime.run.hosts", "http://expyuzz4wqqyqhjn.onion:80");
Metric DUT = new TorRoundtripTime(reporter);
Metric DUT = new TorRoundTripTime(reporter);
// start
DUT.configure(configuration);
@ -124,7 +130,9 @@ public class TorRoundtripTimeTests {
@AfterAll
public static void cleanup() {
Tor.getDefault().shutdown();
Tor tor = Tor.getDefault();
checkNotNull(tor, "tor must not be null");
tor.shutdown();
workingDirectory.delete();
}
}

View File

@ -17,14 +17,16 @@
package bisq.monitor;
import bisq.monitor.metric.TorStartupTime;
import java.util.Map;
import java.util.Properties;
import org.junit.Assert;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import bisq.monitor.metric.TorStartupTime;
@Disabled // Ignore for normal test runs as the tests take lots of time
public class TorStartupTimeTests {
/**
@ -78,6 +80,7 @@ public class TorStartupTimeTests {
Thread.sleep(15 * 1000);
DUT.shutdown();
// TODO Test fails due timing issue
// observe results
Assert.assertTrue(reporter.results() > 0);
}