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"
|
signal-hook = "0.1"
|
||||||
|
|
||||||
|
slog = "2.5"
|
||||||
|
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
rsasl = "0.1"
|
rsasl = "0.1"
|
||||||
|
|
||||||
|
88
src/app.rs
88
src/app.rs
@ -1,5 +1,6 @@
|
|||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
|
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use futures_signals::signal::{Mutable, Signal, MutableSignalCloned};
|
use futures_signals::signal::{Mutable, Signal, MutableSignalCloned};
|
||||||
@ -9,6 +10,16 @@ use termion::event::Key;
|
|||||||
use crate::input::Inputs;
|
use crate::input::Inputs;
|
||||||
use crate::schema::Api;
|
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)]
|
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||||
pub enum Window {
|
pub enum Window {
|
||||||
Main,
|
Main,
|
||||||
@ -21,23 +32,23 @@ enum ConnState<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Application state struct
|
/// 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
|
// TODO: BE SMART. Inputs change the state, resize signals change the state, futures completing
|
||||||
// change the state.
|
// change the state.
|
||||||
|
|
||||||
pub state: Mutable<SuteState>,
|
pub state: Mutable<SuteState<'a>>,
|
||||||
statesig: MutableSignalCloned<SuteState>,
|
statesig: MutableSignalCloned<SuteState<'a>>,
|
||||||
signal: S,
|
signal: S,
|
||||||
inputs: Inputs,
|
inputs: Inputs,
|
||||||
api: Option<ConnState<F>>,
|
api: Option<ConnState<F>>,
|
||||||
new: bool
|
new: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Unpin, F: Unpin> Sute<S, F> {
|
impl<'a, S: Unpin, F: Unpin> Sute<'a, S, F> {
|
||||||
pub fn new(s: S, api: F) -> Self {
|
pub fn new(s: S, log: Arc<LogDrain<'a>>, api: F) -> Self {
|
||||||
let inputs = Inputs::new();
|
let inputs = Inputs::new();
|
||||||
let state = Mutable::new(SuteState::new());
|
let state = Mutable::new(SuteState::new(log));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
statesig: state.signal_cloned(),
|
statesig: state.signal_cloned(),
|
||||||
@ -45,7 +56,7 @@ impl<S: Unpin, F: Unpin> Sute<S, F> {
|
|||||||
signal: s,
|
signal: s,
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
api: Some(ConnState::Connecting(api)),
|
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()
|
self.state.get_cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Signal<Item=(u16,u16)> + Unpin, F: Future<Output=Api> + Unpin> Signal for Sute<S, F> {
|
impl<'a, S: Signal<Item=(u16,u16)> + Unpin, F: Future<Output=Api> + Unpin> Signal for Sute<'a, S, F> {
|
||||||
type Item = SuteState;
|
type Item = SuteState<'a>;
|
||||||
fn poll_change(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
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) {
|
if let Poll::Ready(Some(key)) = Pin::new(&mut self.inputs).poll_next(cx) {
|
||||||
self.handle_input(key);
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SuteState {
|
pub struct SuteState<'a> {
|
||||||
pub active_win: Window,
|
pub active_win: Window,
|
||||||
pub size: (u16,u16),
|
pub size: (u16,u16),
|
||||||
pub running: bool,
|
pub running: bool,
|
||||||
pub tick: usize,
|
pub tick: usize,
|
||||||
pub server: Option<String>,
|
pub server: Option<String>,
|
||||||
|
pub log: Arc<LogDrain<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SuteState {
|
impl<'a> SuteState<'a> {
|
||||||
pub fn new() -> Self {
|
pub fn new(log: Arc<LogDrain<'a>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
active_win: Window::Main,
|
active_win: Window::Main,
|
||||||
size: (80,20),
|
size: (80,20),
|
||||||
running: true,
|
running: true,
|
||||||
tick: 0,
|
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::io;
|
||||||
use std::sync::{Arc, Mutex};
|
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();
|
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 resize = util::Resize::new()?;
|
||||||
let api = schema::Api::connect(server);
|
let api = schema::Api::connect(log.clone(), server);
|
||||||
let app = app::Sute::new(resize, Box::pin(api));
|
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();
|
let mut state = app.get_state();
|
||||||
terminal.draw(|f| ui::draw_ui(f, &mut state))?;
|
terminal.draw(|f| ui::draw_ui(f, &mut state))?;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
|
||||||
|
use slog::Logger;
|
||||||
|
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
|
|
||||||
use smol::io;
|
use smol::io;
|
||||||
@ -32,11 +34,11 @@ impl Api {
|
|||||||
pub fn new(stream: TcpStream, bffh: connection_capnp::bootstrap::Client) -> Self {
|
pub fn new(stream: TcpStream, bffh: connection_capnp::bootstrap::Client) -> Self {
|
||||||
Self { stream, bffh }
|
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 f = async {
|
||||||
let mut stream = TcpStream::connect(addr).await.unwrap();
|
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(),
|
let network = Box::new(twoparty::VatNetwork::new(stream.clone(), stream.clone(),
|
||||||
rpc_twoparty_capnp::Side::Client, Default::default()));
|
rpc_twoparty_capnp::Side::Client, Default::default()));
|
||||||
|
|
||||||
@ -44,19 +46,23 @@ impl Api {
|
|||||||
let bffh: connection_capnp::bootstrap::Client
|
let bffh: connection_capnp::bootstrap::Client
|
||||||
= rpc_system.bootstrap(rpc_twoparty_capnp::Side::Server);
|
= 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
|
f
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn authenticate(&mut self) {
|
async fn authenticate(&mut self, log: Logger) {
|
||||||
let r = self.bffh.auth_request();
|
let r = self.bffh.auth_request();
|
||||||
let auth = r.send().pipeline.get_auth();
|
let auth = r.send().pipeline.get_auth();
|
||||||
let m = auth.mechanisms_request().send().promise.await.unwrap();
|
let m = auth.mechanisms_request().send().promise.await.unwrap();
|
||||||
|
|
||||||
for t in m.get().unwrap().get_mechs().unwrap().iter() {
|
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 host = "localhost";
|
||||||
let program = format!("{}-{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
|
let program = format!("{}-{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
|
||||||
let version = (0u32,1u32);
|
let version = (0u32,1u32);
|
||||||
@ -129,9 +135,9 @@ async fn handshake(mut stream: &mut TcpStream) -> Result<(), io::Error> {
|
|||||||
let major = greeting.get_major();
|
let major = greeting.get_major();
|
||||||
let minor = greeting.get_minor();
|
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 {
|
} else {
|
||||||
println!("Oh noes");
|
error!(log, "Oh noes");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
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) {
|
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()
|
f.render_widget(Block::default()
|
||||||
.title("Header")
|
.title("Header")
|
||||||
.borders(Borders::ALL), layout_chunk);
|
.borders(Borders::ALL), layout_chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_main<B: Backend>(f: &mut Frame<B>, app: &mut SuteState, layout_chunk: Rect) {
|
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()
|
let chunk = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref())
|
.constraints([Constraint::Percentage(20), Constraint::Percentage(80)].as_ref())
|
||||||
.split(layout_chunk);
|
.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(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) {
|
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()
|
f.render_widget(Block::default()
|
||||||
.title("Command line")
|
.title("Command line")
|
||||||
.borders(Borders::ALL), layout_chunk);
|
.borders(Borders::ALL), layout_chunk);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user