|
bux API Reference 1.12.6
Static library of whatever are seen required in general purpose but not directly supported from Modern C++. Or whatever reusable originated from my side projects.
|
Header bux/Logger.h wraps the process-wide logger behind a handful of macros. Whatever the sink is, usage always boils down to the same two steps:
| Macro (square brackets mark optional arguments) | Sink | Include before it |
|---|---|---|
| DEF_LOGGER_COUT([max_ll]) | std::cout | <iostream> |
| DEF_LOGGER_CERR([max_ll]) | std::cerr | <iostream> |
| DEF_LOGGER_OSTREAM(out[, max_ll]) | any std::ostream lvalue outliving the logger | — |
| DEF_LOGGER_FILE(path[, max_ll]) | one std::ofstream opened at path | <fstream> |
| DEF_LOGGER_FILES(pathfmt[, max_ll]) | file whose name is re-formatted from the current timestamp | <bux/FileLog.h> |
| DEF_FALLBACK_LOGGER_FILES(fsize, paths) | same, plus fallback to a finer path format once fsize bytes are exceeded | <bux/FileLog.h> |
| DEF_PARA_LOGGER | bux::C_ParaLog facade fanning out to child loggers | <bux/ParaLog.h> |
max_ll is the most verbose level the sink accepts, defaulting to LL_VERBOSE (i.e. accept everything). See Log levels.
pathfmt is a std::format string taking the current timestamp as its single argument, so a new file is opened whenever the formatted name changes:
Missing directories are created on demand by bux::C_PathFmtLogSnap — unlike DEF_LOGGER_FILE(), whose plain std::ofstream requires the folder to already exist.
DEF_FALLBACK_LOGGER_FILES() additionally caps each file by size: once the current file exceeds fsize bytes, the next path format in paths takes over. Keep paths in a namespace-scope constinit object, because it is consumed by a global initializer:
DEF_PARA_LOGGER defines bux::user::g_paraLog, a bux::C_ParaLog to be populated at run time — each child keeps its own max_ll, and bux::C_ParaLog::partitionBy() routes lines to children by content:
| Macro | Emits |
|---|---|
| LOG(ll, fmtStr[, args...]) | one stamped line, dropped unless ll passes the level filter |
| LOG1(ll, str) | LOG(ll, "{}", str), for text which is not a literal |
| LOG_RAW(fmtStr[, args...]) | the formatted text alone — no stamp, no level filtering |
| FUNLOG | { on the spot and } at end of the enclosing block, tagged with the current function name |
| FUNLOGX(fmtStr[, args...]) | same, with the formatted text as the "arguments" of the scope |
| FUNLOGX1(x1) … FUNLOGX9(x1, ..., x9) | same, with the values rendered as a comma-separated list |
| SCOPELOG(scope) | as FUNLOG, but named scope instead of the current function |
| SCOPELOGX(scope, fmtStr[, args...]) | as FUNLOGX(), but named scope |
| SCOPELOGX1(scope, x1) … SCOPELOGX9(scope, x1, ..., x9) | as FUNLOGX1()…FUNLOGX9(), but named scope |
The FUNLOG/SCOPELOG family declares an unnamed bux::C_EntryLog on the stack, so the closing line is written by its destructor — through every return, break, and throw — and nested scopes indent the lines in between.
Declared in bux/LogLevel.h and exported to the global namespace, so no bux:: prefix is needed:
| Level | Letter | Meaning |
|---|---|---|
| LL_FATAL | F | The program should shut down right after reporting this. |
| LL_ERROR | E | Error the program can keep running after. |
| LL_WARNING | W | Worth warning about, nothing sabotaged yet. |
| LL_INFO | I | Status worth mentioning, normal or not. |
| LL_DEBUG | D | Debug-only, easily suppressed for releases. |
| LL_VERBOSE | V | More detail than some would care for. |
A line survives when its level is not more verbose than the sink's max_ll, i.e. DEF_LOGGER_COUT(LL_WARNING) keeps LL_FATAL, LL_ERROR, LL_WARNING and drops the rest. Filtering costs no formatting: the arguments of LOG() are never evaluated once the level is rejected.
Output of test/smoke_coutlog.cpp, abridged:
Both are consulted by bux/Logger.h at include time, so #define them before including it — ideally on the compiler command line, so all translation units agree.
LOG() is a thin shorthand for locking the singleton and stamping a line, which is worth doing by hand for output the macros do not shape — multi-line dumps, manipulators, or anything streamed piecewise:
A logger the DEF_LOGGER_XXX table does not cover is defined by writing bux::user::logger() directly. DEF_LOGGER_TAIL_() closes the namespaces for you, which is how test/test_logger.cpp swaps in a fresh sink per test case: