Improve newPayload and FCU logs (#7961)

* Change the output log on newPayload and FCU executions

Signed-off-by: Ameziane H. <ameziane.hamlat@consensys.net>
Co-authored-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Co-authored-by: Simon Dudley <simon.dudley@consensys.net>
This commit is contained in:
ahamlat
2024-12-05 17:49:05 +01:00
committed by GitHub
parent cdfbe46339
commit d595eeebb3
11 changed files with 149 additions and 18 deletions

View File

@@ -46,6 +46,7 @@
- Add RPC WS options to specify password file for keystore and truststore [#7970](https://github.com/hyperledger/besu/pull/7970)
- Prometheus Java Metrics library upgraded to version 1.3.3 [#7880](https://github.com/hyperledger/besu/pull/7880)
- Add histogram to Prometheus metrics system [#7944](https://github.com/hyperledger/besu/pull/7944)
- Improve newPayload and FCU logs [#7961](https://github.com/hyperledger/besu/pull/7961)
### Bug fixes

View File

@@ -118,4 +118,16 @@ public class Hash extends DelegatingBytes32 {
public static Hash fromHexStringLenient(final String str) {
return new Hash(Bytes32.fromHexStringLenient(str));
}
/***
* For logging purposes, this method returns a shortened hex representation
*
* @return shortened string with only the beginning and the end of the hex representation
*/
public String toShortLogString() {
final var hexRepresentation = toFastHex(false);
String firstPart = hexRepresentation.substring(0, 5);
String lastPart = hexRepresentation.substring(hexRepresentation.length() - 5);
return firstPart + "....." + lastPart;
}
}

View File

@@ -161,11 +161,31 @@ public final class Wei extends BaseUInt256Value<Wei> implements Quantity {
* @return the string
*/
public String toHumanReadableString() {
return toHumanReadableStringWithPadding(1);
}
/**
* Wei to human-readable string, with padding
*
* @return the string
*/
public String toHumanReadablePaddedString() {
return toHumanReadableStringWithPadding(6);
}
/**
* Returns a human-readable String, the number of returned characters depends on the width
* parameter
*
* @param width the number of digits to use
* @return a human-readable String
*/
private String toHumanReadableStringWithPadding(final int width) {
final BigInteger amount = toBigInteger();
final int numOfDigits = amount.toString().length();
final Unit preferredUnit = Unit.getPreferred(numOfDigits);
final double res = amount.doubleValue() / preferredUnit.divisor;
return String.format("%1." + preferredUnit.decimals + "f %s", res, preferredUnit);
return String.format("%" + width + "." + preferredUnit.decimals + "f %s", res, preferredUnit);
}
/** The enum Unit. */

View File

@@ -44,4 +44,28 @@ public class WeiTest {
assertThat(Wei.of(new BigInteger("1" + String.valueOf(manyZeros))).toHumanReadableString())
.isEqualTo("100.00 tether");
}
@Test
public void toHumanReadablePaddedString() {
assertThat(Wei.ZERO.toHumanReadablePaddedString()).isEqualTo(" 0 wei");
assertThat(Wei.ONE.toHumanReadablePaddedString()).isEqualTo(" 1 wei");
assertThat(Wei.of(999).toHumanReadablePaddedString()).isEqualTo(" 999 wei");
assertThat(Wei.of(1000).toHumanReadablePaddedString()).isEqualTo(" 1.00 kwei");
assertThat(Wei.of(1009).toHumanReadablePaddedString()).isEqualTo(" 1.01 kwei");
assertThat(Wei.of(1011).toHumanReadablePaddedString()).isEqualTo(" 1.01 kwei");
assertThat(Wei.of(new BigInteger("1000000000")).toHumanReadablePaddedString())
.isEqualTo(" 1.00 gwei");
assertThat(Wei.of(new BigInteger("1000000000000000000")).toHumanReadablePaddedString())
.isEqualTo(" 1.00 ether");
final char[] manyZeros = new char[32];
Arrays.fill(manyZeros, '0');
assertThat(
Wei.of(new BigInteger("1" + String.valueOf(manyZeros))).toHumanReadablePaddedString())
.isEqualTo("100.00 tether");
}
}

View File

@@ -389,8 +389,7 @@ public abstract class AbstractEngineForkchoiceUpdated extends ExecutionEngineJso
// fcU calls are synchronous, no need to make volatile
private long lastFcuInfoLog = System.currentTimeMillis();
private static final String logMessage =
"{} for fork-choice-update: head: {}, finalized: {}, safeBlockHash: {}";
private static final String logMessage = "FCU({}) | head: {} | finalized: {} | safeBlockHash: {}";
private void logForkchoiceUpdatedCall(
final EngineStatus status, final EngineForkchoiceUpdatedParameter forkChoice) {
@@ -413,9 +412,9 @@ public abstract class AbstractEngineForkchoiceUpdated extends ExecutionEngineJso
LOG.info(
logMessage,
status.name(),
forkChoice.getHeadBlockHash(),
forkChoice.getFinalizedBlockHash(),
forkChoice.getSafeBlockHash());
forkChoice.getHeadBlockHash().toShortLogString(),
forkChoice.getFinalizedBlockHash().toShortLogString(),
forkChoice.getSafeBlockHash().toShortLogString());
}
private void logAtDebug(

View File

@@ -370,7 +370,8 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
.flatMap(Optional::stream)
.mapToInt(List::size)
.sum(),
(System.currentTimeMillis() - startTimeMs) / 1000.0);
(System.currentTimeMillis() - startTimeMs) / 1000.0,
executionResult.getNbParallelizedTransations());
return respondWith(reqId, blockParam, newBlockHeader.getHash(), VALID);
} else {
if (executionResult.causedBy().isPresent()) {
@@ -564,26 +565,41 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
.collect(Collectors.toList()));
}
private void logImportedBlockInfo(final Block block, final int blobCount, final double timeInS) {
private void logImportedBlockInfo(
final Block block,
final int blobCount,
final double timeInS,
final Optional<Integer> nbParallelizedTransations) {
final StringBuilder message = new StringBuilder();
message.append("Imported #%,d / %d tx");
final int nbTransactions = block.getBody().getTransactions().size();
message.append("Imported #%,d (%s)|%5d tx");
final List<Object> messageArgs =
new ArrayList<>(
List.of(block.getHeader().getNumber(), block.getBody().getTransactions().size()));
List.of(
block.getHeader().getNumber(), block.getHash().toShortLogString(), nbTransactions));
if (block.getBody().getWithdrawals().isPresent()) {
message.append(" / %d ws");
message.append("|%3d ws");
messageArgs.add(block.getBody().getWithdrawals().get().size());
}
message.append(" / %d blobs / base fee %s / %,d (%01.1f%%) gas / (%s) in %01.3fs. Peers: %d");
double mgasPerSec = (timeInS != 0) ? block.getHeader().getGasUsed() / (timeInS * 1_000_000) : 0;
message.append(
"|%2d blobs| base fee %s| gas used %,11d (%5.1f%%)| exec time %01.3fs| mgas/s %6.2f");
messageArgs.addAll(
List.of(
blobCount,
block.getHeader().getBaseFee().map(Wei::toHumanReadableString).orElse("N/A"),
block.getHeader().getBaseFee().map(Wei::toHumanReadablePaddedString).orElse("N/A"),
block.getHeader().getGasUsed(),
(block.getHeader().getGasUsed() * 100.0) / block.getHeader().getGasLimit(),
block.getHash().toHexString(),
timeInS,
ethPeers.peerCount()));
mgasPerSec));
if (nbParallelizedTransations.isPresent()) {
double parallelizedTxPercentage =
(double) (nbParallelizedTransations.get() * 100) / nbTransactions;
message.append("| parallel txs %5.1f%%");
messageArgs.add(parallelizedTxPercentage);
}
message.append("| peers: %2d");
messageArgs.add(ethPeers.peerCount());
LOG.info(String.format(message.toString(), messageArgs.toArray()));
}
}

View File

@@ -26,6 +26,7 @@ public class BlockProcessingResult extends BlockValidationResult {
private final Optional<BlockProcessingOutputs> yield;
private final boolean isPartial;
private Optional<Integer> nbParallelizedTransations = Optional.empty();
/** A result indicating that processing failed. */
public static final BlockProcessingResult FAILED = new BlockProcessingResult("processing failed");
@@ -40,6 +41,21 @@ public class BlockProcessingResult extends BlockValidationResult {
this.isPartial = false;
}
/**
* A result indicating that processing was successful but incomplete.
*
* @param yield the outputs of processing a block
* @param nbParallelizedTransations potential number of parallelized transactions during block
* processing
*/
public BlockProcessingResult(
final Optional<BlockProcessingOutputs> yield,
final Optional<Integer> nbParallelizedTransations) {
this.yield = yield;
this.isPartial = false;
this.nbParallelizedTransations = nbParallelizedTransations;
}
/**
* A result indicating that processing was successful but incomplete.
*
@@ -144,4 +160,13 @@ public class BlockProcessingResult extends BlockValidationResult {
public Optional<List<Request>> getRequests() {
return yield.flatMap(BlockProcessingOutputs::getRequests);
}
/**
* Returns an optional that contains the number of parallelized transactions (if there is any)
*
* @return Optional of parallelized transactions during the block execution
*/
public Optional<Integer> getNbParallelizedTransations() {
return nbParallelizedTransations;
}
}

