Log
Log is the logging facade: a program writes Log.info("connected %d", n) on
every target, and where the text goes is the platform’s business: the browser
console on wasm32, the system log on iOS, logcat on Android, the screen on the
6502 and standard output elsewhere (the table under Where it
goes).
#import "Log.xc"Overview
Section titled “Overview”Log.info("listening on %d", port);Log.warning(String.withCString("disk nearly full"));
LogChannel* net = Log.forSubsystem(String.withCString("net"));net.setMinLevel(Log.levelWarning());net.error("timeout after %d s", (i32)30); // "net: timeout after 30 s"
Log.addMonitor(&self.onLog); // void onLog(String* subsystem, u8 level, String* msg)Levels are debug, info, warning and error, in that order. Messages below the
global minimum (info at first) are dropped, so a
Log.debug costs one comparison until it is wanted. From 0.72, as are subsystems and monitors.
Subsystems. Log.forSubsystem gives the
LogChannel for a name, one per name, with its own minimum
level; its messages reach the Logger as name: message.
Monitors are called with the subsystem ("" for the plain facade), the
level and the message of everything that passes the level filters, whatever the
Logger does with it: to count errors, show the last warning in a status bar, or
watch for a pattern with a Regex. A monitor does not
keep its receiver alive; one whose receiver has gone is dropped.
The Logger receives each message once it has passed the filters. The default
prints error: and warning: prefixes (in red and yellow on a terminal); an app
may install its own with setLogger.
Topics
Section titled “Topics”Writing · error / warning / info / debug
Levels · levelDebug … levelError · setMinLevel / minLevel
Subsystems · forSubsystem · LogChannel
Monitors · addMonitor / removeMonitor
Where it goes · Logger · setLogger / logger
Writing
Section titled “Writing”error / warning / info / debug
Section titled “error / warning / info / debug”static void error(String* msg)static void error(string fmt, ...)static void warning(String* msg)static void warning(string fmt, ...)static void info(String* msg)static void info(string fmt, ...)static void debug(String* msg)static void debug(string fmt, ...)The format forms take printf formats. debug’s format
form does not even format the text while debug messages are dropped.
Levels
Section titled “Levels”levelDebug … levelError
Section titled “levelDebug … levelError”static u8 levelDebug(void) // 0static u8 levelInfo(void) // 1static u8 levelWarning(void) // 2static u8 levelError(void) // 3setMinLevel / minLevel
Section titled “setMinLevel / minLevel”static void setMinLevel(u8 level)static u8 minLevel(void)Messages below level are dropped, from every channel. Info at first.
Subsystems
Section titled “Subsystems”forSubsystem
Section titled “forSubsystem”static LogChannel* forSubsystem(String* name)The channel named name, made on first use with a minimum of debug, so only
the global minimum filters it until it sets its own.
LogChannel
Section titled “LogChannel”String* name;u8 minLevel;void setMinLevel(u8 level)void log(u8 level, String* msg)void error(String* msg) void error(string fmt, ...)void warning(String* msg) void warning(string fmt, ...)void info(String* msg) void info(string fmt, ...)void debug(String* msg) void debug(string fmt, ...)A message passes when it is at or above both the channel’s minimum and the global one.
Monitors
Section titled “Monitors”addMonitor / removeMonitor
Section titled “addMonitor / removeMonitor”static void addMonitor(callback cb void(String* subsystem, u8 level, String* msg))static void removeMonitor(callback cb void(String* subsystem, u8 level, String* msg))cb is usually a bound method, &watcher.onLog.
Where it goes
Section titled “Where it goes”The Logger made on first use is the platform’s, and it writes to the place that platform’s developers look at:
| Platform | Destination | To see it |
|---|---|---|
| macOS, Linux, Windows, arm9, m68k | standard output, through Stdio; error: and warning: are prefixed, in red and yellow on a terminal | the terminal, or redirect stdout |
| iOS, iOS simulator | the system log, through syslog: errors at LOG_ERR, warnings at LOG_WARNING, the rest at LOG_NOTICE | Console.app, log stream, or xcrun simctl spawn booted log stream for the simulator |
| Android | standard output, which the app’s glue copies line by line to logcat under the tag xcapp at priority INFO | adb logcat -s xcapp |
| a browser (wasm32) | the browser console: console.error for errors, console.warn for warnings, console.log for the rest | the page’s developer console |
| xt6502 | the text screen, through Stdio | the screen |
debug messages go where info messages go on every platform. A program that
wants something else, a file say, installs its own Logger with
setLogger; monitors see every message whatever the Logger does
with it.
Logger
Section titled “Logger”protocol Logger { void error(String* msg); void warning(String* msg); void info(String* msg); optional void debug(String* msg); // without it, debug messages go to info }setLogger
Section titled “setLogger”static void setLogger(Logger* l)static Logger* logger(void)Installs the app’s own Logger, or reads the one in use (made on first use). A null Logger discards messages; monitors still see them.