diff --git a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MonitorP2PModule.java b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MonitorP2PModule.java index 80e8571150..32bad2ab14 100644 --- a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MonitorP2PModule.java +++ b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MonitorP2PModule.java @@ -32,6 +32,7 @@ import io.bisq.network.p2p.peers.getdata.RequestDataManager; import io.bisq.network.p2p.peers.keepalive.KeepAliveManager; import io.bisq.network.p2p.peers.peerexchange.PeerExchangeManager; import io.bisq.network.p2p.storage.P2PDataStorage; +import io.bisq.seednode_monitor.metrics.MetricsModel; import org.springframework.core.env.Environment; import java.io.File; @@ -47,7 +48,7 @@ public class MonitorP2PModule extends AppModule { @Override protected void configure() { - bind(MetricsByNodeAddressMap.class).in(Singleton.class); + bind(MetricsModel.class).in(Singleton.class); bind(MonitorP2PService.class).in(Singleton.class); bind(PeerManager.class).in(Singleton.class); diff --git a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MonitorP2PService.java b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MonitorP2PService.java index 68b2291dd8..9421778dfd 100644 --- a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MonitorP2PService.java +++ b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MonitorP2PService.java @@ -23,7 +23,7 @@ import io.bisq.network.Socks5ProxyProvider; import io.bisq.network.p2p.network.NetworkNode; import io.bisq.network.p2p.network.SetupListener; import io.bisq.network.p2p.storage.P2PDataStorage; -import io.bisq.seednode_monitor.request.MonitorRequestManager; +import io.bisq.seednode_monitor.metrics.MonitorRequestManager; import lombok.Getter; import lombok.extern.slf4j.Slf4j; diff --git a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/SeedNodeMonitor.java b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/SeedNodeMonitor.java index 35b792c6d4..284c49e4c8 100644 --- a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/SeedNodeMonitor.java +++ b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/SeedNodeMonitor.java @@ -20,6 +20,7 @@ import io.bisq.core.btc.wallet.BsqWalletService; import io.bisq.core.btc.wallet.BtcWalletService; import io.bisq.core.btc.wallet.WalletsSetup; import io.bisq.core.offer.OpenOfferManager; +import io.bisq.seednode_monitor.metrics.MetricsModel; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -36,7 +37,7 @@ public class SeedNodeMonitor { private static SeedNodeMonitorEnvironment environment; @Getter - private final MetricsByNodeAddressMap metricsByNodeAddressMap; + private final MetricsModel metricsService; public static void setEnvironment(SeedNodeMonitorEnvironment environment) { SeedNodeMonitor.environment = environment; @@ -96,7 +97,7 @@ public class SeedNodeMonitor { seedNodeModule = new SeedNodeMonitorModule(environment); injector = Guice.createInjector(seedNodeModule); - metricsByNodeAddressMap = injector.getInstance(MetricsByNodeAddressMap.class); + metricsService = injector.getInstance(MetricsModel.class); MonitorAppSetup appSetup = injector.getInstance(MonitorAppSetup.class); appSetup.start(); diff --git a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/SeedNodeMonitorMain.java b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/SeedNodeMonitorMain.java index b898c843df..86dd891db8 100644 --- a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/SeedNodeMonitorMain.java +++ b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/SeedNodeMonitorMain.java @@ -99,7 +99,7 @@ public class SeedNodeMonitorMain extends BisqExecutable { port(8080); get("/", (req, res) -> { log.info("Incoming request from: " + req.userAgent()); - return seedNodeMonitor.getMetricsByNodeAddressMap().getResultAsHtml(); + return seedNodeMonitor.getMetricsService().getResultAsHtml(); }); new SeedNodeMonitorMain().execute(args); diff --git a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/Metrics.java b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/Metrics.java similarity index 95% rename from seednode_monitor/src/main/java/io/bisq/seednode_monitor/Metrics.java rename to seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/Metrics.java index 59288c2f02..cb26f4987a 100644 --- a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/Metrics.java +++ b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/Metrics.java @@ -15,7 +15,7 @@ * along with bisq. If not, see . */ -package io.bisq.seednode_monitor; +package io.bisq.seednode_monitor.metrics; import lombok.Getter; diff --git a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MetricsByNodeAddressMap.java b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/MetricsModel.java similarity index 89% rename from seednode_monitor/src/main/java/io/bisq/seednode_monitor/MetricsByNodeAddressMap.java rename to seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/MetricsModel.java index ae15b6bdcd..419cc8f3a3 100644 --- a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/MetricsByNodeAddressMap.java +++ b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/MetricsModel.java @@ -15,11 +15,12 @@ * along with bisq. If not, see . */ -package io.bisq.seednode_monitor; +package io.bisq.seednode_monitor.metrics; import io.bisq.common.util.MathUtils; import io.bisq.network.p2p.NodeAddress; import io.bisq.network.p2p.seed.SeedNodesRepository; +import io.bisq.seednode_monitor.MonitorOptionKeys; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -32,7 +33,7 @@ import java.util.*; import java.util.stream.Collectors; @Slf4j -public class MetricsByNodeAddressMap extends HashMap { +public class MetricsModel { private SlackApi slackApi; @Getter private String resultAsString; @@ -42,26 +43,34 @@ public class MetricsByNodeAddressMap extends HashMap { @Setter private long lastCheckTs; private int totalErrors = 0; + private HashMap map = new HashMap<>(); @Inject - public MetricsByNodeAddressMap(SeedNodesRepository seedNodesRepository, - @Named(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL) String slackUrlSeedChannel) { + public MetricsModel(SeedNodesRepository seedNodesRepository, + @Named(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL) String slackUrlSeedChannel) { this.seedNodesRepository = seedNodesRepository; if (!slackUrlSeedChannel.isEmpty()) slackApi = new SlackApi(slackUrlSeedChannel); } + public void addToMap(NodeAddress nodeAddress, Metrics metrics) { + map.put(nodeAddress, metrics); + } + + public Metrics getMetrics(NodeAddress nodeAddress) { + return map.get(nodeAddress); + } public void updateReport() { Map accumulatedValues = new HashMap<>(); final double[] items = {0}; - List> entryList = entrySet().stream() + List> entryList = map.entrySet().stream() .sorted(Comparator.comparing(entrySet -> seedNodesRepository.getOperator(entrySet.getKey()))) .collect(Collectors.toList()); totalErrors = 0; entryList.stream().forEach(e -> { - totalErrors += e.getValue().errorMessages.size(); + totalErrors += e.getValue().errorMessages.stream().filter(s -> !s.isEmpty()).count(); final List> receivedObjectsList = e.getValue().getReceivedObjectsList(); if (!receivedObjectsList.isEmpty()) { items[0] += 1; @@ -109,7 +118,7 @@ public class MetricsByNodeAddressMap extends HashMap { StringBuilder sb = new StringBuilder(); sb.append("Seed nodes in error:" + totalErrors); - sb.append("\nLast check started at: " + time); + sb.append("\nLast check started at: " + time + "\n"); entryList.stream().forEach(e -> { final List allDurations = e.getValue().getRequestDurations(); @@ -182,8 +191,8 @@ public class MetricsByNodeAddressMap extends HashMap { "Please check the monitoring status page at http://seedmonitor.0-2-1.net:8080/")); } }); - sb.append("\nDuration all requests: ").append(allDurationsString) - .append("\nAll data: ").append(allReceivedDataString); + sb.append("Duration all requests: ").append(allDurationsString) + .append("\nAll data: ").append(allReceivedDataString).append("\n"); html.append(""); } @@ -191,12 +200,11 @@ public class MetricsByNodeAddressMap extends HashMap { html.append(""); resultAsString = sb.toString(); resultAsHtml = html.toString(); - log(); } public void log() { - log.info("\n#################################################################\n" + + log.info("\n\n#################################################################\n" + resultAsString + - "\n#################################################################\n\n"); + "#################################################################\n\n"); } } diff --git a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/request/MonitorRequestHandler.java b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/MonitorRequestHandler.java similarity index 97% rename from seednode_monitor/src/main/java/io/bisq/seednode_monitor/request/MonitorRequestHandler.java rename to seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/MonitorRequestHandler.java index d50d289a67..9996c6cba6 100644 --- a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/request/MonitorRequestHandler.java +++ b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/MonitorRequestHandler.java @@ -1,4 +1,4 @@ -package io.bisq.seednode_monitor.request; +package io.bisq.seednode_monitor.metrics; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -21,7 +21,6 @@ import io.bisq.network.p2p.storage.P2PDataStorage; import io.bisq.network.p2p.storage.payload.PersistableNetworkPayload; import io.bisq.network.p2p.storage.payload.ProtectedStorageEntry; import io.bisq.network.p2p.storage.payload.ProtectedStoragePayload; -import io.bisq.seednode_monitor.Metrics; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; @@ -111,14 +110,14 @@ class MonitorRequestHandler implements MessageListener { }, TIMEOUT_SEC); - log.info("We send a {} to peer {}. ", getDataRequest.getClass().getSimpleName(), nodeAddress); + 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 " + getDataRequest + " to " + nodeAddress + " has succeeded."); + 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."); diff --git a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/request/MonitorRequestManager.java b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/MonitorRequestManager.java similarity index 80% rename from seednode_monitor/src/main/java/io/bisq/seednode_monitor/request/MonitorRequestManager.java rename to seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/MonitorRequestManager.java index ca54fd63df..40842bf9ff 100644 --- a/seednode_monitor/src/main/java/io/bisq/seednode_monitor/request/MonitorRequestManager.java +++ b/seednode_monitor/src/main/java/io/bisq/seednode_monitor/metrics/MonitorRequestManager.java @@ -1,6 +1,5 @@ -package io.bisq.seednode_monitor.request; +package io.bisq.seednode_monitor.metrics; -import io.bisq.common.Clock; import io.bisq.common.Timer; import io.bisq.common.UserThread; import io.bisq.network.p2p.NodeAddress; @@ -10,8 +9,6 @@ import io.bisq.network.p2p.network.ConnectionListener; import io.bisq.network.p2p.network.NetworkNode; import io.bisq.network.p2p.seed.SeedNodesRepository; import io.bisq.network.p2p.storage.P2PDataStorage; -import io.bisq.seednode_monitor.Metrics; -import io.bisq.seednode_monitor.MetricsByNodeAddressMap; import io.bisq.seednode_monitor.MonitorOptionKeys; import lombok.extern.slf4j.Slf4j; import net.gpedro.integrations.slack.SlackApi; @@ -24,10 +21,10 @@ import java.util.concurrent.TimeUnit; @Slf4j public class MonitorRequestManager implements ConnectionListener { - private static final long RETRY_DELAY_SEC = 30; + private static final long RETRY_DELAY_SEC = 20; private static final long CLEANUP_TIMER = 60; private static final long REQUEST_PERIOD_MIN = 10; - private static final int MAX_RETRIES = 4; + private static final int MAX_RETRIES = 6; /////////////////////////////////////////////////////////////////////////////////////////// @@ -35,11 +32,12 @@ public class MonitorRequestManager implements ConnectionListener { /////////////////////////////////////////////////////////////////////////////////////////// private final NetworkNode networkNode; + private final int numNodes; + private SlackApi slackApi; private P2PDataStorage dataStorage; private SeedNodesRepository seedNodesRepository; - private MetricsByNodeAddressMap metricsByNodeAddressMap; - private Clock clock; + private MetricsModel metricsModel; private final Set seedNodeAddresses; private final Map handlerMap = new HashMap<>(); @@ -47,7 +45,7 @@ public class MonitorRequestManager implements ConnectionListener { private Map retryCounterMap = new HashMap<>(); private boolean stopped; private Set nodesInError = new HashSet<>(); - + private int completedRequestIndex; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor @@ -57,21 +55,20 @@ public class MonitorRequestManager implements ConnectionListener { public MonitorRequestManager(NetworkNode networkNode, P2PDataStorage dataStorage, SeedNodesRepository seedNodesRepository, - MetricsByNodeAddressMap metricsByNodeAddressMap, - Clock clock, + MetricsModel metricsModel, @Named(MonitorOptionKeys.SLACK_URL_SEED_CHANNEL) String slackUrlSeedChannel) { this.networkNode = networkNode; this.dataStorage = dataStorage; this.seedNodesRepository = seedNodesRepository; - this.metricsByNodeAddressMap = metricsByNodeAddressMap; - this.clock = clock; + this.metricsModel = metricsModel; if (!slackUrlSeedChannel.isEmpty()) slackApi = new SlackApi(slackUrlSeedChannel); this.networkNode.addConnectionListener(this); seedNodeAddresses = new HashSet<>(seedNodesRepository.getSeedNodeAddresses()); - seedNodeAddresses.stream().forEach(nodeAddress -> metricsByNodeAddressMap.put(nodeAddress, new Metrics())); + seedNodeAddresses.stream().forEach(nodeAddress -> metricsModel.addToMap(nodeAddress, new Metrics())); + numNodes = seedNodeAddresses.size(); } public void shutDown() { @@ -87,39 +84,21 @@ public class MonitorRequestManager implements ConnectionListener { /////////////////////////////////////////////////////////////////////////////////////////// public void start() { - // We want get the logs each 10 minutes - clock.start(); - clock.addListener(new Clock.Listener() { - @Override - public void onSecondTick() { - } - - @Override - public void onMinuteTick() { - processOnMinuteTick(); - } - - @Override - public void onMissedSecondTick(long missed) { - } - }); + requestAllNodes(); + UserThread.runPeriodically(this::requestAllNodes, REQUEST_PERIOD_MIN, TimeUnit.MINUTES); } - private void processOnMinuteTick() { - long minutes = System.currentTimeMillis() / 1000 / 60; - final long currentTimeMillis = System.currentTimeMillis(); - if (minutes % REQUEST_PERIOD_MIN == 0) { - stopAllRetryTimers(); - closeAllConnections(); + private void requestAllNodes() { + stopAllRetryTimers(); + closeAllConnections(); + // we give 1 sec. for all connection shutdown + final int[] delay = {1000}; + metricsModel.setLastCheckTs(System.currentTimeMillis()); - // we give 1 sec. for all connection shutdown - final int[] delay = {1000}; - metricsByNodeAddressMap.setLastCheckTs(currentTimeMillis); - seedNodeAddresses.stream().forEach(nodeAddress -> { - UserThread.runAfter(() -> requestData(nodeAddress), delay[0], TimeUnit.MILLISECONDS); - delay[0] += 100; - }); - } + seedNodeAddresses.stream().forEach(nodeAddress -> { + UserThread.runAfter(() -> requestFromNode(nodeAddress), delay[0], TimeUnit.MILLISECONDS); + delay[0] += 100; + }); } @@ -145,12 +124,12 @@ public class MonitorRequestManager implements ConnectionListener { // RequestData /////////////////////////////////////////////////////////////////////////////////////////// - private void requestData(NodeAddress nodeAddress) { + private void requestFromNode(NodeAddress nodeAddress) { if (!stopped) { if (!handlerMap.containsKey(nodeAddress)) { MonitorRequestHandler requestDataHandler = new MonitorRequestHandler(networkNode, dataStorage, - metricsByNodeAddressMap.get(nodeAddress), + metricsModel.getMetrics(nodeAddress), new MonitorRequestHandler.Listener() { @Override public void onComplete() { @@ -162,8 +141,10 @@ public class MonitorRequestManager implements ConnectionListener { // need to remove before listeners are notified as they cause the update call handlerMap.remove(nodeAddress); - metricsByNodeAddressMap.updateReport(); - metricsByNodeAddressMap.log(); + metricsModel.updateReport(); + completedRequestIndex++; + if (completedRequestIndex == numNodes) + metricsModel.log(); if (nodesInError.contains(nodeAddress)) { nodesInError.remove(nodeAddress); @@ -176,9 +157,6 @@ public class MonitorRequestManager implements ConnectionListener { @Override public void onFault(String errorMessage, NodeAddress nodeAddress) { handlerMap.remove(nodeAddress); - metricsByNodeAddressMap.updateReport(); - metricsByNodeAddressMap.log(); - int retryCounter; if (retryCounterMap.containsKey(nodeAddress)) retryCounter = retryCounterMap.get(nodeAddress); @@ -186,10 +164,14 @@ public class MonitorRequestManager implements ConnectionListener { retryCounter = 0; if (retryCounter < MAX_RETRIES) { - final Timer timer = UserThread.runAfter(() -> requestData(nodeAddress), RETRY_DELAY_SEC); + final Timer timer = UserThread.runAfter(() -> requestFromNode(nodeAddress), RETRY_DELAY_SEC); retryTimerMap.put(nodeAddress, timer); retryCounterMap.put(nodeAddress, ++retryCounter); } else { + metricsModel.updateReport(); + completedRequestIndex++; + if (completedRequestIndex == numNodes) + metricsModel.log(); nodesInError.add(nodeAddress); if (slackApi != null) slackApi.call(new SlackMessage("Error: " + nodeAddress.getFullAddress(),