Prefix in relay loops logs (#920)

* prefix in relay loops logs

* fmt
This commit is contained in:
Svyatoslav Nikolsky
2021-04-22 14:44:39 +03:00
committed by Bastian Köcher
parent 25a4151a8b
commit 63ce1b5973
14 changed files with 137 additions and 89 deletions
+43 -3
View File
@@ -16,7 +16,11 @@
//! Relayer initialization functions.
use std::{fmt::Display, io::Write};
use std::{cell::RefCell, fmt::Display, io::Write};
async_std::task_local! {
pub(crate) static LOOP_NAME: RefCell<String> = RefCell::new(String::default());
}
/// Initialize relay environment.
pub fn initialize_relay() {
@@ -43,20 +47,56 @@ pub fn initialize_logger(with_timestamp: bool) {
Either::Right(ansi_term::Colour::Fixed(8).bold().paint(timestamp))
};
writeln!(buf, "{} {} {} {}", timestamp, log_level, log_target, record.args(),)
writeln!(
buf,
"{}{} {} {} {}",
loop_name_prefix(),
timestamp,
log_level,
log_target,
record.args(),
)
});
} else {
builder.format(move |buf, record| {
let log_level = color_level(record.level());
let log_target = color_target(record.target());
writeln!(buf, "{} {} {}", log_level, log_target, record.args(),)
writeln!(
buf,
"{}{} {} {}",
loop_name_prefix(),
log_level,
log_target,
record.args(),
)
});
}
builder.init();
}
/// Initialize relay loop. Must only be called once per every loop task.
pub(crate) fn initialize_loop(loop_name: String) {
LOOP_NAME.with(|g_loop_name| *g_loop_name.borrow_mut() = loop_name);
}
/// Returns loop name prefix to use in logs. The prefix is initialized with the `initialize_loop` call.
fn loop_name_prefix() -> String {
// try_with to avoid panic outside of async-std task context
LOOP_NAME
.try_with(|loop_name| {
// using borrow is ok here, because loop is only initialized once (=> borrow_mut will only be called once)
let loop_name = loop_name.borrow();
if loop_name.is_empty() {
String::new()
} else {
format!("[{}] ", loop_name)
}
})
.unwrap_or_else(|_| String::new())
}
enum Either<A, B> {
Left(A),
Right(B),
+51 -49
View File
@@ -26,9 +26,9 @@ pub const RECONNECT_DELAY: Duration = Duration::from_secs(10);
/// Basic blockchain client from relay perspective.
#[async_trait]
pub trait Client: Clone + Send + Sync {
pub trait Client: 'static + Clone + Send + Sync {
/// Type of error this clients returns.
type Error: Debug + MaybeConnectionError;
type Error: 'static + Debug + MaybeConnectionError + Send + Sync;
/// Try to reconnect to source node.
async fn reconnect(&mut self) -> Result<(), Self::Error>;
@@ -105,63 +105,65 @@ impl<SC, TC, LM> Loop<SC, TC, LM> {
/// This function represents an outer loop, which in turn calls provided `run_loop` function to do
/// actual job. When `run_loop` returns, this outer loop reconnects to failed client (source,
/// target or both) and calls `run_loop` again.
pub async fn run<R, F>(mut self, run_loop: R) -> Result<(), String>
pub async fn run<R, F>(mut self, loop_name: String, run_loop: R) -> Result<(), String>
where
R: Fn(SC, TC, Option<LM>) -> F,
F: Future<Output = Result<(), FailedClient>>,
SC: Client,
TC: Client,
LM: Clone,
R: 'static + Send + Fn(SC, TC, Option<LM>) -> F,
F: 'static + Send + Future<Output = Result<(), FailedClient>>,
SC: 'static + Client,
TC: 'static + Client,
LM: 'static + Send + Clone,
{
loop {
let result = run_loop(
self.source_client.clone(),
self.target_client.clone(),
self.loop_metric.clone(),
)
.await;
async_std::task::spawn(async move {
crate::initialize::initialize_loop(loop_name);
match result {
Ok(()) => break,
Err(failed_client) => loop {
async_std::task::sleep(self.reconnect_delay).await;
if failed_client == FailedClient::Both || failed_client == FailedClient::Source {
match self.source_client.reconnect().await {
Ok(()) => (),
Err(error) => {
log::warn!(
target: "bridge",
"Failed to reconnect to source client. Going to retry in {}s: {:?}",
self.reconnect_delay.as_secs(),
error,
);
continue;
loop {
let loop_metric = self.loop_metric.clone();
let future_result = run_loop(self.source_client.clone(), self.target_client.clone(), loop_metric);
let result = future_result.await;
match result {
Ok(()) => break,
Err(failed_client) => loop {
async_std::task::sleep(self.reconnect_delay).await;
if failed_client == FailedClient::Both || failed_client == FailedClient::Source {
match self.source_client.reconnect().await {
Ok(()) => (),
Err(error) => {
log::warn!(
target: "bridge",
"Failed to reconnect to source client. Going to retry in {}s: {:?}",
self.reconnect_delay.as_secs(),
error,
);
continue;
}
}
}
}
if failed_client == FailedClient::Both || failed_client == FailedClient::Target {
match self.target_client.reconnect().await {
Ok(()) => (),
Err(error) => {
log::warn!(
target: "bridge",
"Failed to reconnect to target client. Going to retry in {}s: {:?}",
self.reconnect_delay.as_secs(),
error,
);
continue;
if failed_client == FailedClient::Both || failed_client == FailedClient::Target {
match self.target_client.reconnect().await {
Ok(()) => (),
Err(error) => {
log::warn!(
target: "bridge",
"Failed to reconnect to target client. Going to retry in {}s: {:?}",
self.reconnect_delay.as_secs(),
error,
);
continue;
}
}
}
}
break;
},
break;
},
}
log::debug!(target: "bridge", "Restarting relay loop");
}
log::debug!(target: "bridge", "Restarting relay loop");
}
Ok(())
Ok(())
})
.await
}
}