1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//! Easy logging and tracing

use std::fmt::Display;

pub struct Trace {
    title : String,
    info: String,
    backtrace : String,
}

impl Trace {

    /// Provides title to the trace logs
    pub fn new<T : Display>(title: T) -> Trace {
        Trace {
            title: title.to_string(),
            info: String::new(),
            backtrace : String::new(),
        }
    }

    /// Filters backtrace based on "|" separated string provided
    pub fn trace_filter<T: Display>(&mut self, traces_of: T) -> &mut Trace {

        let mut count = 0;

        backtrace::trace(|frame| {

            backtrace::resolve(frame.ip(), |symbol| {

                let name = if let Some(name) = symbol.name() {
                    name.to_string()
                } else {
                    " - <unknown caller name>".to_string()
                };

                let filename = if let Some(filename) = symbol.filename() {
                    filename.display().to_string()
                } else {
                    " - <unknown file name>".to_string()
                };

                let line = if let Some(line) = symbol.lineno() {
                    line
                } else {
                    0
                };

                let output = format!("{:<2} -- {} \n {:10} {}:{} ", count, name, "", filename, line);

                let matches = traces_of.to_string();
                let matches = matches.split("|");

                for text_match in matches {
                    if output.contains(text_match) {
                        self.backtrace = format!("{}\n{}", self.backtrace, output);
                        break;
                    }
                }
            });

            count += 1;

            true // keep going
        });

        self
    }

    /// Any information to be shown inside the log block
    pub fn info<T: Display>(&mut self, info: T) -> &mut Trace {
        self.info = info.to_string();
        self
    }

    /// Emits the trace log
    pub fn emit(&self){

        let output = format!("----------------------------------------------------------------------- BEGIN ------ {} \n", self.title);

        let output = if self.info.len() > 0 {
            format!("{}{} \n",output, self.info)
        } else { output };
        let output = if self.backtrace.len() > 0 {
            format!("{}{} \n\n",output, self.backtrace)
        } else { output };

        let output = format!("{}----------------------------------------------------------------------- END -------- {} \n\n", output, self.title);

        println!("{}", output);
    }

    /// Quick log handle
    pub fn log<T: Display, U: Display, V: Display> (title: T, info: U, trace_filter: V){
        Self::new(title).info(info).trace_filter(trace_filter).emit();
    }

}