Skip to content

Commit

Permalink
Reduce log spam: gated logging for high frequency items.
Browse files Browse the repository at this point in the history
  • Loading branch information
jmacxx committed Oct 15, 2023
1 parent ce8634a commit e2cf7e1
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 20 deletions.
6 changes: 2 additions & 4 deletions src/main/java/bisq/price/spot/ArsBlueRateTransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@

import bisq.price.spot.providers.BlueRateProvider;
import bisq.price.util.bluelytics.ArsBlueMarketGapProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Optional;
import java.util.OptionalDouble;

@Component
@Slf4j
public class ArsBlueRateTransformer implements ExchangeRateTransformer {
private final ArsBlueMarketGapProvider blueMarketGapProvider;

Expand Down Expand Up @@ -54,8 +52,8 @@ public Optional<ExchangeRate> apply(ExchangeRateProvider provider, ExchangeRate
originalExchangeRate.getProvider()
);

log.info(String.format("%s transformed from %s to %s",
originalExchangeRate.getCurrency(), originalExchangeRate.getPrice(), blueRate));
provider.getGatedLogging().maybeLogInfo(String.format("%s transformed from %s to %s",
originalExchangeRate.getCurrency(), originalExchangeRate.getPrice(), blueRate));

return Optional.of(newExchangeRate);
}
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/bisq/price/spot/ExchangeRateProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.TradeCurrency;
import bisq.price.PriceProvider;
import bisq.price.util.GatedLogging;
import lombok.Getter;
import org.knowm.xchange.Exchange;
import org.knowm.xchange.ExchangeFactory;
import org.knowm.xchange.currency.Currency;
Expand All @@ -32,7 +34,6 @@
import org.knowm.xchange.service.marketdata.params.Params;
import org.springframework.core.env.Environment;

import javax.annotation.Nullable;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
Expand All @@ -59,6 +60,8 @@ public abstract class ExchangeRateProvider extends PriceProvider<Set<ExchangeRat
private final String name;
private final String prefix;
private final Environment env;
@Getter
private final GatedLogging gatedLogging = new GatedLogging();

public ExchangeRateProvider(Environment env, String name, String prefix, Duration refreshInterval) {
super(refreshInterval);
Expand Down
35 changes: 20 additions & 15 deletions src/main/java/bisq/price/spot/ExchangeRateService.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

import bisq.common.util.Tuple2;
import bisq.core.util.InlierUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import bisq.price.util.GatedLogging;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

Expand All @@ -32,11 +32,12 @@
* High-level {@link ExchangeRate} data operations.
*/
@Service
@Slf4j
class ExchangeRateService {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
private final Environment env;
private final List<ExchangeRateProvider> providers;
private final List<ExchangeRateTransformer> transformers;
private final GatedLogging gatedLogging = new GatedLogging();

/**
* Construct an {@link ExchangeRateService} with a list of all
Expand Down Expand Up @@ -87,6 +88,7 @@ public Map<String, Object> getAllMarketPrices() {
* by currency code
*/
private Map<String, ExchangeRate> getAggregateExchangeRates() {
boolean maybeLogDetails = gatedLogging.gatingOperation();
Map<String, ExchangeRate> aggregateExchangeRates = new HashMap<>();

// Query all providers and collect all exchange rates, grouped by currency code
Expand All @@ -110,7 +112,7 @@ private Map<String, ExchangeRate> getAggregateExchangeRates() {
} else {
// If multiple providers have rates for this currency, then
// aggregate = average of the rates
double priceAvg = priceAverageWithOutliersRemoved(exchangeRateList, currencyCode);
double priceAvg = priceAverageWithOutliersRemoved(exchangeRateList, currencyCode, maybeLogDetails);
aggregateExchangeRate = new ExchangeRate(
currencyCode,
BigDecimal.valueOf(priceAvg),
Expand All @@ -123,7 +125,8 @@ private Map<String, ExchangeRate> getAggregateExchangeRates() {
return aggregateExchangeRates;
}

private double priceAverageWithOutliersRemoved(List<ExchangeRate> exchangeRateList, String contextInfo) {
private double priceAverageWithOutliersRemoved(
List<ExchangeRate> exchangeRateList, String contextInfo, boolean logOutliers) {
final List<Double> yValues = exchangeRateList.stream().
mapToDouble(ExchangeRate::getPrice).boxed().collect(Collectors.toList());
Tuple2<Double, Double> tuple = InlierUtil.findInlierRange(yValues, 0, getOutlierStdDeviation());
Expand All @@ -145,16 +148,18 @@ private double priceAverageWithOutliersRemoved(List<ExchangeRate> exchangeRateLi
double priceAvg = opt.orElseThrow(IllegalStateException::new);

// log the outlier prices which were removed from the average, if any.
for (ExchangeRate badRate : exchangeRateList.stream()
.filter(e -> !filteredPrices.contains(e))
.collect(Collectors.toList())) {
log.info("{} {} outlier price removed:{}, lower/upper bounds:{}/{}, consensus price:{}",
badRate.getProvider(),
badRate.getCurrency(),
badRate.getPrice(),
lowerBound,
upperBound,
priceAvg);
if (logOutliers) {
for (ExchangeRate badRate : exchangeRateList.stream()
.filter(e -> !filteredPrices.contains(e))
.collect(Collectors.toList())) {
log.info("{} {} outlier price removed:{}, lower/upper bounds:{}/{}, consensus price:{}",
badRate.getProvider(),
badRate.getCurrency(),
badRate.getPrice(),
lowerBound,
upperBound,
priceAvg);
}
}
return priceAvg;
}
Expand Down
46 changes: 46 additions & 0 deletions src/main/java/bisq/price/util/GatedLogging.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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.price.util;

import lombok.extern.slf4j.Slf4j;

import java.time.Instant;

/* Per https://github.com/bisq-network/bisq-pricenode/issues/33
* There's too much logging of outlier filtering data, fills up the logs too fast and obliterates other valid logging.
* It correlates with client requests. Change that logging so its output once per minute.
*/

@Slf4j
public class GatedLogging {
private long timestampOfLastLogMessage = 0;

public void maybeLogInfo(String format, Object... params) {
if (gatingOperation()) {
log.info(format, params);
}
}

public boolean gatingOperation() {
if (Instant.now().getEpochSecond() - timestampOfLastLogMessage > 60) {
timestampOfLastLogMessage = Instant.now().getEpochSecond();
return true;
}
return false;
}
}

0 comments on commit e2cf7e1

Please sign in to comment.