Calf is a structured, header-only C++17 logging library for the CAPIO ecosystem. It produces indented JSON output where each logged scope becomes a self-contained object with enter/exit timestamps and a nested array of events, making logs machine-readable without post-processing.
Calf is designed to work in two distinct environments:
- STL safe processes: uses
std::ofstreamfor I/O (StlLogger) - NON STL safe processes: uses raw syscalls whenever STL is not safe (
SyscallLogger)
Both backends share the same JSON structure and produce identical output formats.
- C++17 or later
- CMake 3.16 or later
- Linux for
SyscallLoggerbackend
Each log scope opened by START_LOG becomes one JSON object in a root array. Inner LOG calls populate the events array. Scopes close with a ts_exit timestamp.
[
{
"invoker": "capio_openat",
"file": "posix/open.cpp",
"line": 77,
"ts_enter": 42,
"args": "dirfd=4, pathname=/tmp/foo, flags=0",
"events": [
{ "ts": 43, "invoker": "get_file_location", "file": "location.hpp", "line": 96, "args": "path=/tmp/foo" },
{ "ts": 44, "invoker": "get_file_location", "file": "location.hpp", "line": 96, "args": "File found on node host0" }
],
"ts_exit": 45
}
]Each thread writes to its own log file under the log directory, named after the thread ID.
include(FetchContent)
FetchContent_Declare(
calf
GIT_REPOSITORY https://github.com/High-Performance-IO/calf.git
GIT_TAG <commit-sha> # pin to a specific commit for reproducible builds
GIT_SHALLOW TRUE
)
set(CALF_LOG ON CACHE BOOL "" FORCE)
set(CALF_BUILD_STL ON CACHE BOOL "" FORCE)
set(CALF_BUILD_SYSCALL ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(calf)Then link each target to the appropriate backend:
# Server binary
target_link_libraries(my_server PRIVATE calf::stl)
# POSIX syscall interceptor (.so)
target_link_libraries(my_interceptor PRIVATE calf::syscall)| Option | Default | Description |
|---|---|---|
CALF_LOG |
ON |
Enable logging. When OFF all macros are no-ops. |
CALF_BUILD_STL |
ON |
Include the STL (std::ofstream) backend. |
CALF_BUILD_SYSCALL |
ON |
Include the raw-syscall backend. |
Include StlLogger.h. Logging is enabled by default on every thread.
#include <calf/StlLogger.h>
void handle_request(int tid, const char *path) {
START_LOG(tid, "call(path=%s)", path);
LOG("processing path=%s", path);
// ... do work ...
LOG("done");
} // ts_exit written here when log goes out of scopeInclude SyscallLogger.h. Logging starts disabled to avoid re-entrancy during library setup. Call ENABLE_LOGGER() once setup is complete.
If the interceptor uses syscall_no_intercept from the syscall_intercept library, redirect Calf's syscalls before enabling:
#include <calf/SyscallLogger.h>
#include <libsyscall_intercept_hook_point.h>
// Called once during interceptor initialisation.
void setup() {
SET_CALF_SYSCALL_HANDLER(syscall_no_intercept);
ENABLE_LOGGER();
}
long hook(long syscall_number, ...) {
START_LOG(capio_syscall(SYS_gettid), "call()");
// ...
}Use DISABLE_LOGGER() around internal operations that must not appear in the log (e.g. Calf's own file I/O):
void internal_op() {
DISABLE_LOGGER(); // RAII: re-enables on scope exit
// ... internal syscalls not logged ...
}| Macro | Description |
|---|---|
START_LOG(tid, fmt, ...) |
Opens a log scope. Creates a Logger log RAII object on the stack. |
LOG(fmt, ...) |
Appends an event to the current scope's events array. |
ERR_EXIT(fmt, ...) |
Logs then terminates (or throws if continue_on_error is true). |
ENABLE_LOGGER() |
Activates logging on the calling thread (POSIX build only). |
DISABLE_LOGGER() |
Suspends logging for the current scope via RAII. |
DBG(tid, lambda) |
Wraps a lambda in a debug-only log scope. Compiled out in release builds. |
SET_CALF_SYSCALL_HANDLER |
Sets non intercepted syscall function handler. available only in SyscallLogger backend. |
| Variable | Description | Default |
|---|---|---|
CALF_LOG_DIR |
Root directory for all log output. | ./calf_logs |
CALF_LOG_PREFIX |
Filename prefix for per-thread log files. | Backend-specific |
Log files are written to $CALF_LOG_DIR/<backend>/<hostname>/<prefix><tid>.log.