Stub to create filenames based on time and log level.
This commit is contained in:
parent
1df1f708bb
commit
7b6544bfa1
@ -7,6 +7,8 @@ edition = "2018"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.4.8"
|
log = { version = "0.4.8", features = ["std"] }
|
||||||
chrono = "0.4.10"
|
chrono = "0.4.10"
|
||||||
gettid = "0.1.0"
|
gettid = "0.1.0"
|
||||||
|
hostname = "0.3.0"
|
||||||
|
username = "0.2.0"
|
||||||
|
|||||||
14
README.md
14
README.md
@ -4,17 +4,27 @@ http://github.com/golang/glog and https://github.com/google/glog
|
|||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
- [ ] `-alsologtostderr`
|
- [ ] `-alsologtostderr`
|
||||||
- [ ] `-colorlogtostderr`
|
- [ ] `-colorlogtostderr` this implies color support.
|
||||||
- [ ] `-log_backtrace_at`
|
- [ ] `-log_backtrace_at`
|
||||||
- [ ] `-log_dir`
|
- [ ] `-log_dir`
|
||||||
- [ ] `-logbuflevel`
|
- [ ] `-logbuflevel`
|
||||||
- [ ] `-logbufsecs`
|
- [ ] `-logbufsecs`
|
||||||
- [ ] `-logfile_mode`
|
- [ ] `-logfile_mode`
|
||||||
- [ ] `-logtostderr`
|
- [ ] `-logtostderr`
|
||||||
- [ ] `-max_log_size`
|
- [ ] `-max_log_size` this implies log rotation.
|
||||||
- [ ] `-minloglevel`
|
- [ ] `-minloglevel`
|
||||||
- [ ] `-stderrthreshold`
|
- [ ] `-stderrthreshold`
|
||||||
- [ ] `-stop_logging_if_full_disk`
|
- [ ] `-stop_logging_if_full_disk`
|
||||||
- [ ] `-timestamp_in_logfile_name`
|
- [ ] `-timestamp_in_logfile_name`
|
||||||
- [ ] `-v`
|
- [ ] `-v`
|
||||||
- [ ] `-vmodule`
|
- [ ] `-vmodule`
|
||||||
|
- [ ] flush / sync behavior matching Go or C++ implementations.
|
||||||
|
- [ ] various wrappers for conditional logging (i.e. log_if, sample based).
|
||||||
|
TODO(wathiede): breakout into subcheckboxes.
|
||||||
|
|
||||||
|
# Not implemented
|
||||||
|
These are things that seem unnecessary or low priority for the rust version.
|
||||||
|
|
||||||
|
- [ ] raw log mode that doesn't allocate or use locking primitives
|
||||||
|
- [ ] numeric logging levels, rust offers debug and trace beyond info, and
|
||||||
|
also target based logging.
|
||||||
|
|||||||
@ -3,8 +3,8 @@ use std::thread;
|
|||||||
|
|
||||||
use glog;
|
use glog;
|
||||||
|
|
||||||
fn main() {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
glog::init();
|
glog::init()?;
|
||||||
|
|
||||||
trace!("trace!");
|
trace!("trace!");
|
||||||
debug!("debug!");
|
debug!("debug!");
|
||||||
@ -14,4 +14,5 @@ fn main() {
|
|||||||
|
|
||||||
let handle = thread::spawn(|| error!("from a second thread"));
|
let handle = thread::spawn(|| error!("from a second thread"));
|
||||||
handle.join();
|
handle.join();
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
97
src/lib.rs
97
src/lib.rs
@ -20,17 +20,59 @@
|
|||||||
//!
|
//!
|
||||||
//! I1103 11:57:31.739339 24395 google.rs:2341] Command line: ./some_prog
|
//! 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
|
//! I1103 11:57:31.739403 24395 google.rs:2342] Process id 24395
|
||||||
|
//!
|
||||||
|
//! Unless otherwise specified, glog writes to the filename "/tmp/<program
|
||||||
|
//! name>.<hostname>.<username>.log.<severity level>.<date>.<time>.<pid>" (e.g.,
|
||||||
|
//! "/tmp/hello_world.example.com.hamaji.log.INFO.20080709-222411.10474"). By default, glog copies
|
||||||
|
//! the log messages of severity level ERROR or FATAL to standard error (stderr) in addition to log
|
||||||
|
//! files.
|
||||||
|
//!
|
||||||
|
//! debug! and trace! are output with a log level of 'D' and 'T' respectively. This deviates from
|
||||||
|
//! Google logging behavior which does not have those logging levels.
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
use std::ffi::OsString;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
use gettid::gettid;
|
use gettid::gettid;
|
||||||
|
use hostname;
|
||||||
use log::Record;
|
use log::Record;
|
||||||
|
use username;
|
||||||
|
|
||||||
struct GlogLogger;
|
struct GlogLogger {
|
||||||
|
pid: u32,
|
||||||
|
program: String,
|
||||||
|
host: String,
|
||||||
|
username: String,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init() -> Result<(), log::SetLoggerError> {
|
pub fn init() -> Result<(), log::SetLoggerError> {
|
||||||
log::set_logger(&GlogLogger {}).map(|_| log::set_max_level(log::LevelFilter::Info))
|
let program = std::env::current_exe()
|
||||||
|
.unwrap_or(PathBuf::from("unknownprogram"))
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string();
|
||||||
|
let program = if let Some(idx) = program.rfind("/") {
|
||||||
|
program[idx + 1..].to_string()
|
||||||
|
} else {
|
||||||
|
program
|
||||||
|
};
|
||||||
|
let host = hostname::get()
|
||||||
|
.unwrap_or(OsString::from("unknownhost"))
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string();
|
||||||
|
let host = if let Some(idx) = host.find(".") {
|
||||||
|
host[..idx].to_string()
|
||||||
|
} else {
|
||||||
|
host
|
||||||
|
};
|
||||||
|
log::set_boxed_logger(Box::new(GlogLogger {
|
||||||
|
pid: std::process::id(),
|
||||||
|
program,
|
||||||
|
host,
|
||||||
|
username: username::get_user_name().unwrap_or("unknownuser".to_string()),
|
||||||
|
}))
|
||||||
|
.map(|_| log::set_max_level(log::LevelFilter::Trace))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn common_log(record: &Record) -> String {
|
fn common_log(record: &Record) -> String {
|
||||||
@ -45,6 +87,44 @@ fn just_filename(path: &str) -> String {
|
|||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prefix_char(lvl: log::Level) -> &'static str {
|
||||||
|
match lvl {
|
||||||
|
log::Level::Trace => "T",
|
||||||
|
log::Level::Debug => "D",
|
||||||
|
log::Level::Info => "I",
|
||||||
|
log::Level::Warn => "W",
|
||||||
|
log::Level::Error => "E",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tag_name(lvl: log::Level) -> &'static str {
|
||||||
|
match lvl {
|
||||||
|
log::Level::Trace => "TRACE",
|
||||||
|
log::Level::Debug => "DEBUG",
|
||||||
|
log::Level::Info => "INFO",
|
||||||
|
log::Level::Warn => "WARNING",
|
||||||
|
log::Level::Error => "ERROR",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlogLogger {
|
||||||
|
// Create a file named "<program name>.<hostname>.<username>.log.<severity level>.<date>-<time>.<pid>"
|
||||||
|
// i.e. "hello_world.myhost.myname.log.INFO.20080709-222411.10474"). By default, glog copies
|
||||||
|
fn log_filenames(&self, lvl: log::Level, t: DateTime<Local>) -> (String, String) {
|
||||||
|
let tag = tag_name(lvl);
|
||||||
|
let name = format!(
|
||||||
|
"{}.{}.{}.log.{}.{}.{}",
|
||||||
|
self.program,
|
||||||
|
self.host,
|
||||||
|
self.username,
|
||||||
|
tag,
|
||||||
|
t.format("%Y%m%d-%H%M%S"),
|
||||||
|
self.pid,
|
||||||
|
);
|
||||||
|
let link = format!("{}.{}", self.program, tag);
|
||||||
|
(name, link)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl log::Log for GlogLogger {
|
impl log::Log for GlogLogger {
|
||||||
fn enabled(&self, _metadata: &log::Metadata) -> bool {
|
fn enabled(&self, _metadata: &log::Metadata) -> bool {
|
||||||
//metadata.level() <= log::Level::Info
|
//metadata.level() <= log::Level::Info
|
||||||
@ -57,20 +137,15 @@ impl log::Log for GlogLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let now = Local::now();
|
let now = Local::now();
|
||||||
|
let lvl = record.level();
|
||||||
let location = match (record.file(), record.line()) {
|
let location = match (record.file(), record.line()) {
|
||||||
(Some(file), Some(line)) => format!("{}:{}", just_filename(file), line),
|
(Some(file), Some(line)) => format!("{}:{}", just_filename(file), line),
|
||||||
(Some(file), None) => just_filename(file),
|
(Some(file), None) => just_filename(file),
|
||||||
_ => "".into(),
|
_ => "".into(),
|
||||||
};
|
};
|
||||||
let prefix = match record.level() {
|
let (filename, link) = self.log_filenames(lvl, now);
|
||||||
// TOOD(wathiede): is there a better way to handle debug and trace logs? Should they
|
println!("filename {} {}", filename, link);
|
||||||
// be the equivalent of -v=2 and -v=3?
|
let prefix = prefix_char(lvl);
|
||||||
log::Level::Trace => "I",
|
|
||||||
log::Level::Debug => "I",
|
|
||||||
log::Level::Info => "I",
|
|
||||||
log::Level::Warn => "W",
|
|
||||||
log::Level::Error => "E",
|
|
||||||
};
|
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"{}{} {} {}] {}",
|
"{}{} {} {}] {}",
|
||||||
prefix,
|
prefix,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user