Logger
A practical guide to vix::utils::Logger.
This logger is a thin wrapper over spdlog with:
- A global singleton instance
- Level control via
VIX_LOG_LEVEL - Optional structured logging via
VIX_LOG_FORMAT - Per-thread context (request id, module, custom fields)
- Optional console synchronization to avoid interleaved output
Include
#include <vix/utils/Logger.hpp>Get the singleton:
auto &log = vix::utils::Logger::getInstance();Default behavior
- Output: console only (no log file is created)
- Default level:
info(can be overridden byVIX_LOG_LEVEL) - Default pattern: timestamp +
[vix]+ level + message
Logging levels
Available levels:
tracedebuginfowarnerrorcriticaloff
Set via environment:
export VIX_LOG_LEVEL=debugOr set programmatically:
auto &log = vix::utils::Logger::getInstance();
log.setLevel(vix::utils::Logger::Level::Debug);Check if a level is enabled:
if (log.enabled(vix::utils::Logger::Level::Debug))
{
log.debug("Will only run when debug is enabled");
}Basic logging
auto &log = vix::utils::Logger::getInstance();
log.info("Server started on port {}", 8080);
log.warn("Cache miss for key={}", key);
log.error("DB error: {}", err);Module prefix
If you want a visible module prefix like [auth] ...:
auto &log = vix::utils::Logger::getInstance();
log.logModule("auth", vix::utils::Logger::Level::Info,
"User {} logged in", user);Pattern
Override the console pattern:
auto &log = vix::utils::Logger::getInstance();
log.setPattern("%T [%^%l%$] %v");Common patterns:
%T=HH:MM:SS%l= level name%^and%$= enable and disable level color%v= message
Async mode
Enable async logging:
auto &log = vix::utils::Logger::getInstance();
log.setAsync(true);Disable async logging:
log.setAsync(false);Notes:
- Async mode uses an internal spdlog thread pool.
- If you use async, keep shutdown simple. Let the process exit normally.
Per-thread context
Logger context is thread-local. It is designed for request scoped data.
Set context
auto &log = vix::utils::Logger::getInstance();
vix::utils::Logger::Context ctx;
ctx.request_id = "r-123";
ctx.module = "http";
ctx.fields["ip"] = "127.0.0.1";
ctx.fields["user_id"] = "42";
log.setContext(ctx);
log.info("Request started");Clear context
auto &log = vix::utils::Logger::getInstance();
log.clearContext();Read context
auto &log = vix::utils::Logger::getInstance();
auto ctx = log.getContext();Tips:
- Set context at the beginning of a request handler.
- Clear it when leaving the handler if the thread is reused.
Structured logging
You can log key/value pairs with logf().
KV format (default)
auto &log = vix::utils::Logger::getInstance();
log.logf(vix::utils::Logger::Level::Info,
"Login ok",
"user", "alice",
"latency_ms", 12,
"status", 200);Output stays on one line and appends fields like:
- your kvpairs
ridandmodfrom the context- all custom context fields
JSON formats
Select output format via environment:
export VIX_LOG_FORMAT=json
# or
export VIX_LOG_FORMAT=json_prettyOr set programmatically:
auto &log = vix::utils::Logger::getInstance();
log.setFormat(vix::utils::Logger::Format::JSON);Notes:
- JSON modes force the sink pattern to
%vso the output is raw JSON. - Pretty JSON may include ANSI colors unless disabled (see below).
Colors and terminals
Pretty JSON colors are controlled by:
NO_COLORset => colors disabledVIX_COLOR=never|0|false=> colors disabledVIX_COLOR=always|1|true=> colors forced on- Otherwise: best-effort detection (TTY on Unix, enabled on Windows)
Example:
export NO_COLOR=1Console synchronization
If you print banners or write to stdout from multiple threads, you can ask the logger to synchronize console writes.
Enable:
export VIX_CONSOLE_SYNC=1Disable:
unset VIX_CONSOLE_SYNC
# or
export VIX_CONSOLE_SYNC=0What it does:
- Waits for banners to finish (via
ConsoleMutex) - Locks a shared console mutex before emitting a log line
Windows macro safety
On Windows, some headers define macros like ERROR, DEBUG, INFO, min, max. This can break enum values or identifiers. The header temporarily undefines them and restores them after includes.
You do not need to do anything. It is handled by Logger.hpp.
Throw helpers
You can log and throw in one call:
auto &log = vix::utils::Logger::getInstance();
log.throwError("Invalid config: {}", reason);This logs at error level and throws std::runtime_error.
Recommended baseline
For typical apps:
export VIX_LOG_LEVEL=info
export VIX_LOG_FORMAT=kvFor debugging locally:
export VIX_LOG_LEVEL=debug
export VIX_LOG_FORMAT=json_pretty