Skip to main content

indy_crypto/utils/
logger.rs

1extern crate env_logger;
2extern crate log;
3extern crate libc;
4
5use self::env_logger::Builder;
6use self::log::LevelFilter;
7use std::env;
8use std::io::Write;
9use log::{Record, Metadata};
10
11use errors::prelude::*;
12
13use self::libc::{c_void, c_char};
14use std::ffi::CString;
15use std::ptr;
16
17pub type EnabledCB = extern fn(context: *const c_void,
18                               level: u32,
19                               target: *const c_char) -> bool;
20
21pub type LogCB = extern fn(context: *const c_void,
22                           level: u32,
23                           target: *const c_char,
24                           message: *const c_char,
25                           module_path: *const c_char,
26                           file: *const c_char,
27                           line: u32);
28
29pub type FlushCB = extern fn(context: *const c_void);
30
31pub struct IndyCryptoLogger {
32    context: *const c_void,
33    enabled: Option<EnabledCB>,
34    log: LogCB,
35    flush: Option<FlushCB>,
36}
37
38impl IndyCryptoLogger {
39    fn new(context: *const c_void, enabled: Option<EnabledCB>, log: LogCB, flush: Option<FlushCB>) -> Self {
40        IndyCryptoLogger { context, enabled, log, flush }
41    }
42}
43
44impl log::Log for IndyCryptoLogger {
45    fn enabled(&self, metadata: &Metadata) -> bool {
46        if let Some(enabled_cb) = self.enabled {
47            let level = metadata.level() as u32;
48            let target = CString::new(metadata.target()).unwrap();
49
50            enabled_cb(self.context,
51                       level,
52                       target.as_ptr(),
53            )
54        } else { true }
55    }
56
57    fn log(&self, record: &Record) {
58        let log_cb = self.log;
59
60        let level = record.level() as u32;
61        let target = CString::new(record.target()).unwrap();
62        let message = CString::new(record.args().to_string()).unwrap();
63
64        let module_path = record.module_path().map(|a| CString::new(a).unwrap());
65        let file = record.file().map(|a| CString::new(a).unwrap());
66        let line = record.line().unwrap_or(0);
67
68        log_cb(self.context,
69               level,
70               target.as_ptr(),
71               message.as_ptr(),
72               module_path.as_ref().map(|p| p.as_ptr()).unwrap_or(ptr::null()),
73               file.as_ref().map(|p| p.as_ptr()).unwrap_or(ptr::null()),
74               line,
75        )
76    }
77
78    fn flush(&self) {
79        if let Some(flush) = self.flush {
80            flush(self.context)
81        }
82    }
83}
84
85unsafe impl Sync for IndyCryptoLogger {}
86
87unsafe impl Send for IndyCryptoLogger {}
88
89impl IndyCryptoLogger {
90    pub fn init(context: *const c_void, enabled: Option<EnabledCB>, log: LogCB, flush: Option<FlushCB>) -> IndyCryptoResult<()> {
91        let logger = IndyCryptoLogger::new(context, enabled, log, flush);
92
93        log::set_boxed_logger(Box::new(logger))?;
94        log::set_max_level(LevelFilter::Trace);
95
96        Ok(())
97    }
98}
99
100pub struct IndyCryptoDefaultLogger;
101
102impl IndyCryptoDefaultLogger {
103    pub fn init(pattern: Option<String>) -> IndyCryptoResult<()> {
104        let pattern = pattern.or(env::var("RUST_LOG").ok());
105
106        Builder::new()
107            .format(|buf, record| writeln!(buf, "{:>5}|{:<30}|{:>35}:{:<4}| {}", record.level(), record.target(), record.file().get_or_insert(""), record.line().get_or_insert(0), record.args()))
108            .filter(None, LevelFilter::Off)
109            .parse(pattern.as_ref().map(String::as_str).unwrap_or(""))
110            .try_init()?;
111
112        Ok(())
113    }
114}
115
116#[cfg(debug_assertions)]
117#[macro_export]
118macro_rules! secret {
119    ($val:expr) => {{ $val }};
120}
121
122#[cfg(not(debug_assertions))]
123#[macro_export]
124macro_rules! secret {
125    ($val:expr) => {{ "_" }};
126}