Improve zebra-consensus logging and metrics (#989)

This commit is contained in:
teor 2020-09-04 08:06:21 +10:00 committed by GitHub
parent 5485f4429a
commit 8a4245daab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 23 deletions

View File

@ -123,20 +123,35 @@ where
// Skip contextual checks for the genesis block // Skip contextual checks for the genesis block
let previous_block_hash = block.header.previous_block_hash; let previous_block_hash = block.header.previous_block_hash;
if previous_block_hash != crate::parameters::GENESIS_PREVIOUS_BLOCK_HASH { if previous_block_hash != crate::parameters::GENESIS_PREVIOUS_BLOCK_HASH {
tracing::debug!(?height, "Awaiting previous block from state"); if height == block::Height(0) {
Err("Invalid block: height is 0, but previous block hash is not null.")?;
}
let expected_height = block::Height(height.0 - 1);
tracing::trace!(?expected_height, ?previous_block_hash, "Waiting for previous block");
metrics::gauge!("block.waiting.block.height", expected_height.0 as i64);
metrics::counter!("block.waiting.count", 1);
let previous_block = BlockVerifier::await_block( let previous_block = BlockVerifier::await_block(
&mut state, &mut state,
previous_block_hash, previous_block_hash,
block::Height(height.0 - 1), expected_height,
) )
.await?; .await?;
let previous_height = previous_block.coinbase_height().unwrap(); let previous_height = previous_block.coinbase_height().unwrap();
if height.0 != previous_height.0 + 1 { if previous_height != expected_height {
Err("Invalid block height: must be 1 more than the previous block height.")?; Err("Invalid block height: must be 1 more than the previous block height.")?;
} }
} }
tracing::trace!(?height, ?hash, "Verified block");
metrics::gauge!(
"block.verified.block.height",
height.0 as _
);
metrics::counter!("block.verified.block.count", 1);
Ok(hash) Ok(hash)
} }
.boxed() .boxed()

View File

