Add statistics dump for offers

This commit is contained in:
Manfred Karrer 2016-07-31 04:10:40 +02:00
parent 5c86e6ed5d
commit 814bf8d065
6 changed files with 144 additions and 91 deletions

View File

@ -76,6 +76,13 @@ public class Storage<T extends Serializable> {
this.dir = dir;
}
@Nullable
public void initWithFileName(String fileName) {
this.fileName = fileName;
storageFile = new File(dir, fileName);
fileManager = new FileManager<>(dir, storageFile, 300);
}
@Nullable
public T initAndGetPersistedWithFileName(String fileName) {
this.fileName = fileName;

View File

@ -0,0 +1,46 @@
package io.bitsquare.trade.offer;
import io.bitsquare.payment.PaymentMethod;
import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.Fiat;
import java.util.Date;
public class FlatOffer {
public final Offer.Direction direction;
public final String currencyCode;
public final long minAmount;
public final long amount;
public final long price;
public final long date;
public final boolean useMarketBasedPrice;
public final double marketPriceMargin;
public final String paymentMethod;
public final String id;
public final String offerFeeTxID;
public FlatOffer(Offer.Direction direction,
String currencyCode,
Coin minAmount,
Coin amount,
Fiat price,
Date date,
String id,
boolean useMarketBasedPrice,
double marketPriceMargin,
PaymentMethod paymentMethod,
String offerFeeTxID) {
this.direction = direction;
this.currencyCode = currencyCode;
this.minAmount = minAmount.value;
this.amount = amount.value;
this.price = price.value;
this.date = date.getTime();
this.id = id;
this.useMarketBasedPrice = useMarketBasedPrice;
this.marketPriceMargin = marketPriceMargin;
this.paymentMethod = paymentMethod.getId();
this.offerFeeTxID = offerFeeTxID;
}
}

View File

@ -17,12 +17,19 @@
package io.bitsquare.trade.offer;
import com.google.inject.name.Named;
import io.bitsquare.app.CoreOptionKeys;
import io.bitsquare.btc.pricefeed.PriceFeedService;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.handlers.ErrorMessageHandler;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.common.util.Utilities;
import io.bitsquare.p2p.BootstrapListener;
import io.bitsquare.p2p.P2PService;
import io.bitsquare.p2p.storage.HashMapChangedListener;
import io.bitsquare.p2p.storage.storageentry.ProtectedStorageEntry;
import io.bitsquare.storage.JsonString;
import io.bitsquare.storage.Storage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -47,6 +54,7 @@ public class OfferBookService {
private final P2PService p2PService;
private PriceFeedService priceFeedService;
private final Storage<JsonString> offersJsonStorage;
private final List<OfferBookChangedListener> offerBookChangedListeners = new LinkedList<>();
@ -55,9 +63,13 @@ public class OfferBookService {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public OfferBookService(P2PService p2PService, PriceFeedService priceFeedService) {
public OfferBookService(P2PService p2PService,
PriceFeedService priceFeedService,
Storage<JsonString> offersJsonStorage,
@Named(CoreOptionKeys.DUMP_STATISTICS) boolean dumpStatistics) {
this.p2PService = p2PService;
this.priceFeedService = priceFeedService;
this.offersJsonStorage = offersJsonStorage;
p2PService.addHashSetChangedListener(new HashMapChangedListener() {
@Override
@ -79,10 +91,28 @@ public class OfferBookService {
});
}
});
}
public void addOfferBookChangedListener(OfferBookChangedListener offerBookChangedListener) {
offerBookChangedListeners.add(offerBookChangedListener);
if (dumpStatistics) {
this.offersJsonStorage.initWithFileName("offers_statistics.json");
p2PService.addP2PServiceListener(new BootstrapListener() {
@Override
public void onBootstrapComplete() {
addOfferBookChangedListener(new OfferBookChangedListener() {
@Override
public void onAdded(Offer offer) {
doDumpStatistics();
}
@Override
public void onRemoved(Offer offer) {
doDumpStatistics();
}
});
UserThread.runAfter(OfferBookService.this::doDumpStatistics, 1);
}
});
}
}
@ -140,4 +170,41 @@ public class OfferBookService {
public boolean isBootstrapped() {
return p2PService.isBootstrapped();
}
public void addOfferBookChangedListener(OfferBookChangedListener offerBookChangedListener) {
offerBookChangedListeners.add(offerBookChangedListener);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void doDumpStatistics() {
final List<FlatOffer> flatOffers = getOffers().stream()
.filter(offer -> !offer.getUseMarketBasedPrice() || priceFeedService.getMarketPrice(offer.getCurrencyCode()) != null)
.map(offer -> {
try {
return new FlatOffer(offer.getDirection(),
offer.getCurrencyCode(),
offer.getMinAmount(),
offer.getAmount(),
offer.getPrice(),
offer.getDate(),
offer.getId(),
offer.getUseMarketBasedPrice(),
offer.getMarketPriceMargin(),
offer.getPaymentMethod(),
offer.getOfferFeePaymentTxID()
);
} catch (Throwable t) {
// In case a offer was corrupted with null values we ignore it
return null;
}
})
.filter(e -> e != null)
.collect(Collectors.toList());
offersJsonStorage.queueUpForSave(new JsonString(Utilities.objectToJson(flatOffers)), 5000);
}
}

View File

@ -47,15 +47,15 @@ public class TradeStatisticsManager {
this.dumpStatistics = dumpStatistics;
if (dumpStatistics) {
this.statisticsJsonStorage.initAndGetPersistedWithFileName("trade_statistics.json");
this.statisticsJsonStorage.initWithFileName("trade_statistics.json");
this.fiatCurrencyListJsonStorage.initAndGetPersistedWithFileName("fiat_currency_list.json");
this.fiatCurrencyListJsonStorage.initWithFileName("fiat_currency_list.json");
ArrayList<CurrencyTuple> fiatCurrencyList = new ArrayList<>(CurrencyUtil.getAllSortedFiatCurrencies().stream()
.map(e -> new CurrencyTuple(e.getCode(), e.getName()))
.collect(Collectors.toList()));
fiatCurrencyListJsonStorage.queueUpForSave(new JsonString(Utilities.objectToJson(fiatCurrencyList)), 2000);
this.cryptoCurrencyListJsonStorage.initAndGetPersistedWithFileName("crypto_currency_list.json");
this.cryptoCurrencyListJsonStorage.initWithFileName("crypto_currency_list.json");
ArrayList<CurrencyTuple> cryptoCurrencyList = new ArrayList<>(CurrencyUtil.getAllSortedCryptoCurrencies().stream()
.map(e -> new CurrencyTuple(e.getCode(), e.getName()))
.collect(Collectors.toList()));

View File

@ -13,8 +13,8 @@ import io.bitsquare.common.CommonOptionKeys;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.common.util.Utilities;
import io.bitsquare.p2p.BootstrapListener;
import io.bitsquare.p2p.P2PService;
import io.bitsquare.p2p.P2PServiceListener;
import io.bitsquare.trade.offer.OpenOfferManager;
import io.bitsquare.trade.statistics.TradeStatisticsManager;
import org.apache.commons.lang3.exception.ExceptionUtils;
@ -74,49 +74,9 @@ public class SeedNode {
injector = Guice.createInjector(seedNodeModule);
Version.setBtcNetworkId(injector.getInstance(BitsquareEnvironment.class).getBitcoinNetwork().ordinal());
p2pService = injector.getInstance(P2PService.class);
p2pService.start(false, new P2PServiceListener() {
@Override
public void onRequestingDataCompleted() {
}
@Override
public void onNoSeedNodeAvailable() {
}
@Override
public void onNoPeersAvailable() {
}
p2pService.start(false, new BootstrapListener() {
@Override
public void onBootstrapComplete() {
}
@Override
public void onTorNodeReady() {
}
@Override
public void onHiddenServicePublished() {
}
@Override
public void onSetupFailed(Throwable throwable) {
}
@Override
public void onUseDefaultBridges() {
}
@Override
public void onRequestCustomBridges(Runnable resultHandler) {
}
});

View File

@ -9,12 +9,15 @@ import io.bitsquare.app.Log;
import io.bitsquare.app.Version;
import io.bitsquare.arbitration.ArbitratorManager;
import io.bitsquare.btc.WalletService;
import io.bitsquare.btc.pricefeed.PriceFeedService;
import io.bitsquare.common.CommonOptionKeys;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.common.util.Utilities;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.p2p.BootstrapListener;
import io.bitsquare.p2p.P2PService;
import io.bitsquare.p2p.P2PServiceListener;
import io.bitsquare.trade.offer.OfferBookService;
import io.bitsquare.trade.offer.OpenOfferManager;
import io.bitsquare.trade.statistics.TradeStatisticsManager;
import org.apache.commons.lang3.exception.ExceptionUtils;
@ -33,6 +36,8 @@ public class Statistics {
private final Injector injector;
private final StatisticsModule statisticsModule;
private final TradeStatisticsManager tradeStatisticsManager;
private final OfferBookService offerBookService;
private final PriceFeedService priceFeedService;
private P2PService p2pService;
@ -74,54 +79,22 @@ public class Statistics {
injector = Guice.createInjector(statisticsModule);
Version.setBtcNetworkId(injector.getInstance(BitsquareEnvironment.class).getBitcoinNetwork().ordinal());
p2pService = injector.getInstance(P2PService.class);
p2pService.start(false, new P2PServiceListener() {
@Override
public void onRequestingDataCompleted() {
}
@Override
public void onNoSeedNodeAvailable() {
}
@Override
public void onNoPeersAvailable() {
}
p2pService.start(false, new BootstrapListener() {
@Override
public void onBootstrapComplete() {
}
@Override
public void onTorNodeReady() {
}
@Override
public void onHiddenServicePublished() {
}
@Override
public void onSetupFailed(Throwable throwable) {
}
@Override
public void onUseDefaultBridges() {
}
@Override
public void onRequestCustomBridges(Runnable resultHandler) {
}
});
// We want to persist trade statistics so we need to instantiate the tradeStatisticsManager
tradeStatisticsManager = injector.getInstance(TradeStatisticsManager.class);
offerBookService = injector.getInstance(OfferBookService.class);
priceFeedService = injector.getInstance(PriceFeedService.class);
// We need the price feed for market based offers
priceFeedService.setCurrencyCode(CurrencyUtil.getDefaultTradeCurrency().getCode());
priceFeedService.setType(PriceFeedService.Type.LAST);
priceFeedService.init(price -> log.debug("price " + price),
(errorMessage, throwable) -> log.warn(throwable.getMessage()));
}
public void shutDown() {