Skip to content

Commit

Permalink
panic hook implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
danwritecode committed Apr 27, 2023
1 parent 1c8c9b9 commit ddf763a
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 15 deletions.
59 changes: 58 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "log_anywhere"
version = "0.0.3"
version = "0.0.4"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand All @@ -13,3 +13,4 @@ reqwest = { version = "^0.11", features = ["json"] }
serde = { version = "^1", features = ["derive"] }
serde_json = "^1"
crossbeam = "^0.8"
futures = "0.3.28"
74 changes: 66 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub use crate::providers::prelude::*;

use std::sync::{ Arc, Mutex };
use std::time::Duration;
use std::mem;
use std::{ mem, panic, thread };

use log::{Log, SetLoggerError};
use anyhow::Result;
Expand All @@ -28,13 +28,17 @@ pub struct LogAnywhereLogger {
provider: Arc<dyn LogProvider>,
log_buffer_records: Arc<Mutex<Vec<LogAnywhereRecord>>>,
buffer_timing: Arc<u64>,
buffer_emptied_on_panic: Arc<Mutex<bool>>,
is_panicking: Arc<Mutex<bool>>,
level: Arc<log::LevelFilter> // TO DO: Make this into string slice
}

async fn buffer_loop(
log_buffer_records: Arc<Mutex<Vec<LogAnywhereRecord>>>,
provider: Arc<dyn LogProvider>,
buffer_timing: Arc<u64>
buffer_timing: Arc<u64>,
buffer_emptied_on_panic: Arc<Mutex<bool>>,
is_panicking: Arc<Mutex<bool>>
) {
loop {
let messages = {
Expand All @@ -44,11 +48,49 @@ async fn buffer_loop(

if messages.len() > 0 {
provider.send_log(messages).await;

if *is_panicking.lock().unwrap() {
println!("panic state detected");
if log_buffer_records.lock().unwrap().len() == 0 {
println!("buffer empty in panic, exiting");
*buffer_emptied_on_panic.lock().unwrap() = true;
} else {
println!("buffer not empty, waiting for next loop cycle to empty buffer");
}
}
}
sleep(Duration::from_secs(*buffer_timing)).await
}
}

fn set_panic_hook (
log_buffer_records: Arc<Mutex<Vec<LogAnywhereRecord>>>,
buffer_emptied_on_panic: Arc<Mutex<bool>>,
is_panicking: Arc<Mutex<bool>>
) {

panic::set_hook(Box::new(move |p| {
eprintln!("{}", p);
eprintln!("waiting for log_anywhere to cleanup, 1 second please");
*is_panicking.lock().unwrap() = true;

let file = p.location().map(|l| l.file().to_string());
let line = p.location().map(|l| l.line());

let anywhere_log = LogAnywhereRecord {
level: "PANIC".to_string(),
message: p.to_string(),
file,
line
};

log_buffer_records.lock().unwrap().push(anywhere_log);

// loop infinitely until buffer is emptied
while !*buffer_emptied_on_panic.lock().unwrap() {}
}));
}

impl LogAnywhereLogger {
/// Initializes the global logger with a LogAnywhereLogger instance.
///
Expand All @@ -72,19 +114,35 @@ impl LogAnywhereLogger {
provider,
log_buffer_records: Arc::new(Mutex::new(Vec::new())),
buffer_timing: Arc::new(buffer_timing),
buffer_emptied_on_panic: Arc::new(Mutex::new(false)),
is_panicking: Arc::new(Mutex::new(false)),
level: Arc::new(level),
}
}

pub fn init(self: Box<Self>) -> Result<(), SetLoggerError> {
let buff_rec_clone = Arc::clone(&self.log_buffer_records);
let provider_clone = Arc::clone(&self.provider);
let buffer_timing_clone = Arc::clone(&self.buffer_timing);
let level_clone = Arc::clone(&self.level);
task::spawn(buffer_loop(buff_rec_clone, provider_clone, buffer_timing_clone));
let level_ptr = Arc::clone(&self.level);

// set panic hook
set_panic_hook(
self.log_buffer_records.clone(),
self.buffer_emptied_on_panic.clone(),
self.is_panicking.clone()
);

// start buffer_loop
task::spawn(
buffer_loop(
self.log_buffer_records.clone(),
self.provider.clone(),
self.buffer_timing.clone(),
self.buffer_emptied_on_panic.clone(),
self.is_panicking.clone()
)
);

log::set_boxed_logger(self)?;
log::set_max_level(*level_clone);
log::set_max_level(*level_ptr);
Ok(())
}
}
Expand Down
12 changes: 7 additions & 5 deletions src/providers/axiom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ impl AxiomProvider {
#[async_trait]
impl LogProvider for AxiomProvider {
async fn send_log(&self, messages: Vec<LogAnywhereRecord>) {
println!("Logged for Axiom: {:?}", messages);

let mut headers = header::HeaderMap::new();
headers.insert(AUTHORIZATION, format!("Bearer {}", &self.auth_token).parse().unwrap());
headers.insert(CONTENT_TYPE, "application/json".parse().unwrap());
Expand All @@ -32,9 +30,13 @@ impl LogProvider for AxiomProvider {
.headers(headers)
.json(&messages)
.send()
.await
.unwrap();
.await;

println!("res: {:?}", res.text().await.unwrap());
match res {
Ok(res) => println!("res: {:?}", res.text().await.unwrap()),
Err(e) => {
println!("error status: {:?}, error: {:?}", e.status(), e)
}
}
}
}

0 comments on commit ddf763a

Please sign in to comment.