falcon/log¶
Structured logging for Falcon autotuners — console and file output with configurable verbosity, patterns, and log levels.
The log library binds spdlog, a fast, header-only C++ logging library, and provides four severity levels for diagnostic and operational logging.
Installation¶
import "libs/log/log.fal";
Quick Start¶
import "libs/log/log.fal";
autotuner MyAutotuner (float param) -> (float result) {
result = 0.0;
start -> run;
state run {
Error err = log::Info("Starting parameter sweep");
err = log::Debug("param value: " + strings::FromDouble(param));
result = param * 2.0;
err = log::Info("Sweep complete");
-> done;
}
state done { terminal; }
}
API Reference¶
Info(string message) -> (Error err)¶
Log an informational message at info level. This is the standard level for operational events and milestone announcements.
Error err = log::Info("Device initialized successfully");
Debug(string message) -> (Error err)¶
Log a diagnostic message at debug level. Use this for detailed tracing that is typically hidden in production.
Error err = log::Debug("Sweep parameter: voltage=0.75V, step=0.01V");
Warn(string message) -> (Error err)¶
Log a warning message at warn level. Use this to report unusual but non-fatal conditions.
Error err = log::Warn("Device calibration is stale (>24h old)");
Err(string message) -> (Error err)¶
Log an error message at error level. Use this to report failures that should be investigated but do not prevent execution.
Error err = log::Err("Measurement out of expected range: 2.5mA (expected <1mA)");
Log Levels¶
| Level | Environment Variable | Visibility | Use Case |
|---|---|---|---|
trace |
LOG_LEVEL=trace |
Very verbose | Low-level debugging (rarely used) |
debug |
LOG_LEVEL=debug |
Verbose | Development and diagnostics |
info |
LOG_LEVEL=info (default) |
Standard | Operational events, milestones |
warn |
LOG_LEVEL=warn |
Important | Unusual conditions, caution alerts |
error |
LOG_LEVEL=error |
Critical | Failures and errors |
off |
LOG_LEVEL=off |
Silent | Disable all logging |
Configuration¶
The logger is configured entirely via environment variables. Set these before running falcon-run:
LOG_LEVEL¶
Controls which messages are emitted.
export LOG_LEVEL=debug
falcon-run MyAutotuner my_autotuner.fal
Default: info
LOG_FILE¶
If set, enables dual-sink output: logs are written to both a rotating file and the console. Without this variable, logs go to console only.
export LOG_FILE=/tmp/falcon-autotuner.log
falcon-run MyAutotuner my_autotuner.fal
# Logs appear in /tmp/falcon-autotuner.log (rotated at 10MB, keeping 3 files)
# Warnings and errors also appear on stderr
Default: not set (console-only mode)
LOG_PATTERN¶
Custom spdlog format string. See spdlog format reference for syntax.
Common placeholders:
%Y-%m-%d %H:%M:%S.%f— ISO 8601 timestamp with milliseconds%l— log level (trace, debug, info, warn, error, critical)%v— message body%^...%$— color range (wraps text in ANSI color codes)
export LOG_PATTERN="[%H:%M:%S] [%^%-8l%$] %v"
falcon-run MyAutotuner my_autotuner.fal
Output:
[14:32:01] [info ] Device initialized
[14:32:01] [debug ] Setting voltage to 0.75V
[14:32:02] [warn ] High current detected: 2.1mA
Default:
[%Y-%m-%d %H:%M:%S.%f] [%^%l%$] %v
File Rotation¶
When LOG_FILE is set:
- Logs are written to a rotating file sink (max 10 MB per file)
- Up to 3 rotated backup files are retained
- Older files are automatically deleted
- The current file is always named as specified by
LOG_FILE - Errors and warnings also appear on
stderrfor immediate visibility
Example with 10 MB files:
/tmp/falcon-autotuner.log (current, <10 MB)
/tmp/falcon-autotuner.log.1 (previous, ~10 MB)
/tmp/falcon-autotuner.log.2 (older, ~10 MB)
Examples¶
Development: Verbose console output¶
export LOG_LEVEL=debug
falcon-run VoltageSweeep sweep.fal --param min=0.0 --param max=1.5
Production: File + console errors¶
export LOG_LEVEL=info
export LOG_FILE=/var/log/falcon/autotuner.log
falcon-run ChargeStability sweep.fal
Custom timestamp format¶
export LOG_PATTERN="[%T] %l: %v" # [HH:MM:SS] level: message
falcon-run MyAutotuner my_autotuner.fal
Capture only warnings and above¶
export LOG_LEVEL=warn
falcon-run MyAutotuner my_autotuner.fal
Combining with Other Libraries¶
The log library works well with io for capturing output:
import "libs/log/log.fal";
import "libs/io/io.fal";
autotuner CaptureLogsExample -> (int captured_count) {
captured_count = 0;
start -> test_logging;
state test_logging {
// Start capturing stdout
Error err = io::BeginStdout();
// Emit some log messages
err = log::Info("First message");
err = log::Debug("Second message");
err = log::Warn("Third message");
// Capture all output
string output = io::End();
// Count messages
int count = 0;
if (strings::Contains(output, "First")) { count = count + 1; }
if (strings::Contains(output, "Second")) { count = count + 1; }
if (strings::Contains(output, "Third")) { count = count + 1; }
captured_count = count;
-> done;
}
state done { terminal; }
}
Running the tests¶
falcon-test libs/log/tests/run_tests.fal
The test suite verifies:
- All four log levels (
Info,Debug,Warn,Err) produce output - Messages appear in captured stdout with correct content
- Level tags are present in the formatted output
- ANSI color codes are included (verified with
StripAnsi)
Implementation Details¶
Thread Safety¶
The underlying spdlog logger uses thread-safe sinks (stdout/stderr and rotating file sinks are all multi-threaded safe). All four routines are safe to call concurrently from multiple Falcon states.
Error Handling¶
Each routine returns an Error. Currently these are always nil (success). Future versions may return meaningful errors for I/O failures (e.g., disk full when writing to LOG_FILE).
Performance¶
Spdlog is highly optimized for low-latency logging. The default configuration is suitable for real-time quantum device control with minimal overhead.