mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-21 14:24:06 +01:00
Add inventory module
Simple monitor dumping json files with data result and request/response time to disk. Can be used by a simple web server to show state of seed nodes.
This commit is contained in:
parent
55b693e295
commit
3521619e03
5 changed files with 322 additions and 0 deletions
13
build.gradle
13
build.gradle
|
@ -99,6 +99,7 @@ configure([project(':cli'),
|
|||
project(':seednode'),
|
||||
project(':statsnode'),
|
||||
project(':pricenode'),
|
||||
project(':inventory'),
|
||||
project(':apitest')]) {
|
||||
|
||||
apply plugin: 'application'
|
||||
|
@ -594,6 +595,18 @@ configure(project(':daemon')) {
|
|||
}
|
||||
}
|
||||
|
||||
configure(project(':inventory')) {
|
||||
mainClassName = 'bisq.inventory.InventoryMonitorMain'
|
||||
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile "com.google.guava:guava:$guavaVersion"
|
||||
|
||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||
}
|
||||
}
|
||||
|
||||
configure(project(':apitest')) {
|
||||
mainClassName = 'bisq.apitest.ApiTestMain'
|
||||
|
||||
|
|
186
inventory/src/main/java/bisq/inventory/InventoryMonitor.java
Normal file
186
inventory/src/main/java/bisq/inventory/InventoryMonitor.java
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.inventory;
|
||||
|
||||
|
||||
import bisq.core.network.p2p.seed.DefaultSeedNodeRepository;
|
||||
import bisq.core.proto.network.CoreNetworkProtoResolver;
|
||||
|
||||
import bisq.network.p2p.NetworkNodeProvider;
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
import bisq.network.p2p.inventory.GetInventoryRequestManager;
|
||||
import bisq.network.p2p.network.NetworkNode;
|
||||
import bisq.network.p2p.network.SetupListener;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.Capabilities;
|
||||
import bisq.common.app.Capability;
|
||||
import bisq.common.config.BaseCurrencyNetwork;
|
||||
import bisq.common.file.JsonFileManager;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Slf4j
|
||||
public class InventoryMonitor {
|
||||
|
||||
private final NetworkNode networkNode;
|
||||
private final GetInventoryRequestManager getInventoryRequestManager;
|
||||
private final List<NodeAddress> seedNodes = new ArrayList<>();
|
||||
private final Map<NodeAddress, JsonFileManager> jsonFileManagerByNodeAddress = new HashMap<>();
|
||||
private final boolean useLocalhostForP2P;
|
||||
private final int intervalSec;
|
||||
|
||||
public InventoryMonitor(File appDir,
|
||||
boolean useLocalhostForP2P,
|
||||
BaseCurrencyNetwork network,
|
||||
int intervalSec) {
|
||||
this.useLocalhostForP2P = useLocalhostForP2P;
|
||||
this.intervalSec = intervalSec;
|
||||
Capabilities.app.addAll(
|
||||
Capability.TRADE_STATISTICS,
|
||||
Capability.TRADE_STATISTICS_2,
|
||||
Capability.ACCOUNT_AGE_WITNESS,
|
||||
Capability.ACK_MSG,
|
||||
Capability.PROPOSAL,
|
||||
Capability.BLIND_VOTE,
|
||||
Capability.DAO_STATE,
|
||||
Capability.BUNDLE_OF_ENVELOPES,
|
||||
Capability.MEDIATION,
|
||||
Capability.SIGNED_ACCOUNT_AGE_WITNESS,
|
||||
Capability.REFUND_AGENT,
|
||||
Capability.TRADE_STATISTICS_HASH_UPDATE,
|
||||
Capability.NO_ADDRESS_PRE_FIX,
|
||||
Capability.TRADE_STATISTICS_3,
|
||||
Capability.RECEIVE_BSQ_BLOCK
|
||||
);
|
||||
|
||||
networkNode = new NetworkNodeProvider(new CoreNetworkProtoResolver(Clock.systemDefaultZone()),
|
||||
ArrayList::new,
|
||||
useLocalhostForP2P,
|
||||
9999,
|
||||
new File(appDir, "tor"),
|
||||
null,
|
||||
"",
|
||||
-1,
|
||||
"",
|
||||
null,
|
||||
false,
|
||||
false).get();
|
||||
getInventoryRequestManager = new GetInventoryRequestManager(networkNode);
|
||||
|
||||
seedNodes.addAll(DefaultSeedNodeRepository.getSeedNodeAddressesFromPropertyFile(network));
|
||||
|
||||
File jsonDir = new File(appDir, "json");
|
||||
if (!jsonDir.exists() && !jsonDir.mkdir()) {
|
||||
log.warn("make jsonDir failed");
|
||||
}
|
||||
seedNodes.forEach(nodeAddress -> {
|
||||
JsonFileManager jsonFileManager = new JsonFileManager(new File(jsonDir, getShortAddress(nodeAddress, useLocalhostForP2P)));
|
||||
jsonFileManagerByNodeAddress.put(nodeAddress, jsonFileManager);
|
||||
});
|
||||
|
||||
networkNode.start(new SetupListener() {
|
||||
@Override
|
||||
public void onTorNodeReady() {
|
||||
startRequests();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHiddenServicePublished() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetupFailed(Throwable throwable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestCustomBridges() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getShortAddress(NodeAddress nodeAddress, boolean useLocalhostForP2P) {
|
||||
return useLocalhostForP2P ?
|
||||
nodeAddress.getFullAddress().replace(":", "_") :
|
||||
nodeAddress.getFullAddress().substring(0, 10);
|
||||
}
|
||||
|
||||
private void startRequests() {
|
||||
UserThread.runPeriodically(this::requestAllSeeds, intervalSec);
|
||||
requestAllSeeds();
|
||||
}
|
||||
|
||||
private void requestAllSeeds() {
|
||||
seedNodes.forEach(nodeAddress -> {
|
||||
RequestInfo requestInfo = new RequestInfo(System.currentTimeMillis());
|
||||
new Thread(() -> {
|
||||
Thread.currentThread().setName("request @ " + getShortAddress(nodeAddress, useLocalhostForP2P));
|
||||
getInventoryRequestManager.request(nodeAddress,
|
||||
result -> {
|
||||
log.info("nodeAddress={}, result={}", nodeAddress, result.toString());
|
||||
long responseTime = System.currentTimeMillis();
|
||||
requestInfo.setResponseTime(responseTime);
|
||||
requestInfo.setResult(result);
|
||||
String json = Utilities.objectToJson(requestInfo);
|
||||
jsonFileManagerByNodeAddress.get(nodeAddress).writeToDisc(json, String.valueOf(responseTime));
|
||||
},
|
||||
errorMessage -> {
|
||||
log.warn(errorMessage);
|
||||
requestInfo.setErrorMessage(errorMessage);
|
||||
});
|
||||
}).start();
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void shutDown() {
|
||||
jsonFileManagerByNodeAddress.values().forEach(JsonFileManager::shutDown);
|
||||
}
|
||||
|
||||
@Getter
|
||||
static class RequestInfo {
|
||||
private final long requestStartTime;
|
||||
@Setter
|
||||
private long responseTime;
|
||||
@Setter
|
||||
private Map<String, Integer> result;
|
||||
@Setter
|
||||
private String errorMessage;
|
||||
|
||||
public RequestInfo(long requestStartTime) {
|
||||
this.requestStartTime = requestStartTime;
|
||||
}
|
||||
}
|
||||
}
|
106
inventory/src/main/java/bisq/inventory/InventoryMonitorMain.java
Normal file
106
inventory/src/main/java/bisq/inventory/InventoryMonitorMain.java
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.inventory;
|
||||
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.app.Log;
|
||||
import bisq.common.app.Version;
|
||||
import bisq.common.config.BaseCurrencyNetwork;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
|
||||
import sun.misc.Signal;
|
||||
|
||||
@Slf4j
|
||||
public class InventoryMonitorMain {
|
||||
|
||||
private static InventoryMonitor inventoryMonitor;
|
||||
private static boolean stopped;
|
||||
|
||||
// prog args for regtest: 10 1 BTC_REGTEST
|
||||
public static void main(String[] args) {
|
||||
int intervalSec = 600;
|
||||
boolean useLocalhostForP2P = false;
|
||||
BaseCurrencyNetwork network = BaseCurrencyNetwork.BTC_MAINNET;
|
||||
|
||||
if (args.length > 0) {
|
||||
intervalSec = Integer.parseInt(args[0]);
|
||||
}
|
||||
if (args.length > 1) {
|
||||
useLocalhostForP2P = args[1].equals("1");
|
||||
}
|
||||
if (args.length > 2) {
|
||||
network = BaseCurrencyNetwork.valueOf(args[2]);
|
||||
}
|
||||
|
||||
String appName = "bisq-InventoryMonitor-" + network;
|
||||
|
||||
File appDir = new File(Utilities.getUserDataDir(), appName);
|
||||
String logPath = Paths.get(appDir.getPath(), "bisq").toString();
|
||||
Log.setup(logPath);
|
||||
Log.setLevel(Level.INFO);
|
||||
Version.setBaseCryptoNetworkId(network.ordinal());
|
||||
|
||||
inventoryMonitor = new InventoryMonitor(appDir, useLocalhostForP2P, network, intervalSec);
|
||||
|
||||
ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||
.setNameFormat(inventoryMonitor.getClass().getSimpleName())
|
||||
.setDaemon(true)
|
||||
.build();
|
||||
UserThread.setExecutor(Executors.newSingleThreadExecutor(threadFactory));
|
||||
|
||||
Signal.handle(new Signal("INT"), signal -> {
|
||||
shutDown();
|
||||
});
|
||||
|
||||
Signal.handle(new Signal("TERM"), signal -> {
|
||||
shutDown();
|
||||
});
|
||||
keepRunning();
|
||||
}
|
||||
|
||||
private static void shutDown() {
|
||||
inventoryMonitor.shutDown();
|
||||
stopped = true;
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private static void keepRunning() {
|
||||
while (!stopped) {
|
||||
try {
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
} catch (InterruptedException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
16
inventory/src/main/resources/logback.xml
Normal file
16
inventory/src/main/resources/logback.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="CONSOLE_APPENDER" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%highlight(%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{30}: %msg %xEx%n)</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="TRACE">
|
||||
<appender-ref ref="CONSOLE_APPENDER"/>
|
||||
</root>
|
||||
|
||||
<logger name="com.neemre.btcdcli4j" level="WARN"/>
|
||||
<logger name="com.neemre.btcdcli4j.core.client.ClientConfigurator" level="ERROR"/>
|
||||
|
||||
</configuration>
|
|
@ -11,6 +11,7 @@ include 'pricenode'
|
|||
include 'relay'
|
||||
include 'seednode'
|
||||
include 'statsnode'
|
||||
include 'inventory'
|
||||
include 'apitest'
|
||||
|
||||
rootProject.name = 'bisq'
|
||||
|
|
Loading…
Add table
Reference in a new issue