diff --git a/pkgs/by-name/bunpen/log/annotated/annotatedlogger.ha b/pkgs/by-name/bunpen/log/annotated/annotatedlogger.ha new file mode 100644 index 000000000..0fbfd4cbd --- /dev/null +++ b/pkgs/by-name/bunpen/log/annotated/annotatedlogger.ha @@ -0,0 +1,65 @@ +// vim: set shiftwidth=2 : +// +// the "annotated logger" logs each incoming entry, prepended with additional +// information (such as the pid which triggered the log statement). +// +// TODO: pids logged here suffer from aliasing, when using PID namespaces; +// i could de-alias these by (either): +// 1. maintaining global state that is a sequence of pids, and appending to this +// on each fork. e.g. `[pid=19332/2/4]`. +// however siblings each placed in a new PID space will still have aliasing. +// 2. maintaining global state that is a sequence of pids, and appending to this +// on each fork, by piping the fork'd PID from parent into child. +// by using the parent's view, siblings are no longer aliased. + +use fmt; +use log; +use rt; + +export type logger = struct { + // vtable (println, printfln) + base: log::logger, + // where to forward logs + forward: nullable *log::logger, +}; + +let _global: logger = logger { + base = log::logger { + println = &log_println, + printfln = &log_printfln, + }, + forward = null, // can't evaluate &log::default at compile time, so set null +}; + +// annotatedlogger with program lifetime, in case you don't want to manage that yourself +export const global: *logger = &_global; + +export fn set_forward(me: *logger, forward: *log::logger) void = { + me.forward = forward; +}; + +fn log_println(base: *log::logger, fields: fmt::formattable...) void = { + // no way to nest `printf("[pid={}]: {}", getpid(), print(fields...))` + // except by evaluating the inner printf: + let entry = fmt::asprint(fields...); + defer free(entry); + log_println1(base, entry); +}; +fn log_printfln(base: *log::logger, fmt: str, fields: fmt::field...) void = { + // no way to nest `printf("[pid={}]: {}", getpid(), printf(fmt, fields...))` + // except by evaluating the inner printf: + let entry = fmt::asprintf(fmt, fields...); + defer free(entry); + log_println1(base, entry); +}; +fn log_println1(base: *log::logger, entry: str) void = { + let me = base: *logger; + log::lprintfln(get_forward(me), "[pid={}] {}", rt::getpid(): int, entry); +}; + +fn get_forward(me: *logger) *log::logger = { + return match (me.forward) { + case null => yield log::default; + case let l: *log::logger => yield l; + }; +}; diff --git a/pkgs/by-name/bunpen/log/tree/treelogger.ha b/pkgs/by-name/bunpen/log/tree/treelogger.ha index 1740c595b..81691baa0 100644 --- a/pkgs/by-name/bunpen/log/tree/treelogger.ha +++ b/pkgs/by-name/bunpen/log/tree/treelogger.ha @@ -48,6 +48,10 @@ export fn set_level(me: *logger, level: uint) void = { me.level = level; }; +export fn set_forward(me: *logger, forward: *log::logger) void = { + me.forward = forward; +}; + fn log_println(base: *log::logger, fields: fmt::formattable...) void = { let me = base: *logger; if (me.level > 0 && (len(fields) == 0 || get_depth(fields[0]) < me.level)) { diff --git a/pkgs/by-name/bunpen/main.ha b/pkgs/by-name/bunpen/main.ha index a60468373..9b3ebd1db 100644 --- a/pkgs/by-name/bunpen/main.ha +++ b/pkgs/by-name/bunpen/main.ha @@ -3,6 +3,7 @@ use config; use errors; use errors::ext; use log; +use log::annotated; use log::tree; use restrict; use restrict::ns; @@ -47,6 +48,7 @@ fn prepare_env(req: config::cli_request) config::exec_params = { export fn main() void = { // install my logger, but defaulted to no logging. + log::tree::set_forward(tree::global, log::annotated::global); log::tree::install(tree::global); let opts = match (config::parse_args(os::args[1..])) {