View File

@@ -183,7 +183,8 @@ public class MainnetBlockValidator implements BlockValidator {
}
return new BlockProcessingResult(
Optional.of(new BlockProcessingOutputs(worldState, receipts, maybeRequests)));
Optional.of(new BlockProcessingOutputs(worldState, receipts, maybeRequests)),
result.getNbParallelizedTransations());
}
} catch (MerkleTrieException ex) {
context.getWorldStateArchive().heal(ex.getMaybeAddress(), ex.getLocation());

View File

@@ -135,6 +135,8 @@ public abstract class AbstractBlockProcessor implements BlockProcessor {
blockHashLookup,
blobGasPrice);
boolean parallelizedTxFound = false;
int nbParallelTx = 0;
for (int i = 0; i < transactions.size(); i++) {
final Transaction transaction = transactions.get(i);
if (!hasAvailableBlockBudget(blockHeader, transaction, currentGasUsed)) {
@@ -181,6 +183,13 @@ public abstract class AbstractBlockProcessor implements BlockProcessor {
transactionReceiptFactory.create(
transaction.getType(), transactionProcessingResult, worldState, currentGasUsed);
receipts.add(transactionReceipt);
if (!parallelizedTxFound
&& transactionProcessingResult.getIsProcessedInParallel().isPresent()) {
parallelizedTxFound = true;
nbParallelTx = 1;
} else if (transactionProcessingResult.getIsProcessedInParallel().isPresent()) {
nbParallelTx++;
}
}
if (blockHeader.getBlobGasUsed().isPresent()
&& currentBlobGasUsed != blockHeader.getBlobGasUsed().get()) {
@@ -243,7 +252,8 @@ public abstract class AbstractBlockProcessor implements BlockProcessor {
}
return new BlockProcessingResult(
Optional.of(new BlockProcessingOutputs(worldState, receipts, maybeRequests)));
Optional.of(new BlockProcessingOutputs(worldState, receipts, maybeRequests)),
parallelizedTxFound ? Optional.of(nbParallelTx) : Optional.empty());
}
protected Optional<PreprocessingContext> runBlockPreProcessing(

View File

@@ -251,8 +251,10 @@ public class ParallelizedConcurrentTransactionProcessor {
blockAccumulator.importStateChangesFromSource(transactionAccumulator);
if (confirmedParallelizedTransactionCounter.isPresent())
if (confirmedParallelizedTransactionCounter.isPresent()) {
confirmedParallelizedTransactionCounter.get().inc();
transactionProcessingResult.setIsProcessedInParallel(Optional.of(Boolean.TRUE));
}
return Optional.of(transactionProcessingResult);
} else {
blockAccumulator.importPriorStateFromSource(transactionAccumulator);

View File

@@ -49,6 +49,8 @@ public class TransactionProcessingResult
private final Bytes output;
private Optional<Boolean> isProcessedInParallel = Optional.empty();
private final ValidationResult<TransactionInvalidReason> validationResult;
private final Optional<Bytes> revertReason;
@@ -194,6 +196,25 @@ public class TransactionProcessingResult
return validationResult;
}
/**
* Set isProcessedInParallel to the value in parameter
*
* @param isProcessedInParallel new value of isProcessedInParallel
*/
public void setIsProcessedInParallel(final Optional<Boolean> isProcessedInParallel) {
this.isProcessedInParallel = isProcessedInParallel;
}
/**
* Returns a flag that indicates if the transaction was executed in parallel
*
* @return Optional of Boolean, the value of the boolean is true if the transaction was executed
* in parallel
*/
public Optional<Boolean> getIsProcessedInParallel() {
return isProcessedInParallel;
}
/**
* Returns the reason why a transaction was reverted (if applicable).
*