24#ifndef LOGGING_ENABLED
25#define LOGGING_ENABLED 0
32#define LOG_LEVEL_DEBUG 0
33#define LOG_LEVEL_INFO 1
34#define LOG_LEVEL_WARNING 2
35#define LOG_LEVEL_ERROR 3
53static_assert(
static_cast<uint8_t
>(LogLevel::Debug) == LOG_LEVEL_DEBUG,
"LOG_LEVEL_DEBUG out of sync with LogLevel");
54static_assert(
static_cast<uint8_t
>(LogLevel::Info) == LOG_LEVEL_INFO,
"LOG_LEVEL_INFO out of sync with LogLevel");
55static_assert(
static_cast<uint8_t
>(LogLevel::Warning) == LOG_LEVEL_WARNING,
"LOG_LEVEL_WARNING out of sync with LogLevel");
56static_assert(
static_cast<uint8_t
>(LogLevel::Error) == LOG_LEVEL_ERROR,
"LOG_LEVEL_ERROR out of sync with LogLevel");
79 LOGGER_OSREPORT = 1u << 0,
81 LOGGER_SERIAL = 1u << 2,
82 LOGGER_FILE = 1u << 3,
174 virtual const char *
name()
const = 0;
196 Logger(
const Logger &) =
delete;
197 Logger & operator=(
const Logger &) =
delete;
238 void log(
LogLevel level,
const char * fmt, va_list args);
253 uint32_t resolveActiveMask()
const;
259 uint32_t sequence = 0;
260 bool initialized =
false;
280void LogPrintf(
LogLevel level,
const char * fmt, ...);
286void Log_Printf(
int level,
const char * fmt, ...);
294 #define LOG_DEBUG(fmt, ...) LogPrintf(LogLevel::Debug, fmt, ##__VA_ARGS__)
295 #define LOG_INFO(fmt, ...) LogPrintf(LogLevel::Info, fmt, ##__VA_ARGS__)
296 #define LOG_WARN(fmt, ...) LogPrintf(LogLevel::Warning, fmt, ##__VA_ARGS__)
297 #define LOG_ERROR(fmt, ...) LogPrintf(LogLevel::Error, fmt, ##__VA_ARGS__)
299 #define LOG_DEBUG(fmt, ...) Log_Printf(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
300 #define LOG_INFO(fmt, ...) Log_Printf(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
301 #define LOG_WARN(fmt, ...) Log_Printf(LOG_LEVEL_WARNING, fmt, ##__VA_ARGS__)
302 #define LOG_ERROR(fmt, ...) Log_Printf(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)
311#define LOG_DEBUG(fmt, ...) ((void)0)
312#define LOG_INFO(fmt, ...) ((void)0)
313#define LOG_WARN(fmt, ...) ((void)0)
314#define LOG_ERROR(fmt, ...) ((void)0)
318#define LOG(fmt, ...) LOG_INFO(fmt, ##__VA_ARGS__)
void log(LogLevel level, const char *fmt, va_list args)
Formats fmt/args into a fixed stack buffer and fans it out to every backend selected by the current c...
void activateDeferred(LogBackendId id)
Called by a backend that deferred its own activation on some background precondition (eg.
void shutdown()
Shuts down every registered backend and forgets the config.
void setLevel(LogLevel level)
Runtime-adjusts the minimum severity without touching any other config field or re-touching backend i...
bool registerBackend(LogBackendId id, LoggingDriver *backend)
Registers a backend under the given single-bit LogBackendId, for later selection via LogConfig::mode ...
void init(const LogConfig &config)
Applies config, calling init()/shutdown() on registered backends as needed so only the ones actually ...
static const int MAX_BACKENDS
Maximum number of backends that can be registered at once.
LogLevel getLevel() const
Abstract backend a Logger fans a formatted line out to.
virtual bool init(const LogConfig &config)=0
Opens whatever handle/socket/file this backend needs, using only fields from config (nothing hardcode...
virtual void write(LogLevel level, const char *line, size_t len)=0
Writes one already-formatted, newline-terminated line.
virtual void shutdown()=0
Releases whatever init() acquired.
virtual const char * name() const =0
Short identifier for diagnostics (eg. "UDP", "File").
A simple mutual-exclusion lock.
LogLevel
Severity of a single log call.
LogFlushPolicy
How LoggerFile flushes writes to storage.
LogMode
Which single backend is active when LogConfig::mode isn't Multi.
LogBackendId
Bitmask identifying an individual backend.
@ Immediate
fflush() after every write - safest against a crash/power loss, slowest
@ Never
rely on the C library / fclose() at shutdown - fastest, least crash-safe
@ EveryNWrites
fflush() every LogConfig::flushEveryNWrites writes
@ OSReport
OSReport (Wii U) / SYS_Report (GC+Wii) - always safe, no hardware required.
@ Multi
fan out to every backend set in LogConfig::multiBackendMask
Full runtime configuration for the Logger.
bool mirrorToOSReport
Regardless of mode/multiBackendMask, also mirror every line to the console OS default backend (OSRepo...
uint32_t multiBackendMask
Only consulted when mode == LogMode::Multi.
LogFlushPolicy flushPolicy
How often the file backend flushes to storage.
uint16_t targetPort
Destination UDP port for the UDP backend.
int geckoChannel
EXI channel (GC/Wii): 0 = memory card slot A, 1 = memory card slot B (where a USB Gecko is normally i...
bool includeTimestamp
prefix each line with the time since process start as "[secs.millis]"
LogLevel level
Minimum severity that is logged.
char filePath[1024]
Path of the log file for the file backend. Each platform's init() points this at debug....
const char * targetIp
Destination IPv4 address for the UDP backend.
uint32_t flushEveryNWrites
Flush interval in writes; only used when flushPolicy is LogFlushPolicy::EveryNWrites.
LogMode mode
Which backend(s) receive log lines; see LogMode.
bool nonBlocking
socket is always created non-blocking; kept for clarity/future use
bool includeLevelTag
prefix each line with "[DEBUG] "/"[INFO] "/etc.
bool includeSequenceNumber
prefix each line with a monotonic call counter, useful for spotting dropped UDP packets
uint32_t serialBaudRate
Informational only on GC/Wii (EXI has a fixed protocol rate); used as the requested baud rate for a W...