Display logs below message tab

This commit is contained in:
Giacomo Pasini 2023-11-08 18:47:37 +01:00
parent 438f596f11
commit fb36250398
No known key found for this signature in database
GPG Key ID: FC08489D2D895D4B
6 changed files with 66 additions and 17 deletions

View File

@ -21,6 +21,7 @@ overwatch-derive = { git = "https://github.com/logos-co/Overwatch", rev = "ac28d
nomos-network = { path = "../nomos-services/network", features = ["libp2p"] }
nomos-da = { path = "../nomos-services/data-availability", features = ["libp2p"] }
nomos-consensus = { path = "../nomos-services/consensus" }
nomos-log = { path = "../nomos-services/log" }
nomos-libp2p = { path = "../nomos-libp2p"}
nomos-core = { path = "../nomos-core" }
nomos-node = { path = "../nodes/nomos-node" }
@ -34,3 +35,4 @@ once_cell = "1"
crossterm = "0.27"
ratatui = "0.24"
tui-input = "0.8"
ansi-to-tui = "3"

View File

@ -18,6 +18,7 @@ use full_replication::{
AbsoluteNumber, Attestation, Certificate, FullReplication, Settings as DaSettings,
};
use nomos_core::{block::BlockId, da::DaProtocol, wire};
use nomos_log::{LoggerBackend, LoggerSettings, SharedWriter};
use nomos_network::{backends::libp2p::Libp2p, NetworkService};
use overwatch_rs::{overwatch::OverwatchRunner, services::ServiceData};
use reqwest::Url;
@ -27,7 +28,7 @@ use std::{
path::PathBuf,
sync::{
mpsc::{Receiver, Sender},
Arc,
Arc, self
},
time::{Duration, Instant},
};
@ -70,6 +71,8 @@ pub struct App {
payload_sender: UnboundedSender<Box<[u8]>>,
status_updates: Receiver<Status>,
node: Url,
logs: Arc<sync::Mutex<Vec<u8>>>,
scroll_logs: u16,
}
impl NomosChat {
@ -91,6 +94,9 @@ impl NomosChat {
let (payload_sender, payload_receiver) = tokio::sync::mpsc::unbounded_channel();
let (status_sender, status_updates) = std::sync::mpsc::channel();
let shared_writer = Arc::new(sync::Mutex::new(Vec::new()));
let backend = SharedWriter::from_inner(shared_writer.clone());
std::thread::spawn(move || {
OverwatchRunner::<DisseminateApp>::run(
DisseminateAppServiceSettings {
@ -103,6 +109,11 @@ impl NomosChat {
node_addr,
output: None,
},
logger: LoggerSettings {
backend: LoggerBackend::Writer(backend),
level: tracing::Level::INFO,
..Default::default()
},
},
None,
)
@ -120,6 +131,8 @@ impl NomosChat {
payload_sender,
status_updates,
node: self.node.clone(),
logs: shared_writer,
scroll_logs: 0,
};
run_app(&mut terminal, app);
@ -188,6 +201,12 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) {
KeyCode::Esc => {
return;
}
KeyCode::Left => {
app.scroll_logs = app.scroll_logs.saturating_sub(1);
}
KeyCode::Right => {
app.scroll_logs = app.scroll_logs.saturating_add(1);
}
_ => {
if !app.message_in_flight {
app.input.handle_event(&Event::Key(key));

View File

@ -95,12 +95,13 @@ fn chat(f: &mut Frame, app: &App) {
.style(Style::new().white().on_black());
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Min(5), Constraint::Min(1), Constraint::Max(10)].as_ref())
.constraints([Constraint::Max(3), Constraint::Percentage(80), Constraint::Max(10)].as_ref())
.split(block.inner(f.size()));
f.render_widget(block, f.size());
let messages_rect = centered_rect(chunks[1], 90, 100);
render_messages(f, app, messages_rect);
render_logs(f, app, chunks[2]);
let chunks = Layout::default()
.direction(Direction::Horizontal)
@ -160,9 +161,21 @@ fn render_status(f: &mut Frame, app: &App, rect: Rect) {
let status = Paragraph::new(
app.message_status
.as_ref()
.map(|s| format!("{}{}", s.display(), waiting_animation))
.map(|s| format!("{}{}", s, waiting_animation))
.unwrap_or_default(),
)
.block(Block::default().borders(Borders::ALL).title("Status:"));
f.render_widget(status, rect);
}
fn render_logs<'a>(f: &mut Frame, app: &App, rect: Rect) {
use ansi_to_tui::IntoText;
let logs = app.logs.lock().unwrap();
f.render_widget(
Paragraph::new(logs.into_text().unwrap())
.wrap(Wrap { trim: true })
.scroll((app.scroll_logs, 0))
.block(Block::default().borders(Borders::ALL).title("Logs: (use ←/→ to scroll up/down")),
rect,
);
}

View File

@ -2,6 +2,7 @@ use crate::da::disseminate::{
DaProtocolChoice, DisseminateApp, DisseminateAppServiceSettings, Settings, Status,
};
use clap::Args;
use nomos_log::{LoggerBackend, LoggerSettings};
use nomos_network::{backends::libp2p::Libp2p, NetworkService};
use overwatch_rs::{overwatch::OverwatchRunner, services::ServiceData};
use reqwest::Url;
@ -59,6 +60,10 @@ impl Disseminate {
node_addr,
output,
},
logger: LoggerSettings {
backend: LoggerBackend::None,
..Default::default()
},
},
None,
)
@ -67,13 +72,13 @@ impl Disseminate {
});
// drop to signal we're not going to send more blobs
drop(payload_sender);
tracing::info!("{}", rx.recv().unwrap().display());
tracing::info!("{}", rx.recv().unwrap());
while let Ok(update) = rx.recv() {
if let Status::Err(e) = update {
tracing::error!("{e}");
return Err(e);
}
tracing::info!("{}", update.display());
tracing::info!("{}", update);
}
tracing::info!("done");
Ok(())

View File

@ -5,6 +5,7 @@ use futures::StreamExt;
use hex::FromHex;
use nomos_core::{da::DaProtocol, wire};
use nomos_da::network::{adapters::libp2p::Libp2pAdapter, NetworkAdapter};
use nomos_log::Logger;
use nomos_network::{backends::libp2p::Libp2p, NetworkService};
use overwatch_derive::*;
use overwatch_rs::{
@ -91,17 +92,17 @@ pub enum Status {
Err(Box<dyn std::error::Error + Send + Sync>),
}
impl Status {
pub fn display(&self) -> &str {
impl std::fmt::Display for Status {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Encoding => "Encoding message into blob(s)",
Self::Disseminating => "Sending blob(s) to the network",
Self::WaitingAttestations => "Waiting for attestations",
Self::CreatingCert => "Creating certificate",
Self::SavingCert => "Saving certificate to file",
Self::SendingCert => "Sending certificate to node",
Self::Done => "",
Self::Err(_) => "Error",
Self::Encoding => write!(f, "Encoding message into blob(s)"),
Self::Disseminating => write!(f, "Sending blob(s) to the network"),
Self::WaitingAttestations => write!(f, "Waiting for attestations"),
Self::CreatingCert => write!(f, "Creating certificate"),
Self::SavingCert => write!(f, "Saving certificate to file"),
Self::SendingCert => write!(f, "Sending certificate to node"),
Self::Done => write!(f, ""),
Self::Err(e) => write!(f, "Error: {e}"),
}
}
}
@ -112,6 +113,7 @@ impl Status {
pub struct DisseminateApp {
network: ServiceHandle<NetworkService<Libp2p>>,
send_blob: ServiceHandle<DisseminateService>,
logger: ServiceHandle<Logger>,
}
#[derive(Clone, Debug)]

View File

@ -28,7 +28,7 @@ pub struct Logger {
/// required by contract by Overwatch for a configuration struct
#[derive(Clone)]
pub struct SharedWriter {
inner: Arc<Mutex<Box<dyn Write + Send + Sync>>>,
inner: Arc<Mutex<dyn Write + Send + Sync>>,
}
impl Write for SharedWriter {
@ -44,9 +44,17 @@ impl Write for SharedWriter {
impl SharedWriter {
pub fn new<W: Write + Send + Sync + 'static>(writer: W) -> Self {
Self {
inner: Arc::new(Mutex::new(Box::new(writer))),
inner: Arc::new(Mutex::new(writer)),
}
}
pub fn into_inner(&self) -> Arc<Mutex<dyn Write + Send + Sync>> {
self.inner.clone()
}
pub fn from_inner(inner: Arc<Mutex<dyn Write + Send + Sync>>) -> Self {
Self { inner }
}
}
impl Debug for SharedWriter {