How to do it...

  1. Open the Cargo.toml file that was generated earlier for you.

  2. Under [dependencies], if you didn't do so in the last recipe, add the following line:

log = "0.4.1"

If you want, you can go to log's crates.io page (https://crates.io/crates/log) to check for the newest version and use that one instead.

  1. In the folder bin, create a file called custom_logger.rs.
  2. Add the following code and run it with RUST_LOG=custom_logger cargo run --bin custom_logger if you're on a Unix-based system. Otherwise, run $env:RUST_LOG="custom_logger"; cargo run --bin custom_logger on Windows:
1   #[macro_use]
2 extern crate log;
3
4 use log::{Level, Metadata, Record};
5 use std::fs::{File, OpenOptions};
6 use std::io::{self, BufWriter, Write};
7 use std::{error, fmt, result};
8 use std::sync::RwLock;
9 use std::time::{SystemTime, UNIX_EPOCH};
10
11 // This logger will write logs into a file on disk
12 struct FileLogger {
13 level: Level,
14 writer: RwLock<BufWriter<File>>,
15 }
16
17 impl log::Log for FileLogger {
18 fn enabled(&self, metadata: &Metadata) -> bool {
19 // Check if the logger is enabled for a certain log level
20 // Here, you could also add own custom filtering based on
targets or regex
21 metadata.level() <= self.level
22 }
23
24 fn log(&self, record: &Record) {
25 if self.enabled(record.metadata()) {
26 let mut writer = self.writer
27 .write()
28 .expect("Failed to unlock log file writer in write
mode");
29 let now = SystemTime::now();
30 let timestamp = now.duration_since(UNIX_EPOCH).expect(
31 "Failed to generate timestamp: This system is
operating before the unix epoch",
32 );
33 // Write the log into the buffer
34 write!(
35 writer,
36 "{} {} at {}: {} ",
37 record.level(),
38 timestamp.as_secs(),
39 record.target(),
40 record.args()
41 ).expect("Failed to log to file");
42 }
43 self.flush();
44 }
45
46 fn flush(&self) {
47 // Write the buffered logs to disk
48 self.writer
49 .write()
50 .expect("Failed to unlock log file writer in write
mode")
51 .flush()
52 .expect("Failed to flush log file writer");
53 }
54 }
55
56 impl FileLogger {
57 // A convenience method to set everything up nicely
58 fn init(level: Level, file_name: &str) -> Result<()> {
59 let file = OpenOptions::new()
60 .create(true)
61 .append(true)
62 .open(file_name)?;
63 let writer = RwLock::new(BufWriter::new(file));
64 let logger = FileLogger { level, writer };
65 // set the global level filter that log uses to optimize
ignored logs
66 log::set_max_level(level.to_level_filter());
67 // set this logger as the one used by the log macros
68 log::set_boxed_logger(Box::new(logger))?;
69 Ok(())
70 }
71 }

This is the custom error used in our logger:

73  // Our custom error for our FileLogger
74 #[derive(Debug)]
75 enum FileLoggerError {
76 Io(io::Error),
77 SetLogger(log::SetLoggerError),
78 }
79
80 type Result<T> = result::Result<T, FileLoggerError>;
81 impl error::Error for FileLoggerError {
82 fn description(&self) -> &str {
83 match *self {
84 FileLoggerError::Io(ref err) => err.description(),
85 FileLoggerError::SetLogger(ref err) =>
err.description(),
86 }
87 }
88
89 fn cause(&self) -> Option<&error::Error> {
90 match *self {
91 FileLoggerError::Io(ref err) => Some(err),
92 FileLoggerError::SetLogger(ref err) => Some(err),
93 }
94 }
95 }
96
97 impl fmt::Display for FileLoggerError {
98 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
99 match *self {
100 FileLoggerError::Io(ref err) => write!(f, "IO error: {}",
err),
101 FileLoggerError::SetLogger(ref err) => write!(f, "Parse
error: {}", err),
102 }
103 }
104 }
105
106 impl From<io::Error> for FileLoggerError {
107 fn from(err: io::Error) -> FileLoggerError {
108 FileLoggerError::Io(err)
109 }
110 }
111
112 impl From<log::SetLoggerError> for FileLoggerError {
113 fn from(err: log::SetLoggerError) -> FileLoggerError {
114 FileLoggerError::SetLogger(err)
115 }
116 }

Initializing and using the logger:

118 fn main() {
119 FileLogger::init(Level::Info, "log.txt").expect("Failed to
init
FileLogger");
120 trace!("Beginning the operation");
121 info!("A lightning strikes a body");
122 warn!("It's moving");
123 error!("It's alive!");
124 debug!("Dr. Frankenstein now knows how it feels to be god");
125 trace!("End of the operation");
126 }
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.76.175