log4rs_sentry/
lib.rs

1extern crate log;
2extern crate log4rs;
3extern crate sentry;
4
5use log::{Level, Record};
6use log4rs::{
7	append::Append,
8	encode::{
9		Encode,
10		writer::simple::SimpleWriter
11	}
12};
13use sentry::{
14	protocol::value::{Number, Value},
15	Level as SentryLevel
16};
17
18#[derive(Debug)]
19pub struct SentryAppender
20{
21	encoder : Box<Encode>
22}
23
24impl SentryAppender
25{
26	pub fn new(encoder : Box<Encode>) -> Self
27	{
28		SentryAppender { encoder }
29	}
30}
31
32impl Append for SentryAppender
33{
34	fn append(&self, record: &Record) -> Result<(), Box<std::error::Error + Sync + Send>>
35	{
36		let level = match record.level() {
37			Level::Error => SentryLevel::Error,
38			Level::Warn => SentryLevel::Warning,
39			_ => return Ok(()) // don't send messages < warn to sentry
40		};
41		
42		let mut buf : Vec<u8> = Vec::new();
43		self.encoder.encode(&mut SimpleWriter(&mut buf), record)?;
44		let msg = match String::from_utf8(buf) {
45			Ok(msg) => msg,
46			Err(e) => return Err(Box::new(e))
47		};
48		
49		let mut event = sentry::protocol::Event::new();
50		event.level = level;
51		event.message = Some(msg);
52		event.logger = Some(record.metadata().target().to_owned());
53		
54		if let Some(file) = record.file()
55		{
56			event.extra.insert("file".to_owned(), Value::String(file.to_owned()));
57		}
58		
59		if let Some(line) = record.line()
60		{
61			event.extra.insert("line".to_owned(), Value::Number(Number::from(line)));
62		}
63		
64		if let Some(module_path) = record.module_path()
65		{
66			event.tags.insert("module_path".to_owned(), module_path.to_owned());
67		}
68		
69		sentry::capture_event(event);
70		Ok(())
71	}
72
73	fn flush(&self) {}
74}