added logger

LOG_LEVEL env var is now supported
This commit is contained in:
Niklas Kapelle 2025-04-26 18:54:46 +02:00
parent e77ee9c8a3
commit 6496f671d9
Signed by: niklas
GPG Key ID: 4EB651B36D841D16
6 changed files with 88 additions and 16 deletions

33
Cargo.lock generated
View File

@ -395,12 +395,14 @@ version = "0.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"gpio", "gpio",
"log",
"regex", "regex",
"rocket", "rocket",
"rppal", "rppal",
"rust-embed", "rust-embed",
"serde", "serde",
"serde_json", "serde_json",
"simplelog",
"tokio", "tokio",
] ]
@ -786,6 +788,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "num_threads"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "object" name = "object"
version = "0.36.7" version = "0.36.7"
@ -1278,6 +1289,17 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "simplelog"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16257adbfaef1ee58b1363bdc0664c9b8e1e30aed86049635fb5f147d065a9c0"
dependencies = [
"log",
"termcolor",
"time",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@ -1351,6 +1373,15 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "thread_local" name = "thread_local"
version = "1.1.8" version = "1.1.8"
@ -1369,7 +1400,9 @@ checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
dependencies = [ dependencies = [
"deranged", "deranged",
"itoa", "itoa",
"libc",
"num-conv", "num-conv",
"num_threads",
"powerfmt", "powerfmt",
"serde", "serde",
"time-core", "time-core",

View File

@ -13,6 +13,8 @@ serde_json = "1.0.140"
rocket = "0.5.1" rocket = "0.5.1"
tokio = { version = "1.44.2", features = ["full"] } tokio = { version = "1.44.2", features = ["full"] }
rust-embed = "8.7.0" rust-embed = "8.7.0"
log = "0.4.27"
simplelog = "0.12.2"
[target.armv7-unknown-linux-gnueabihf] [target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc" linker = "arm-linux-gnueabihf-gcc"

View File

@ -1,13 +1,21 @@
use log::info;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
error::Error, error::Error,
fmt::Display,
fs, fs,
}; };
#[derive(PartialEq, Eq, Deserialize, Serialize, Hash, Clone, PartialOrd, Ord)] #[derive(PartialEq, Eq, Deserialize, Serialize, Hash, Clone, PartialOrd, Ord)]
pub struct TallyID(pub String); pub struct TallyID(pub String);
impl Display for TallyID {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct AttendanceDay { pub struct AttendanceDay {
date: String, date: String,
@ -106,6 +114,7 @@ impl AttendanceDay {
if self.ids.contains(&id) { if self.ids.contains(&id) {
return; return;
} }
info!("Adding id: {}", id);
self.ids.push(id); self.ids.push(id);
} }
} }

View File

@ -1,8 +1,9 @@
use std::sync::Arc;
use id_store::IDStore; use id_store::IDStore;
use log::{LevelFilter, error, info, warn};
use pm3::{pm3_mock, run_pm3}; use pm3::{pm3_mock, run_pm3};
use tokio::sync::{mpsc, Mutex}; use simplelog::{ConfigBuilder, SimpleLogger};
use std::{env, sync::Arc};
use tokio::sync::{Mutex, mpsc};
use webserver::start_webserver; use webserver::start_webserver;
mod id_store; mod id_store;
@ -10,17 +11,40 @@ mod parser;
mod pm3; mod pm3;
mod webserver; mod webserver;
fn setup_logger() {
let log_level = env::var("LOG_LEVEL")
.ok()
.and_then(|level| level.parse::<LevelFilter>().ok())
.unwrap_or({
if cfg!(debug_assertions) {
LevelFilter::Debug
} else {
LevelFilter::Warn
}
});
let config = ConfigBuilder::new()
.set_target_level(LevelFilter::Error)
.build();
let _ = SimpleLogger::init(log_level, config);
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
setup_logger();
info!("Starting application");
let (tx, mut rx) = mpsc::channel::<String>(1); let (tx, mut rx) = mpsc::channel::<String>(1);
tokio::spawn(async move { tokio::spawn(async move {
match run_pm3(tx).await { match run_pm3(tx).await {
Ok(()) => { Ok(()) => {
println!("PM3 exited with an zero error code"); warn!("PM3 exited with a zero exit code");
} }
Err(e) => { Err(e) => {
println!("PM3 failed to run: {}", e); error!("Failed to run PM3: {}", e);
} }
} }
}); });
@ -37,7 +61,7 @@ async fn main() {
match start_webserver(store.clone()).await { match start_webserver(store.clone()).await {
Ok(()) => {} Ok(()) => {}
Err(e) => { Err(e) => {
eprintln!("Failed to start webserver: {}", e); error!("Failed to start webserver: {}", e);
} }
} }
} }

View File

@ -1,18 +1,18 @@
use log::{debug, error, info};
use std::env; use std::env;
use std::error::Error; use std::error::Error;
use std::io::{self, BufRead}; use std::io::{self, BufRead};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use tokio::time::{Duration, sleep};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio::time::{Duration, sleep};
pub async fn run_pm3(tx: mpsc::Sender<String>) -> Result<(), Box<dyn Error>> { pub async fn run_pm3(tx: mpsc::Sender<String>) -> Result<(), Box<dyn Error>> {
let pm3_path = match env::var("PM3_BIN") { let pm3_path = match env::var("PM3_BIN") {
Ok(path) => path, Ok(path) => path,
Err(_) => { Err(_) => {
println!("PM3_BIN not set. Using default value"); info!("PM3_BIN not set. Using default value");
"pm3".to_owned() "pm3".to_owned()
}, }
}; };
let mut cmd = Command::new("stdbuf") let mut cmd = Command::new("stdbuf")
@ -29,18 +29,20 @@ pub async fn run_pm3(tx: mpsc::Sender<String>) -> Result<(), Box<dyn Error>> {
for line_result in reader.lines() { for line_result in reader.lines() {
match line_result { match line_result {
Ok(line) => { Ok(line) => {
debug!("PM3: {}", line);
let parse_result = super::parser::parse_line(&line); let parse_result = super::parser::parse_line(&line);
if let Some(uid) = parse_result { if let Some(uid) = parse_result {
debug!("Read ID: {}", uid);
match tx.send(uid).await { match tx.send(uid).await {
Ok(()) => {} Ok(()) => {}
Err(e) => { Err(e) => {
eprintln!("Failed to send to channel: {}", e); error!("Failed to send to channel: {}", e);
} }
} }
} }
} }
Err(e) => { Err(e) => {
eprintln!("{}", e); error!("Failed to read line from PM3: {}", e);
} }
} }
} }
@ -50,7 +52,7 @@ pub async fn run_pm3(tx: mpsc::Sender<String>) -> Result<(), Box<dyn Error>> {
if status.success() { if status.success() {
Ok(()) Ok(())
} else { } else {
Err("pm3 had non zero exit code".into()) Err("PM3 exited with a non zero exit code".into())
} }
} }
@ -60,7 +62,7 @@ pub async fn pm3_mock(tx: mpsc::Sender<String>) -> Result<(), Box<dyn Error>> {
match tx.send("F1409618".to_owned()).await { match tx.send("F1409618".to_owned()).await {
Ok(()) => {} Ok(()) => {}
Err(e) => { Err(e) => {
eprintln!("Failed to send to channel: {}", e); error!("Failed to send to channel: {}", e);
} }
} }

View File

@ -1,3 +1,4 @@
use log::{error, info};
use rocket::http::Status; use rocket::http::Status;
use rocket::{Config, State}; use rocket::{Config, State};
use rocket::{get, http::ContentType, response::content::RawHtml, routes}; use rocket::{get, http::ContentType, response::content::RawHtml, routes};
@ -49,10 +50,11 @@ fn static_files(file: std::path::PathBuf) -> Option<(ContentType, Vec<u8>)> {
#[get("/api/csv")] #[get("/api/csv")]
async fn export_csv(manager: &State<Arc<Mutex<IDStore>>>) -> Result<String, Status> { async fn export_csv(manager: &State<Arc<Mutex<IDStore>>>) -> Result<String, Status> {
info!("Exporting CSV");
match manager.lock().await.export_csv() { match manager.lock().await.export_csv() {
Ok(csv) => Ok(csv), Ok(csv) => Ok(csv),
Err(e) => { Err(e) => {
eprintln!("Failed to generate csv: {}", e); error!("Failed to generate csv: {}", e);
Err(Status::InternalServerError) Err(Status::InternalServerError)
} }
} }