@ -111,12 +111,9 @@ where
fn call(&mut self, block: Arc<Block>) -> Self::Future { fn call(&mut self, block: Arc<Block>) -> Self::Future {
// TODO(jlusby): Error = Report, handle errors from state_service. // TODO(jlusby): Error = Report, handle errors from state_service.
let span = tracing::debug_span!( let height = block.coinbase_height();
"block_verify", let hash = block.hash();
height = ?block.coinbase_height(), let span = tracing::debug_span!("block_verify", ?height, ?hash,);
hash = ?block.hash()
);
let block_height = block.coinbase_height();
let mut block_verifier = self.block_verifier.clone(); let mut block_verifier = self.block_verifier.clone();
let mut state_service = self.state_service.clone(); let mut state_service = self.state_service.clone();
@ -124,15 +121,15 @@ where
let max_checkpoint_height = self.checkpoint.clone().map(|c| c.max_height); let max_checkpoint_height = self.checkpoint.clone().map(|c| c.max_height);
// Log an info-level message on unexpected high blocks // Log an info-level message on unexpected high blocks
let is_unexpected_high_block = match (block_height, self.last_block_height) { let is_unexpected_high_block = match (height, self.last_block_height) {
(Some(block::Height(block_height)), Some(block::Height(last_block_height))) (Some(block::Height(height)), Some(block::Height(last_block_height)))
if (block_height > last_block_height + MAX_EXPECTED_BLOCK_GAP) => if (height > last_block_height + MAX_EXPECTED_BLOCK_GAP) =>
{ {
self.last_block_height = Some(block::Height(block_height)); self.last_block_height = Some(block::Height(height));
true true
} }
(Some(block_height), _) => { (Some(height), _) => {
self.last_block_height = Some(block_height); self.last_block_height = Some(height);
false false
} }
// The other cases are covered by the verifiers // The other cases are covered by the verifiers
@ -144,7 +141,7 @@ where
// to use BlockVerifier, CheckpointVerifier, or both. // to use BlockVerifier, CheckpointVerifier, or both.
// Call a verifier based on the block height and checkpoints. // Call a verifier based on the block height and checkpoints.
if is_higher_than_max_checkpoint(block_height, max_checkpoint_height) { if is_higher_than_max_checkpoint(height, max_checkpoint_height) {
// Log a message on early high blocks. // Log a message on early high blocks.
// The sync service rejects most of these blocks, but we // The sync service rejects most of these blocks, but we
// still want to know if a large number get through. // still want to know if a large number get through.
@ -153,7 +150,7 @@ where
// low blocks. (We can't distinguish between these cases, until // low blocks. (We can't distinguish between these cases, until
// we've verified the blocks.) // we've verified the blocks.)
if is_unexpected_high_block { if is_unexpected_high_block {
tracing::debug!(?block_height, "unexpected high block, or recent unexpected low blocks"); tracing::debug!(?height, "unexpected high block, or recent unexpected low blocks");
} }
block_verifier block_verifier
@ -170,6 +167,13 @@ where
.await?; .await?;
} }
tracing::trace!(?height, ?hash, "Verified block");
metrics::gauge!(
"chain.verified.block.height",
height.expect("Valid blocks have a block height").0 as _
);
metrics::counter!("chain.verified.block.count", 1);
let add_block = state_service let add_block = state_service
.ready_and() .ready_and()
.await? .await?

View File

@ -180,6 +180,7 @@ impl CheckpointVerifier {
if initial_height >= checkpoint_list.max_height() { if initial_height >= checkpoint_list.max_height() {
(None, Progress::FinalCheckpoint) (None, Progress::FinalCheckpoint)
} else { } else {
metrics::gauge!("checkpoint.previous.height", initial_height.0 as i64);
( (
Some(initial_tip.hash()), Some(initial_tip.hash()),
Progress::InitialTip(initial_height), Progress::InitialTip(initial_height),
@ -243,6 +244,8 @@ impl CheckpointVerifier {
let mut pending_height = match self.previous_checkpoint_height() { let mut pending_height = match self.previous_checkpoint_height() {
// Check if we have the genesis block as a special case, to simplify the loop // Check if we have the genesis block as a special case, to simplify the loop
BeforeGenesis if !self.queued.contains_key(&block::Height(0)) => { BeforeGenesis if !self.queued.contains_key(&block::Height(0)) => {
tracing::trace!("Waiting for genesis block");
metrics::counter!("checkpoint.waiting.count", 1);
return WaitingForBlocks; return WaitingForBlocks;
} }
BeforeGenesis => block::Height(0), BeforeGenesis => block::Height(0),
@ -288,12 +291,18 @@ impl CheckpointVerifier {
.checkpoint_list .checkpoint_list
.max_height_in_range((start, Included(pending_height))); .max_height_in_range((start, Included(pending_height)));
tracing::debug!( tracing::trace!(
checkpoint_start = ?start, checkpoint_start = ?start,
highest_contiguous_block = ?pending_height, highest_contiguous_block = ?pending_height,
?target_checkpoint ?target_checkpoint
); );
if let Some(block::Height(target_checkpoint)) = target_checkpoint {
metrics::gauge!("checkpoint.target.height", target_checkpoint as i64);
} else {
metrics::counter!("checkpoint.waiting.count", 1);
}
target_checkpoint target_checkpoint
.map(Checkpoint) .map(Checkpoint)
.unwrap_or(WaitingForBlocks) .unwrap_or(WaitingForBlocks)
@ -366,8 +375,10 @@ impl CheckpointVerifier {
// Ignore heights that aren't checkpoint heights // Ignore heights that aren't checkpoint heights
if verified_height == self.checkpoint_list.max_height() { if verified_height == self.checkpoint_list.max_height() {
metrics::gauge!("checkpoint.previous.height", verified_height.0 as i64);
self.verifier_progress = FinalCheckpoint; self.verifier_progress = FinalCheckpoint;
} else if self.checkpoint_list.contains(verified_height) { } else if self.checkpoint_list.contains(verified_height) {
metrics::gauge!("checkpoint.previous.height", verified_height.0 as i64);
self.verifier_progress = PreviousCheckpoint(verified_height); self.verifier_progress = PreviousCheckpoint(verified_height);
// We're done with the initial tip hash now // We're done with the initial tip hash now
self.initial_tip_hash = None; self.initial_tip_hash = None;
@ -403,7 +414,7 @@ impl CheckpointVerifier {
Ok(height) => height, Ok(height) => height,
Err(error) => { Err(error) => {
// Block errors happen frequently on mainnet, due to bad peers. // Block errors happen frequently on mainnet, due to bad peers.
tracing::debug!(?error); tracing::trace!(?error);
// Sending might fail, depending on what the caller does with rx, // Sending might fail, depending on what the caller does with rx,
// but there's nothing we can do about it. // but there's nothing we can do about it.
@ -426,7 +437,7 @@ impl CheckpointVerifier {
if qb.hash == hash { if qb.hash == hash {
let old_tx = std::mem::replace(&mut qb.tx, tx); let old_tx = std::mem::replace(&mut qb.tx, tx);
let e = "rejected older of duplicate verification requests".into(); let e = "rejected older of duplicate verification requests".into();
tracing::debug!(?e); tracing::trace!(?e);
let _ = old_tx.send(Err(e)); let _ = old_tx.send(Err(e));
return rx; return rx;
} }
@ -447,7 +458,7 @@ impl CheckpointVerifier {
qblocks.push(new_qblock); qblocks.push(new_qblock);
let is_checkpoint = self.checkpoint_list.contains(height); let is_checkpoint = self.checkpoint_list.contains(height);
tracing::debug!(?height, ?hash, ?is_checkpoint, "Queued block"); tracing::trace!(?height, ?hash, ?is_checkpoint, "Queued block");
// TODO(teor): // TODO(teor):
// - Remove this log once the CheckpointVerifier is working? // - Remove this log once the CheckpointVerifier is working?
@ -555,7 +566,6 @@ impl CheckpointVerifier {
.expect("every checkpoint height must have a hash"), .expect("every checkpoint height must have a hash"),
), ),
WaitingForBlocks => { WaitingForBlocks => {
tracing::debug!("waiting for blocks to complete checkpoint range");
return; return;
} }
FinishedVerifying => { FinishedVerifying => {
@ -642,7 +652,13 @@ impl CheckpointVerifier {
"the previous checkpoint should match: bad checkpoint list, zebra bug, or bad chain" "the previous checkpoint should match: bad checkpoint list, zebra bug, or bad chain"
); );
tracing::info!(?current_range, "Verified checkpoint range"); let block_count = rev_valid_blocks.len();
tracing::info!(?block_count, ?current_range, "Verified checkpoint range");
metrics::gauge!(
"checkpoint.verified.block.height",
target_checkpoint_height.0 as _
);
metrics::counter!("checkpoint.verified.block.count", block_count as _);
// All the blocks we've kept are valid, so let's verify them // All the blocks we've kept are valid, so let's verify them
// in height order. // in height order.