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(()) };
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}