Skip to content

Commit 6f004f5

Browse files
authored
Merge pull request #1157 from input-output-hk/chain-not-moving-up
Add warning if blockchain is not moving up
2 parents 3297a96 + d32570a commit 6f004f5

File tree

5 files changed

+88
-1
lines changed

5 files changed

+88
-1
lines changed

doc/quickstart/02_passive_node.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ Description of the fields:
8484
this node should maintain.
8585
- `explorer`: (optional) Explorer settings
8686
- `enabled`: True or false
87+
- `no_blockchain_updates_warning_interval`: (optional, seconds) if no new blocks
88+
were received after this period of time, the node will start sending you
89+
warnings in the logs.
8790

8891
[multiaddr]: https://github.com/multiformats/multiaddr
8992

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use crate::{blockchain, utils::task::TokioServiceInfo};
2+
use chain_time::{
3+
era::{EpochPosition, EpochSlotOffset},
4+
Epoch,
5+
};
6+
use futures::prelude::*;
7+
use std::time::{Duration, SystemTime};
8+
use tokio::timer::Interval;
9+
10+
pub fn check_last_block_time(
11+
service_info: TokioServiceInfo,
12+
blockchain_tip: blockchain::Tip,
13+
check_interval: Duration,
14+
) -> impl Future<Item = (), Error = ()> {
15+
let logger = service_info.logger().clone();
16+
let err_logger = logger.clone();
17+
18+
// those are different values, because check_interval can be big
19+
// (30 minutes) and the notification may remain unseen
20+
let check_period = check_interval;
21+
let notification_period = Duration::from_secs(60);
22+
23+
Interval::new_interval(notification_period)
24+
.map_err(move |e| error!(err_logger, "timer error: {}", e))
25+
.and_then(move |_| blockchain_tip.get_ref())
26+
.for_each(move |tip| {
27+
let tip_date = tip.block_date();
28+
let slot = tip
29+
.epoch_leadership_schedule()
30+
.era()
31+
.from_era_to_slot(EpochPosition {
32+
epoch: Epoch(tip_date.epoch),
33+
slot: EpochSlotOffset(tip_date.slot_id),
34+
});
35+
let tip_time = tip.time_frame().slot_to_systemtime(slot).ok_or_else(|| {
36+
error!(logger, "cannot convert the block tip date to system time");
37+
})?;
38+
let period_since_last_block =
39+
SystemTime::now().duration_since(tip_time).map_err(|e| {
40+
error!(
41+
logger,
42+
"cannot compute the time passed since the last block: {}", e
43+
);
44+
})?;
45+
if period_since_last_block > check_period {
46+
warn!(
47+
logger,
48+
"blockchain is not moving up, the last block was {} seconds ago",
49+
period_since_last_block.as_secs()
50+
);
51+
}
52+
Ok(())
53+
})
54+
}

jormungandr/src/main.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ use std::time::Duration;
7373

7474
pub mod blockcfg;
7575
pub mod blockchain;
76+
pub mod blockchain_stuck_notifier;
7677
pub mod client;
7778
pub mod explorer;
7879
pub mod fragment;
@@ -281,7 +282,7 @@ fn start_services(bootstrapped_node: BootstrappedNode) -> Result<(), start_up::E
281282
let full_context = rest::FullContext {
282283
stats_counter,
283284
blockchain,
284-
blockchain_tip,
285+
blockchain_tip: blockchain_tip.clone(),
285286
network_task: network_msgbox,
286287
transaction_task: fragment_msgbox,
287288
logs: pool_logs,
@@ -293,6 +294,22 @@ fn start_services(bootstrapped_node: BootstrappedNode) -> Result<(), start_up::E
293294
rest_context.set_node_state(NodeState::Running);
294295
};
295296

297+
{
298+
let blockchain_tip = blockchain_tip.clone();
299+
let no_blockchain_updates_warning_interval = bootstrapped_node
300+
.settings
301+
.no_blockchain_updates_warning_interval
302+
.clone();
303+
304+
services.spawn_future("blockchain_stuck_notifier", move |info| {
305+
blockchain_stuck_notifier::check_last_block_time(
306+
info,
307+
blockchain_tip,
308+
no_blockchain_updates_warning_interval,
309+
)
310+
});
311+
}
312+
296313
services.wait_any_finished();
297314
info!(bootstrapped_node.logger, "Shutting down node");
298315
Ok(())

jormungandr/src/settings/start/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ pub struct Config {
3030
pub p2p: P2pConfig,
3131

3232
pub explorer: Option<Explorer>,
33+
34+
/// the time interval with no blockchain updates after which alerts are thrown
35+
#[serde(default)]
36+
pub no_blockchain_updates_warning_interval: Option<Duration>,
3337
}
3438

3539
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]

jormungandr/src/settings/start/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::{fs::File, path::PathBuf};
1414
const DEFAULT_FILTER_LEVEL: FilterLevel = FilterLevel::Info;
1515
const DEFAULT_LOG_FORMAT: LogFormat = LogFormat::Plain;
1616
const DEFAULT_LOG_OUTPUT: LogOutput = LogOutput::Stderr;
17+
const DEFAULT_NO_BLOCKCHAIN_UPDATES_WARNING_INTERVAL: u64 = 1800; // 30 min
1718

1819
custom_error! {pub Error
1920
ConfigIo { source: std::io::Error } = "Cannot read the node configuration file: {source}",
@@ -34,6 +35,7 @@ pub struct Settings {
3435
pub mempool: Mempool,
3536
pub leadership: Leadership,
3637
pub explorer: bool,
38+
pub no_blockchain_updates_warning_interval: std::time::Duration,
3739
}
3840

3941
pub struct RawSettings {
@@ -173,6 +175,13 @@ impl RawSettings {
173175
.as_ref()
174176
.map_or(Leadership::default(), |cfg| cfg.leadership.clone()),
175177
explorer,
178+
no_blockchain_updates_warning_interval: config
179+
.as_ref()
180+
.and_then(|config| config.no_blockchain_updates_warning_interval.clone())
181+
.map(|d| d.into())
182+
.unwrap_or(std::time::Duration::from_secs(
183+
DEFAULT_NO_BLOCKCHAIN_UPDATES_WARNING_INTERVAL,
184+
)),
176185
})
177186
}
178187
}

0 commit comments

Comments
 (0)