Browse Source

Finish logger

new_protocol
ThePerkinrex 5 years ago
parent
commit
5a4b7f953c
No known key found for this signature in database GPG Key ID: 1F45A7C4BFB41607
  1. 3
      .gitignore
  2. 22
      .vscode/launch.json
  3. 277
      server/src/logger.rs
  4. 36
      server/src/logger/color_message.rs
  5. 28
      server/src/main.rs

3
.gitignore

@ -0,0 +1,3 @@
db.sqlite*
output.log
properties.json

22
.vscode/launch.json

@ -0,0 +1,22 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Cargo launch",
"cargo": {
"args": [
"build",
"--manifest-path",
"server/Cargo.toml"
]
},
"program": "${cargo:program}",
"args": []
}
]
}

277
server/src/logger.rs

@ -10,47 +10,42 @@ use crossterm::{
terminal::{Clear, ClearType}, terminal::{Clear, ClearType},
}; };
use fern::colors::{ColoredLevelConfig, Color}; use fern::colors::{Color, ColoredLevelConfig};
pub fn setup() -> Result<(Close, Stdin<String>), fern::InitError> {
let (stdout, stdin, close, join_handle) = TerminalHandler::new(|x| { mod color_message;
if x == "sv_cheats" { use color_message::print_line;
log::info!("CHEATS ENABLED")
} // TODO: Cleanup
x
}); pub fn setup(
let colors_line = ColoredLevelConfig::new() properties: &crate::server_properties::ServerProperties,
.error(Color::Red) ) -> Result<(Close, Stdin<String>), fern::InitError> {
.warn(Color::Yellow) let (stdout, stdin, close, join_handle) = TerminalHandler::new(
// we actually don't need to specify the color for debug and info, they are white by default |x| {
.info(Color::White) if x == "sv_cheats" {
.debug(Color::BrightBlack) log::info!("CHEATS ENABLED")
// depending on the terminals color scheme, this is the same as the background color }
.trace(Color::BrightBlack); x
let colors_level = colors_line.clone().info(Color::Green).debug(Color::BrightBlack); },
let stdout_logger = fern::Dispatch::new() properties.use_colors,
.format(move |out, message, record| { );
out.finish(format_args!(
"{colors_line}{}[{}{colors_line}][{}] {}\x1B[0m", // let simple_formatter = |out: fern::FormatCallback, message: _, record: &log::Record| {
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"), // out.finish(format_args!(
colors_level.clone().color(record.level()), // "{}[{}][{}] {}",
record.target(), // chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
message, // record.level(),
colors_line = format!("\x1B[{}m", colors_line.clone().get_color(&record.level()).to_fg_str()), // record.target(),
// colors_level = colors_level.clone().get_color(&record.level()).to_fg_str(), // message,
)) // ))
}) // };
.level(log::LevelFilter::Debug) let stdout_logger = if properties.use_colors {
colored_formatter(fern::Dispatch::new())
} else {
simple_formatter(fern::Dispatch::new())
}
.chain(stdout); .chain(stdout);
let file = fern::Dispatch::new().format(|out, message, record| { let file = simple_formatter(fern::Dispatch::new()).chain(
out.finish(format_args!(
"{}[{}][{}] {}",
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
record.level(),
record.target(),
message,
))
})
.chain(
std::fs::OpenOptions::new() std::fs::OpenOptions::new()
.write(true) .write(true)
.create(true) .create(true)
@ -59,16 +54,67 @@ pub fn setup() -> Result<(Close, Stdin<String>), fern::InitError> {
); );
fern::Dispatch::new() fern::Dispatch::new()
.level(log::LevelFilter::Debug)
.level_for("h2::codec", log::LevelFilter::Info) .level_for("h2::codec", log::LevelFilter::Info)
.level_for("tokio::codec", log::LevelFilter::Info) .level_for("tokio::codec", log::LevelFilter::Info)
.level_for("sqlx::query", log::LevelFilter::Info) .level_for("sqlx::query", log::LevelFilter::Info)
.chain(stdout_logger) .chain(stdout_logger)
.chain(file) .chain(file)
.apply()?; .apply()?;
log::warn!("TEST1"); log::info!("Saving output to output.log");
log::error!("TEST2");
// std::process::exit(1); // std::process::exit(1);
Ok((Close{close, handle: join_handle}, stdin)) Ok((
Close {
close,
handle: join_handle,
},
stdin,
))
}
fn simple_formatter(d: fern::Dispatch) -> fern::Dispatch {
d.format(
|out: fern::FormatCallback, message: _, record: &log::Record| {
out.finish(format_args!(
"{}[{}][{}] {}",
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
record.level(),
record.target(),
message,
))
},
)
}
fn colored_formatter(d: fern::Dispatch) -> fern::Dispatch {
let colors_line = ColoredLevelConfig::new()
.error(Color::Red)
.warn(Color::Yellow)
// we actually don't need to specify the color for debug and info, they are white by default
.info(Color::White)
.debug(Color::BrightBlack)
// depending on the terminals color scheme, this is the same as the background color
.trace(Color::BrightBlack);
let colors_level = colors_line
.clone()
.info(Color::Green)
.debug(Color::BrightBlack);
d.format(
move |out: fern::FormatCallback, message: _, record: &log::Record| {
out.finish(format_args!(
"{colors_line}{}[{}{colors_line}][{}] {}\x1B[0m",
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
colors_level.clone().color(record.level()),
record.target(),
message,
colors_line = format!(
"\x1B[{}m",
colors_line.clone().get_color(&record.level()).to_fg_str()
),
// colors_level = colors_level.clone().get_color(&record.level()).to_fg_str(),
))
},
)
} }
pub type Stdout = mpsc::Sender<String>; pub type Stdout = mpsc::Sender<String>;
@ -83,8 +129,9 @@ where
stdin: mpsc::Sender<T>, stdin: mpsc::Sender<T>,
close: mpsc::Receiver<()>, close: mpsc::Receiver<()>,
handler: F, handler: F,
lines: LimitedVec<String>, lines: LimitedVec<String>,
command: String, command: String,
use_colors: bool,
} }
impl<T, F> TerminalHandler<T, F> impl<T, F> TerminalHandler<T, F>
@ -94,6 +141,7 @@ where
{ {
fn new( fn new(
handler: F, handler: F,
use_colors: bool,
) -> ( ) -> (
Stdout, Stdout,
Stdin<T>, Stdin<T>,
@ -112,17 +160,16 @@ where
stdin: stdin_send, stdin: stdin_send,
close: close_recv, close: close_recv,
handler, handler,
lines: LimitedVec::new(crossterm::terminal::size().unwrap().1 as usize - 1), lines: LimitedVec::new(crossterm::terminal::size().unwrap().1 as usize - 1),
command: String::new(), command: String::new(),
use_colors,
}; };
loop { loop {
if s.iterate() { if s.iterate() {
break; break;
} }
} }
queue!(stdout, crossterm::event::DisableMouseCapture).unwrap(); cleanup();
crossterm::terminal::disable_raw_mode().ok();
println!("Closing printing thread");
}); });
(stdout_send, stdin_recv, close_send, join_handle) (stdout_send, stdin_recv, close_send, join_handle)
} }
@ -132,46 +179,42 @@ where
match self.close.try_recv() { match self.close.try_recv() {
Err(mpsc::TryRecvError::Empty) => (), Err(mpsc::TryRecvError::Empty) => (),
_ => return true, _ => return true,
} }
while is_event_available() { while is_event_available() {
match crossterm::event::read().unwrap() { match crossterm::event::read().unwrap() {
Event::Resize(_cols, rows) => self.lines.size = rows as usize - 1, Event::Resize(_cols, rows) => self.lines.size = rows as usize - 1,
Event::Key(k) => match (k.code, k.modifiers) { Event::Key(k) => match (k.code, k.modifiers) {
(KeyCode::Char('c'), KeyModifiers::CONTROL) => { (KeyCode::Char('c'), KeyModifiers::CONTROL) => {
let mut stdout = std::io::stdout(); cleanup();
queue!(stdout, crossterm::event::DisableMouseCapture).unwrap();
crossterm::terminal::disable_raw_mode().unwrap();
stdout.flush().unwrap();
println!("Exiting server");
std::process::exit(0) std::process::exit(0)
} }
(k, _m) => { (k, _m) => match k {
match k { KeyCode::Char(c) => self.command.push(c),
KeyCode::Char(c) => self.command.push(c), KeyCode::Backspace => {
KeyCode::Backspace => {self.command.pop();}, self.command.pop();
KeyCode::Enter => { }
log::info!(target: "COMMAND", "{}", self.command); KeyCode::Enter => {
match self.stdin.send((self.handler)(self.command.clone())) { log::info!(target: "command", " >> {}", self.command);
Ok(_) => (), match self.stdin.send((self.handler)(self.command.clone())) {
Err(e) => log::error!("{}", e), Ok(_) => (),
}; Err(e) => log::error!("{}", e),
self.command = String::new(); };
} self.command = String::new();
KeyCode::Esc => { }
self.lines.scroll_to_bottom(); KeyCode::Esc => {
} self.lines.scroll_to_bottom();
_ => () }
} _ => (),
}, },
}, },
Event::Mouse(m) => match m { Event::Mouse(m) => match m {
MouseEvent::ScrollUp(_, _, _) => self.lines.scroll_up(), MouseEvent::ScrollUp(_, _, _) => self.lines.scroll_up(),
MouseEvent::ScrollDown(_, _, _) => self.lines.scroll_down(), MouseEvent::ScrollDown(_, _, _) => self.lines.scroll_down(),
_ => (), _ => (),
}, },
} }
updated = true; updated = true;
} }
while let Some(x) = match self.stdout.try_recv() { while let Some(x) = match self.stdout.try_recv() {
Err(mpsc::TryRecvError::Empty) => None, Err(mpsc::TryRecvError::Empty) => None,
@ -190,18 +233,44 @@ where
// println!("Got stdout"); // println!("Got stdout");
if updated { if updated {
queue!(stdout, Clear(ClearType::All), MoveTo(0, 0)).unwrap(); queue!(stdout, Clear(ClearType::All), MoveTo(0, 0)).unwrap();
for v in self.lines.iter() { let mut i = 0;
queue!(stdout, Print(v), MoveToNextLine(1)).unwrap(); let size = crossterm::terminal::size().unwrap();
for v in self.lines.iter(self.use_colors) {
print_line(&v, self.use_colors, &mut stdout);
queue!(stdout, MoveToNextLine(1)).unwrap();
i += 1;
if i >= size.1 as usize - 1 {
break;
}
// println!("{}", v); // println!("{}", v);
} }
let size = crossterm::terminal::size().unwrap(); queue!(
queue!(stdout, MoveTo(0, size.1), Clear(ClearType::CurrentLine), Print(&self.command)).unwrap(); stdout,
MoveTo(0, size.1),
// Clear(ClearType::CurrentLine),
Print(&format!(" >> {}", self.command))
)
.unwrap();
stdout.flush().unwrap(); stdout.flush().unwrap();
} }
false false
} }
} }
fn cleanup() {
let mut stdout = std::io::stdout();
queue!(
stdout,
Clear(ClearType::All),
MoveTo(0, 0),
crossterm::event::DisableMouseCapture
)
.unwrap();
crossterm::terminal::disable_raw_mode().unwrap();
stdout.flush().unwrap();
println!("Exiting server, output has been saved to output.log");
}
impl<T, F> Drop for TerminalHandler<T, F> impl<T, F> Drop for TerminalHandler<T, F>
where where
T: Send + 'static, T: Send + 'static,
@ -218,15 +287,15 @@ fn is_event_available() -> bool {
} }
pub struct Close { pub struct Close {
close: mpsc::Sender<()>, close: mpsc::Sender<()>,
handle: std::thread::JoinHandle<()>, handle: std::thread::JoinHandle<()>,
} }
impl Close { impl Close {
pub fn close(self) { pub fn close(self) {
self.close.send(()).unwrap(); self.close.send(()).unwrap();
self.handle.join().unwrap(); self.handle.join().unwrap();
println!("CLOSING"); println!("CLOSING");
queue!(std::io::stdout(), crossterm::event::DisableMouseCapture).unwrap(); queue!(std::io::stdout(), crossterm::event::DisableMouseCapture).unwrap();
} }
} }
@ -249,15 +318,18 @@ impl<T> LimitedVec<T> {
fn push(&mut self, v: T) { fn push(&mut self, v: T) {
// while self.inner.len() >= self.size { // while self.inner.len() >= self.size {
// self.inner.remove(0); // self.inner.remove(0);
// } // }
if self.pos != 0 { if self.pos != 0 {
self.pos += 1; self.pos += 1;
} }
self.inner.push(v); self.inner.push(v);
// assert!(self.inner.len() <= self.size) // assert!(self.inner.len() <= self.size)
} }
fn iter(&self) -> std::slice::Iter<T> { fn iter<'a>(&'a self, use_colors: bool) -> Box<dyn Iterator<Item = String> + 'a>
where
T: std::fmt::Display,
{
let start = if self.inner.len() < self.size { let start = if self.inner.len() < self.size {
0 0
} else { } else {
@ -271,7 +343,24 @@ impl<T> LimitedVec<T> {
if end < self.inner.len() { if end < self.inner.len() {
end = self.inner.len() end = self.inner.len()
} }
self.inner[start..end].iter() let iter = self.inner[start..end].iter();
let map = iter.enumerate().map(move |(i, x)| {
format!(
"{}{}",
if use_colors {
format!(
"\x1B[{}m{:>5}\x1B[0m ",
fern::colors::Color::BrightBlack.to_fg_str(),
start + i
)
} else {
String::new()
},
x
)
});
Box::new(map)
} }
fn scroll_up(&mut self) { fn scroll_up(&mut self) {

36
server/src/logger/color_message.rs

@ -0,0 +1,36 @@
use crossterm::{
cursor::{MoveRight, MoveToNextLine},
event::{Event, KeyCode, KeyModifiers, MouseEvent},
queue,
style::{Print, PrintStyledContent},
};
use std::io::Write;
pub fn print_line(message: &String, use_colors: bool, stdout: &mut std::io::Stdout) {
if use_colors {
let mut s = String::new();
let mut highlight = false;
for c in message.chars() {
if c == '`' {
// queue!(stdout, Print(format!("{}`", highlight))).unwrap();
if highlight {
let styled = format!("\x1B[{}m{}\x1B[0m", fern::colors::Color::Blue.to_fg_str(), s);
queue!(stdout, Print(styled)).unwrap();
s = String::new();
}else{
queue!(stdout, Print(s)).unwrap();
s = String::new();
}
highlight = !highlight;
continue;
}
s.push(c);
}
queue!(stdout, Print(&s)).unwrap();
}else {
queue!(stdout, Print(message)).unwrap();
}
}

28
server/src/main.rs

@ -4,31 +4,29 @@ mod games;
mod logger; mod logger;
mod server_properties; mod server_properties;
use log::info;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
server_properties::setup(); server_properties::setup();
let p = server_properties::ServerProperties::load(); let p = server_properties::ServerProperties::load();
let (close, _stdin) = logger::setup().unwrap(); let (close, _stdin) = logger::setup(&p).unwrap();
// protobuf::route_guide_grpc::RouteGuid info!(target: "setup", "Server name: `{}`", p.name);
// for i in 0..100 { info!(target: "setup", "Serving on address `{}`", p.addr);
// std::thread::sleep(std::time::Duration::from_secs_f32(0.1)); // for i in 0..1000 {
// std::thread::sleep(std::time::Duration::from_secs_f32(1.));
// if i == 69 { // info!("{}\nTEXTETX\nTEXT", i)
// log::info!("69 Nͬ͂ͧi̽̅̽҉̫̕͢ĉ͆̚҉̢͞͏eͫ̑͑");
// std::thread::sleep(std::time::Duration::from_secs_f32(0.2));
// }else{
// log::info!("{}", i);
// }
// } // }
// std::thread::sleep(std::time::Duration::from_secs_f32(200.));
info!(target: "setup", "Loading games from the games directory");
let games = games::load_games(); let games = games::load_games();
log::info!("{:?}", games); log::info!("{:?}", games);
games[0].run(4); games[0].run(4);
info!(target: "setup", "Loading database");
let pool = db::DbPool::new().await; let pool = db::DbPool::new().await;
// let mut conn = pool.acquire().await; info!(target: "setup", "Starting server");
// println!("{}", conn.add_user("Hi").await);
// println!("{:?}", conn.users().await);
// conn.close().await;
grpc::start(pool, games, p).await; grpc::start(pool, games, p).await;
close.close(); close.close();
} }

Loading…
Cancel
Save