Ultra-fast, low-latency logging library for C with nanosecond-scale overhead.
- Low latency: 54ns median logging overhead
- Lock-free producers: Thread-local staging buffers eliminate contention
- Flexible output: Binary (compressed) or text (human-readable) formats
- Custom patterns: JSON, logfmt, syslog, or any custom format
- Automatic rotation: Daily log rotation with seamless transitions
- Zero dependencies: Standard C11 only
- Cross-platform: Linux, macOS, Windows
#include <cnanolog.h>
int main(void) {
// Initialize logger
cnanolog_init("app.clog");
// Log messages (supports 0-50 arguments automatically)
LOG_INFO("Application started");
LOG_WARN("Low memory: %d MB available", available_mb);
LOG_ERROR("Connection failed: %s (code: %d)", error_msg, code);
// Cleanup
cnanolog_shutdown();
return 0;
}Compile:
gcc -std=c11 -pthread myapp.c -lcnanolog -o myappDecompress binary logs:
./decompressor app.clog > app.loggit clone https://github.com/zachgenius/CNanoLog.git
cd CNanoLog
mkdir build && cd build
cmake ..
make
sudo make installCNANOLOG_ENABLE_TIMESTAMPS- Enable timestamps (default: ON)BUILD_EXAMPLES- Build examples (default: ON)BUILD_TESTS- Build tests (default: ON)
- Usage Guide - Detailed usage examples and patterns
- API Reference - Complete API documentation
- Configuration - Tuning and optimization options
- Binary Format - Binary log format specification
cnanolog_rotation_config_t config = {
.policy = CNANOLOG_ROTATE_NONE,
.base_path = "app.log",
.format = CNANOLOG_OUTPUT_TEXT,
.text_pattern = "%T [%l] %m" // HH:MM:SS [LEVEL] message
};
cnanolog_init_ex(&config);
LOG_INFO("Server started on port %d", 8080);
// Output: 11:23:45.123 [INFO] Server started on port 8080cnanolog_rotation_config_t config = {
.policy = CNANOLOG_ROTATE_DAILY,
.base_path = "logs/app.log",
.format = CNANOLOG_OUTPUT_TEXT
};
cnanolog_init_ex(&config);
// Logs rotate automatically at midnight:
// logs/app-2025-11-08.log
// logs/app-2025-11-09.logvoid* worker_thread(void* arg) {
cnanolog_preallocate(); // Avoid first-log allocation
LOG_INFO("Worker %d started", thread_id);
// ... work ...
return NULL;
}
int main(void) {
cnanolog_init("app.clog");
pthread_t threads[4];
for (int i = 0; i < 4; i++)
pthread_create(&threads[i], NULL, worker_thread, &i);
for (int i = 0; i < 4; i++)
pthread_join(threads[i], NULL);
cnanolog_shutdown();
}Supported tokens for custom text output:
%t- Full timestamp (YYYY-MM-DD HH:MM:SS.nnnnnnnnn)%T- Short timestamp (HH:MM:SS.nnn)%d- Date (YYYY-MM-DD)%D- Time (HH:MM:SS)%l- Level name (INFO, WARN, ERROR, DEBUG)%L- Level letter (I, W, E, D)%f- Filename%F- Full file path%n- Line number%m- Message%%- Literal %
Examples:
// JSON
.text_pattern = "{\"time\":\"%t\",\"level\":\"%l\",\"msg\":\"%m\"}"
// Logfmt
.text_pattern = "time=\"%t\" level=%l file=%f:%n msg=\"%m\""
// Syslog
.text_pattern = "%d %T myapp[%l]: %m"Producer Thread (Lock-free)
↓
Thread-local Staging Buffer (8MB)
↓
Background Thread
↓ (format/compress)
Log File (binary or text)
Producers pack raw arguments into binary format (~54ns). Background thread handles formatting, compression, and I/O, keeping producer latency low.
- Producer latency is identical for binary and text modes
- Text mode: ~5-8M logs/sec throughput
- Binary mode: ~50M logs/sec throughput
- Use
cnanolog_preallocate()in threads for predictable latency - Pin background thread to dedicated core for 3x throughput boost
- Maximum 50 arguments per log call
- Format strings must be compile-time literals
- Logs dropped when buffer full (no blocking mode yet)
- Date-based rotation only (no size-based rotation)
MIT License - see LICENSE file for details.
Inspired by NanoLog from Stanford University (USENIX ATC 2018).