mirror of
https://gitlab.com/fabinfra/fabaccess/sute.git
synced 2025-03-12 14:41:52 +01:00
Adds slog based logging into a widget
This commit is contained in:
parent
4cead5a94f
commit
2044abfea8
@ -26,6 +26,8 @@ smol = "1.2"
|
||||
|
||||
signal-hook = "0.1"
|
||||
|
||||
slog = "2.5"
|
||||
|
||||
libc = "0.2"
|
||||
rsasl = "0.1"
|
||||
|
||||
|
88
src/app.rs
88
src/app.rs
@ -1,5 +1,6 @@
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
|
||||
use futures::prelude::*;
|
||||
use futures_signals::signal::{Mutable, Signal, MutableSignalCloned};
|
||||
@ -9,6 +10,16 @@ use termion::event::Key;
|
||||
use crate::input::Inputs;
|
||||
use crate::schema::Api;
|
||||
|
||||
use slog::{
|
||||
Drain,
|
||||
Level,
|
||||
Record,
|
||||
OwnedKVList,
|
||||
};
|
||||
|
||||
use tui::text::{Span, Spans};
|
||||
use tui::style::{Style, Color};
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
pub enum Window {
|
||||
Main,
|
||||
@ -21,23 +32,23 @@ enum ConnState<F> {
|
||||
}
|
||||
|
||||
/// Application state struct
|
||||
pub struct Sute<S, F> {
|
||||
pub struct Sute<'a, S, F> {
|
||||
|
||||
// TODO: BE SMART. Inputs change the state, resize signals change the state, futures completing
|
||||
// change the state.
|
||||
|
||||
pub state: Mutable<SuteState>,
|
||||
statesig: MutableSignalCloned<SuteState>,
|
||||
pub state: Mutable<SuteState<'a>>,
|
||||
statesig: MutableSignalCloned<SuteState<'a>>,
|
||||
signal: S,
|
||||
inputs: Inputs,
|
||||
api: Option<ConnState<F>>,
|
||||
new: bool
|
||||
}
|
||||
|
||||
impl<S: Unpin, F: Unpin> Sute<S, F> {
|
||||
pub fn new(s: S, api: F) -> Self {
|
||||
impl<'a, S: Unpin, F: Unpin> Sute<'a, S, F> {
|
||||
pub fn new(s: S, log: Arc<LogDrain<'a>>, api: F) -> Self {
|
||||
let inputs = Inputs::new();
|
||||
let state = Mutable::new(SuteState::new());
|
||||
let state = Mutable::new(SuteState::new(log));
|
||||
|
||||
Self {
|
||||
statesig: state.signal_cloned(),
|
||||
@ -45,7 +56,7 @@ impl<S: Unpin, F: Unpin> Sute<S, F> {
|
||||
signal: s,
|
||||
inputs: inputs,
|
||||
api: Some(ConnState::Connecting(api)),
|
||||
new: true
|
||||
new: true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,13 +80,13 @@ impl<S: Unpin, F: Unpin> Sute<S, F> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_state(&self) -> SuteState {
|
||||
pub fn get_state(&self) -> SuteState<'a> {
|
||||
self.state.get_cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Signal<Item=(u16,u16)> + Unpin, F: Future<Output=Api> + Unpin> Signal for Sute<S, F> {
|
||||
type Item = SuteState;
|
||||
impl<'a, S: Signal<Item=(u16,u16)> + Unpin, F: Future<Output=Api> + Unpin> Signal for Sute<'a, S, F> {
|
||||
type Item = SuteState<'a>;
|
||||
fn poll_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
if let Poll::Ready(Some(key)) = Pin::new(&mut self.inputs).poll_next(cx) {
|
||||
self.handle_input(key);
|
||||
@ -97,22 +108,71 @@ impl<S: Signal<Item=(u16,u16)> + Unpin, F: Future<Output=Api> + Unpin> Signal fo
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SuteState {
|
||||
pub struct SuteState<'a> {
|
||||
pub active_win: Window,
|
||||
pub size: (u16,u16),
|
||||
pub running: bool,
|
||||
pub tick: usize,
|
||||
pub server: Option<String>,
|
||||
pub log: Arc<LogDrain<'a>>,
|
||||
}
|
||||
|
||||
impl SuteState {
|
||||
pub fn new() -> Self {
|
||||
impl<'a> SuteState<'a> {
|
||||
pub fn new(log: Arc<LogDrain<'a>>) -> Self {
|
||||
Self {
|
||||
active_win: Window::Main,
|
||||
size: (80,20),
|
||||
running: true,
|
||||
tick: 0,
|
||||
server: None
|
||||
server: None,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LogDrain<'a> {
|
||||
inner: Mutex<Vec<Spans<'a>>>,
|
||||
}
|
||||
|
||||
impl<'a> LogDrain<'a> {
|
||||
pub fn new() -> Self {
|
||||
Self { inner: Mutex::new(Vec::new()) }
|
||||
}
|
||||
pub fn get_inner(&self) -> MutexGuard<Vec<Spans<'a>>> {
|
||||
self.inner.lock().unwrap()
|
||||
}
|
||||
}
|
||||
impl<'a> Drain for LogDrain<'a> {
|
||||
type Ok = ();
|
||||
type Err = ();
|
||||
fn log(&self, record: &Record, values: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
|
||||
let critical_style: Style = Style::default().fg(Color::Magenta);
|
||||
let error_style: Style = Style::default().fg(Color::Red);
|
||||
let warning_style: Style = Style::default().fg(Color::Yellow);
|
||||
let info_style: Style = Style::default().fg(Color::Cyan);
|
||||
let debug_style: Style = Style::default().fg(Color::White);
|
||||
let trace_style: Style = Style::default().fg(Color::Green);
|
||||
|
||||
let lvlspan = match record.level() {
|
||||
Level::Critical => Span::styled("CRIT", critical_style),
|
||||
Level::Error => Span::styled("ERRO", error_style),
|
||||
Level::Warning => Span::styled("WARN", warning_style),
|
||||
Level::Info => Span::styled("INFO", info_style),
|
||||
Level::Debug => Span::styled("DEBG", debug_style),
|
||||
Level::Trace => Span::styled("TRCE", trace_style),
|
||||
};
|
||||
let contentspan = Span::from(record.msg().to_string());
|
||||
|
||||
{
|
||||
let mut v = self.inner.lock().unwrap();
|
||||
v.push(Spans::from(vec![
|
||||
Span::from("["), lvlspan, Span::from("]: "),
|
||||
contentspan,
|
||||
]));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
17
src/main.rs
17
src/main.rs
@ -1,3 +1,6 @@
|
||||
#[macro_use]
|
||||
extern crate slog;
|
||||
|
||||
use std::io;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
@ -54,9 +57,19 @@ fn main() -> Result<(), io::Error> {
|
||||
terminal.resize(tui::layout::Rect::new(0, 0, x,y)).unwrap();
|
||||
}
|
||||
|
||||
let drain = Arc::new(app::LogDrain::new());
|
||||
let log = slog::Logger::root(slog::Fuse::new(drain.clone()), o!());
|
||||
|
||||
let resize = util::Resize::new()?;
|
||||
let api = schema::Api::connect(server);
|
||||
let app = app::Sute::new(resize, Box::pin(api));
|
||||
let api = schema::Api::connect(log.clone(), server);
|
||||
let app = app::Sute::new(resize, drain, Box::pin(api));
|
||||
|
||||
crit!(log, "This is a test: {}", 42);
|
||||
error!(log, "This is a test: {}", 42);
|
||||
warn!(log, "This is a test: {}", 42);
|
||||
info!(log, "This is a test: {}", 42);
|
||||
debug!(log, "This is a test: {}", 42);
|
||||
trace!(log, "This is a test: {}", 42);
|
||||
|
||||
let mut state = app.get_state();
|
||||
terminal.draw(|f| ui::draw_ui(f, &mut state))?;
|
||||
|
@ -1,5 +1,7 @@
|
||||
use std::ffi::CStr;
|
||||
|
||||
use slog::Logger;
|
||||
|
||||
use futures::prelude::*;
|
||||
|
||||
use smol::io;
|
||||
@ -32,11 +34,11 @@ impl Api {
|
||||
pub fn new(stream: TcpStream, bffh: connection_capnp::bootstrap::Client) -> Self {
|
||||
Self { stream, bffh }
|
||||
}
|
||||
pub fn connect<A: AsyncToSocketAddrs>(addr: A) -> impl Future<Output=Api> {
|
||||
pub fn connect<A: AsyncToSocketAddrs>(log: Logger, addr: A) -> impl Future<Output=Api> {
|
||||
let f = async {
|
||||
let mut stream = TcpStream::connect(addr).await.unwrap();
|
||||
|
||||
handshake(&mut stream).await.unwrap();
|
||||
handshake(log.clone(), &mut stream).await.unwrap();
|
||||
let network = Box::new(twoparty::VatNetwork::new(stream.clone(), stream.clone(),
|
||||
rpc_twoparty_capnp::Side::Client, Default::default()));
|
||||
|
||||
@ -44,19 +46,23 @@ impl Api {
|
||||
let bffh: connection_capnp::bootstrap::Client
|
||||
= rpc_system.bootstrap(rpc_twoparty_capnp::Side::Server);
|
||||
|
||||
Api::new(stream, bffh)
|
||||
let mut api = Api::new(stream, bffh);
|
||||
|
||||
api.authenticate(log).await;
|
||||
|
||||
api
|
||||
};
|
||||
|
||||
f
|
||||
}
|
||||
|
||||
async fn authenticate(&mut self) {
|
||||
async fn authenticate(&mut self, log: Logger) {
|
||||
let r = self.bffh.auth_request();
|
||||
let auth = r.send().pipeline.get_auth();
|
||||
let m = auth.mechanisms_request().send().promise.await.unwrap();
|
||||
|
||||
for t in m.get().unwrap().get_mechs().unwrap().iter() {
|
||||
println!("{}", t.unwrap());
|
||||
info!(log, "Mechanism {} available", t.unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +114,7 @@ impl Api {
|
||||
//}
|
||||
}
|
||||
|
||||
async fn handshake(mut stream: &mut TcpStream) -> Result<(), io::Error> {
|
||||
async fn handshake(log: Logger, mut stream: &mut TcpStream) -> Result<(), io::Error> {
|
||||
let host = "localhost";
|
||||
let program = format!("{}-{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
|
||||
let version = (0u32,1u32);
|
||||
@ -129,9 +135,9 @@ async fn handshake(mut stream: &mut TcpStream) -> Result<(), io::Error> {
|
||||
let major = greeting.get_major();
|
||||
let minor = greeting.get_minor();
|
||||
|
||||
println!("Peer {} running {} API {}.{}", peer_host, peer_program, major, minor)
|
||||
info!(log, "Peer {} running {} API {}.{}", peer_host, peer_program, major, minor)
|
||||
} else {
|
||||
println!("Oh noes");
|
||||
error!(log, "Oh noes");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -25,25 +25,28 @@ pub fn draw_ui<B: Backend>(f: &mut Frame<B>, app: &mut SuteState) {
|
||||
}
|
||||
|
||||
fn draw_header<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
|
||||
f.render_widget(Clear, layout_chunk);
|
||||
f.render_widget(Block::default()
|
||||
.title("Header")
|
||||
.borders(Borders::ALL), layout_chunk);
|
||||
}
|
||||
|
||||
fn draw_main<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
|
||||
f.render_widget(Clear, layout_chunk);
|
||||
let chunk = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref())
|
||||
.split(layout_chunk);
|
||||
|
||||
f.render_widget(Paragraph::new(app.server.as_ref().map(|s| s.as_str()).unwrap_or("Not connected")), chunk[0]);
|
||||
f.render_widget(Paragraph::new("Main"), chunk[1]);
|
||||
|
||||
draw_logs(f, app, chunk[1])
|
||||
}
|
||||
fn draw_logs<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
|
||||
// TODO: Just use a signal.
|
||||
let v = app.log.get_inner().clone();
|
||||
f.render_widget(Paragraph::new(v.into_iter().collect::<Vec<tui::text::Spans>>()), layout_chunk);
|
||||
}
|
||||
|
||||
fn draw_command_line<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
|
||||
f.render_widget(Clear, layout_chunk);
|
||||
f.render_widget(Block::default()
|
||||
.title("Command line")
|
||||
.borders(Borders::ALL), layout_chunk);
|
||||
|
Loading…
x
Reference in New Issue
Block a user