From cdda6669d03ee876bc7e5a113625d48a47753e34 Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Tue, 14 Jan 2020 21:48:04 -0800 Subject: [PATCH] Initial basic logging implementation w/ example and Go version. --- .gitignore | 3 ++ Cargo.toml | 12 +++++++ README.md | 20 ++++++++++++ examples/demo.go | 18 ++++++++++ examples/demo.rs | 17 ++++++++++ src/lib.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 155 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 examples/demo.go create mode 100644 examples/demo.rs create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6936990 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..817e0b2 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "glog" +version = "0.1.0" +authors = ["Bill Thiede "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +log = "0.4.8" +chrono = "0.4.10" +gettid = "0.1.0" diff --git a/README.md b/README.md new file mode 100644 index 0000000..dc752f5 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Glog +Rust logging in the pattern established by Google logging. See +http://github.com/golang/glog and https://github.com/google/glog + +# TODO +- [ ] `-alsologtostderr` +- [ ] `-colorlogtostderr` +- [ ] `-log_backtrace_at` +- [ ] `-log_dir` +- [ ] `-logbuflevel` +- [ ] `-logbufsecs` +- [ ] `-logfile_mode` +- [ ] `-logtostderr` +- [ ] `-max_log_size` +- [ ] `-minloglevel` +- [ ] `-stderrthreshold` +- [ ] `-stop_logging_if_full_disk` +- [ ] `-timestamp_in_logfile_name` +- [ ] `-v` +- [ ] `-vmodule` diff --git a/examples/demo.go b/examples/demo.go new file mode 100644 index 0000000..2dff6ff --- /dev/null +++ b/examples/demo.go @@ -0,0 +1,18 @@ +package main + +import ( + "flag" + + "github.com/golang/glog" +) + +func main() { + flag.Parse() + defer glog.Flush() + + glog.V(1).Infoln("v1.info!") + glog.V(0).Infoln("v0.info!") + glog.Infoln("info!") + glog.Warningln("warn!") + glog.Errorln("error!") +} diff --git a/examples/demo.rs b/examples/demo.rs new file mode 100644 index 0000000..8acad68 --- /dev/null +++ b/examples/demo.rs @@ -0,0 +1,17 @@ +use log::{debug, error, info, trace, warn}; +use std::thread; + +use glog; + +fn main() { + glog::init(); + + trace!("trace!"); + debug!("debug!"); + info!("info!"); + warn!("warn!"); + error!("error!"); + + let handle = thread::spawn(|| error!("from a second thread")); + handle.join(); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..ecbcbb8 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,85 @@ +//! This module implements the standard rust logging facade in the style of Google's logging. +//! Log lines have this form: +//! +//! Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... +//! +//! where the fields are defined as follows: +//! +//! L A single character, representing the log level +//! (eg 'I' for INFO) +//! mm The month (zero padded; ie May is '05') +//! dd The day (zero padded) +//! hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds +//! threadid The space-padded thread ID as returned by GetTID() +//! (this matches the PID on Linux) +//! file The file name +//! line The line number +//! msg The user-supplied message +//! +//! Example: +//! +//! I1103 11:57:31.739339 24395 google.rs:2341] Command line: ./some_prog +//! I1103 11:57:31.739403 24395 google.rs:2342] Process id 24395 +use std::ffi::OsStr; +use std::path::Path; + +use chrono::{DateTime, Local}; +use gettid::gettid; +use log::Record; + +struct GlogLogger; + +pub fn init() -> Result<(), log::SetLoggerError> { + log::set_logger(&GlogLogger {}).map(|_| log::set_max_level(log::LevelFilter::Info)) +} + +fn common_log(record: &Record) -> String { + "".to_string() +} + +fn just_filename(path: &str) -> String { + Path::new(path) + .file_name() + .unwrap_or(OsStr::new("UNKNOWN")) + .to_string_lossy() + .to_string() +} + +impl log::Log for GlogLogger { + fn enabled(&self, _metadata: &log::Metadata) -> bool { + //metadata.level() <= log::Level::Info + true + } + + fn log(&self, record: &log::Record) { + if !self.enabled(record.metadata()) { + return; + } + + let now = Local::now(); + let location = match (record.file(), record.line()) { + (Some(file), Some(line)) => format!("{}:{}", just_filename(file), line), + (Some(file), None) => just_filename(file), + _ => "".into(), + }; + let prefix = match record.level() { + // TOOD(wathiede): is there a better way to handle debug and trace logs? Should they + // be the equivalent of -v=2 and -v=3? + log::Level::Trace => "I", + log::Level::Debug => "I", + log::Level::Info => "I", + log::Level::Warn => "W", + log::Level::Error => "E", + }; + let msg = format!( + "{}{} {} {}] {}", + prefix, + now.format("%m%d %H:%M:%S%.6f"), + gettid(), + location, + record.args() + ); + println!("{}", msg); + } + fn flush(&self) {} +}