# ChronoLog 🕒 [](https://opensource.org/licenses/MIT) [](https://github.com/Hamas888/ChronoLog) [](https://github.com/Hamas888/ChronoLog) A **cross-platform real-time logging library** for embedded systems that provides structured, colorized, and timestamped logging with automatic platform detection. ChronoLog seamlessly adapts to different embedded environments including Arduino, ESP-IDF, nRF Connect SDK (Zephyr), and STM32 HAL with or without RTOS support. ## 📑 Table of Contents - [✨ Features](#-features) - [🎯 Supported Platforms](#-supported-platforms) - [📦 Installation](#-installation) - [PlatformIO (Arduino & ESP-IDF)](#platformio-arduino--esp-idf) - [ESP-IDF Component](#esp-idf-component) - [nRF Connect SDK (Zephyr)](#nrf-connect-sdk-zephyr) - [STM32Cube Project](#stm32cube-project) - [🚀 Quick Start](#-quick-start) - [Basic Usage](#basic-usage) - [Multiple Module Loggers](#multiple-module-loggers) - [Runtime Log Level Control](#runtime-log-level-control) - [📋 Log Output Examples](#-log-output-examples) - [⚙️ Configuration](#️-configuration) - [🛠️ Platform-Specific Requirements](#️-platform-specific-requirements) - [🔧 Troubleshooting](#-troubleshooting) - [📁 Repository Structure](#-repository-structure) - [🛣️ Roadmap & Upcoming Features](#️-roadmap--upcoming-features) - [💖 Support & Motivation](#-support--motivation) - [🤝 Contributing](#-contributing) - [📄 License](#-license) - [👨💻 Author](#-author) - [⭐ Show Your Support](#-show-your-support) ## ✨ Features - **🎯 Automatic Platform Detection**: Detects and adapts to Arduino, ESP-IDF, Zephyr (nRF Connect SDK), STM32 HAL, and desktop environments - **⏰ Smart Timestamps**: - Real-time timestamps when system time is synced (Arduino/ESP-IDF with NTP) - Uptime-based timestamps for other platforms - System time for desktop platforms (Linux, Windows, macOS) - **🎨 Colorized Output**: Color-coded log levels for better readability - **📋 Structured Logging**: Clean tabular format with timestamps, module names, log levels, and thread/task information - **🧵 Thread-Safe Operation**: Safe concurrent logging from multiple threads - **📊 Multiple Log Levels**: DEBUG, INFO, WARN, ERROR, FATAL with runtime level control - **🎛️ Module-based Logging**: Create separate loggers for different modules with individual log levels - **📈 Progress Bar Support**: Built-in progress tracking with visual progress bars (requires `CHRONOLOG_PRO_FEATURES`) - **🖥️ Desktop Support**: Full compatibility with Linux, Windows, and macOS - **💾 Memory Efficient**: Header-only library with minimal memory footprint - **🚀 Zero Configuration**: Works out-of-the-box on supported platforms - **⚙️ Conditional Compilation**: Enable only the features you need to optimize for your platform ## 🎯 Supported Platforms | Platform | Framework | RTOS/Thread Support | Real-time Clock | |----------|-----------|---------------------|-----------------| | **ESP32** | Arduino | ✅ FreeRTOS | ✅ NTP Sync | | **ESP32** | ESP-IDF | ✅ FreeRTOS | ✅ NTP Sync | | **STM32** | HAL | ✅ FreeRTOS/CMSIS-OS | ⏱️ HAL_GetTick() | | **STM32** | HAL | ❌ Bare Metal | ⏱️ HAL_GetTick() | | **nRF52** | nRF Connect SDK | ✅ Zephyr | ⏱️ k_uptime_get() | | **Linux** | Native | ✅ pthread | ✅ System Time | | **Windows** | Native | ✅ Windows Threads | ✅ System Time | | **macOS** | Native | ✅ pthread | ✅ System Time | ## 📦 Installation ### PlatformIO (Arduino & ESP-IDF) #### Method 1: Library Manager Search Search for "ChronoLog" in the PlatformIO Library Manager and add it to your project. #### Method 2: Add to platformio.ini Simply add ChronoLog to the `lib_deps` section in your `platformio.ini` file: ```ini [env:your_board] platform = your_platform board = your_board framework = arduino ; or espidf lib_deps = ChronoLog ``` **Example for ESP32-C6:** ```ini [env:esp32-c6-devkitm-1] platform = https://github.com/tasmota/platform-espressif32.git board = esp32-c6-devkitm-1 framework = arduino lib_deps = ChronoLog ``` ### ESP-IDF Component 1. Create a `components` folder in your project root (if it doesn't exist) 2. Navigate to the components folder and clone the repository: ```bash cd components git clone https://github.com/Hamas888/ChronoLog.git ``` 3. Add the requirement to your main `CMakeLists.txt`: ```cmake idf_component_register( SRCS "main.cpp" INCLUDE_DIRS "." REQUIRES ChronoLog # Add this line ) ``` ### nRF Connect SDK (Zephyr) 1. Create a `modules` folder in your project root 2. Navigate to the modules folder and clone the repository: ```bash cd modules git clone https://github.com/Hamas888/ChronoLog.git ``` 3. Add the subdirectory to your root `CMakeLists.txt`: ```cmake add_subdirectory(modules/ChronoLog) target_link_libraries(app PRIVATE ChronoLog) ``` ### STM32Cube Project 1. Clone the repository in your project root: ```bash git clone https://github.com/Hamas888/ChronoLog.git ``` 2. Add to your root `CMakeLists.txt` after `add_executable()`: ```cmake add_executable(${PROJECT_NAME} ${SOURCES} ${LINKER_SCRIPT}) # Add ChronoLog add_subdirectory(ChronoLog) target_link_libraries(${PROJECT_NAME} ChronoLog) ``` ### Desktop Applications (Linux, Windows, macOS) For native desktop applications, simply include the library in your CMake project: 1. Clone or download ChronoLog to your project: ```bash git clone https://github.com/Hamas888/ChronoLog.git ``` 2. Add to your `CMakeLists.txt`: ```cmake add_subdirectory(ChronoLog) target_link_libraries(your_target_name ChronoLog) ``` **Note**: Desktop builds automatically detect the platform and provide full thread safety and system time support. ## 🚀 Quick Start ### Basic Usage ```cpp #include "ChronoLog.h" // Create a logger for your module ChronoLogger logger("MyModule", CHRONOLOG_LEVEL_DEBUG); void setup() { // or main() for non-Arduino platforms // For STM32, set UART handler (REQUIRED for STM32 platforms) #if defined(CHRONOLOG_PLATFORM_STM32_HAL) logger.setUartHandler(&huart2); // Your UART handle (e.g., huart1, huart2) #endif logger.info("System initialized"); logger.debug("Debug information"); logger.warn("This is a warning"); logger.error("An error occurred"); logger.fatal("Critical system error"); } ``` ### Multiple Module Loggers ```cpp #include "ChronoLog.h" ChronoLogger sensorLogger("Sensors", CHRONOLOG_LEVEL_INFO); ChronoLogger networkLogger("Network", CHRONOLOG_LEVEL_DEBUG); ChronoLogger systemLogger("System", CHRONOLOG_LEVEL_WARN); void initLoggers() { // Required for STM32 platforms #if defined(CHRONOLOG_PLATFORM_STM32_HAL) sensorLogger.setUartHandler(&huart2); networkLogger.setUartHandler(&huart2); systemLogger.setUartHandler(&huart2); #endif } void sensorTask() { sensorLogger.info("Reading temperature: %.2f°C", 25.6f); sensorLogger.debug("Sensor calibration complete"); } void networkTask() { networkLogger.info("WiFi connected to %s", "MyNetwork"); networkLogger.error("Failed to connect to server"); } ``` ### Runtime Log Level Control ```cpp ChronoLogger logger("MyModule", CHRONOLOG_LEVEL_INFO); void updateLogLevel(int level) { logger.setLevel(static_cast<ChronoLogLevel>(level)); logger.info("Log level updated to %d", level); } ``` ### Desktop Application Example ```cpp #include "ChronoLog.h" #if defined(CHRONOLOG_PLATFORM_DESKTOP) #include <thread> #include <chrono> #endif ChronoLogger appLogger("DesktopApp", CHRONOLOG_LEVEL_DEBUG); void workerThread(int threadId) { for (int i = 0; i < 5; i++) { appLogger.info("Worker %d processing item %d", threadId, i); #if defined(CHRONOLOG_PLATFORM_DESKTOP) std::this_thread::sleep_for(std::chrono::milliseconds(100)); #endif } } int main() { appLogger.info("Desktop application started"); #if defined(CHRONOLOG_PLATFORM_DESKTOP) // Create multiple threads for testing thread safety std::thread t1(workerThread, 1); std::thread t2(workerThread, 2); t1.join(); t2.join(); #else // For embedded platforms, run sequentially workerThread(1); workerThread(2); #endif appLogger.info("All workers completed"); return 0; } ``` ### Progress Bar Example ```cpp #include "ChronoLog.h" // Enable pro features in your build configuration // #define CHRONOLOG_PRO_FEATURES 1 ChronoLogger logger("Progress", CHRONOLOG_LEVEL_PRO_FEATURES); void processWithProgress() { uint32_t total = 100; for (uint32_t i = 0; i <= total; i++) { // Update progress bar (parameter order: current, total, title) logger.progress(i, total, "Processing data"); // Simulate work #if defined(CHRONOLOG_PLATFORM_DESKTOP) std::this_thread::sleep_for(std::chrono::milliseconds(50)); #elif defined(CHRONOLOG_PLATFORM_ARDUINO) delay(50); #elif defined(CHRONOLOG_PLATFORM_ESP_IDF) vTaskDelay(pdMS_TO_TICKS(50)); #endif } logger.info("Processing completed!"); } ``` ## 📋 Log Output Examples ### Arduino/ESP-IDF with NTP Sync ``` 14:32:15 | Sensors | INFO | WiFiTask | Temperature reading: 25.6°C 14:32:15 | Network | DEBUG | NetworkTask | Attempting connection to server 14:32:16 | Network | WARN | NetworkTask | Connection timeout, retrying... 14:32:17 | System | ERROR | MainTask | Memory allocation failed 14:32:17 | System | FATAL | ErrorHandler | System halt required ``` ### STM32/nRF52 with Uptime ``` 00:05:23 | Sensors | INFO | SensorTask | Accelerometer initialized 00:05:23 | Sensors | DEBUG | SensorTask | Calibration data: X=1.02, Y=0.98, Z=9.81 00:05:24 | BLE | INFO | BLETask | Advertisement started 00:05:25 | System | WARN | MainTask | Low battery warning: 15% ``` ### Desktop Applications with Thread Safety ``` 14:32:15 | DesktopApp | INFO | Thread-123 | Worker 1 processing item 0 14:32:15 | DesktopApp | INFO | Thread-456 | Worker 2 processing item 0 14:32:15 | FileHandler | DEBUG | Thread-789 | Opening configuration file 14:32:16 | Database | ERROR | Thread-234 | Connection timeout after 5s 14:32:16 | Progress | PROGRESS | Thread-567 | Processing data: 100% (100/100) [====================] ``` **Note**: Progress bars require `CHRONOLOG_PRO_FEATURES` to be enabled and logger level set to `CHRONOLOG_LEVEL_PRO_FEATURES` or higher. ### Progress Bar Color Coding Progress bars use conditional coloring based on completion status: - **🟠 Orange**: In-progress (0-99% complete) - **🔵 Cyan**: Completed (100% complete) ### Color-Coded Output The library automatically applies color coding to different log levels: - 🔵 **DEBUG**: Blue (Italic) - 🟢 **INFO**: Green (Italic) - 🟡 **WARN**: Yellow (Italic) - 🔴 **ERROR**: Red (Italic) - 🟣 **FATAL**: Magenta (Italic) - 🟠 **PROGRESS** (In-progress): Orange (Italic) - 🔵 **PROGRESS** (Complete): Cyan (Italic) ## ⚙️ Configuration ### Compile-Time Feature Configuration ChronoLog allows you to enable or disable features at compile time to optimize for your specific use case: ```cpp // === Core Logging Configuration === #define CHRONOLOG_MODE 1 // Set to 0 to disable all logging #define CHRONOLOG_BUFFER_LEN 100 // Buffer size for log messages (default: 100) #define CHRONOLOG_DEFAULT_LEVEL CHRONOLOG_LEVEL_DEBUG // Default log level // === Feature Control === #define CHRONOLOG_COLOR_ENABLE 1 // Enable colored output (1 = enabled, 0 = disabled) #define CHRONOLOG_THREAD_SAFE 1 // Enable thread-safe operations (1 = enabled, 0 = disabled) #define CHRONOLOG_PRO_FEATURES 1 // Enable Pro features like progress bars (1 = enabled, 0 = disabled) // Note: The following features are automatically detected based on platform: // - Timestamps are always enabled and use platform-appropriate time sources // - Thread/task information is automatically detected on RTOS platforms // - Desktop support is automatic when compiling for Linux/Windows/macOS // - RTOS support is automatic when FreeRTOS/Zephyr/CMSIS-OS is detected ``` ### Example Configuration for Different Scenarios #### Minimal Embedded Configuration (Memory Constrained) ```cpp // Minimal configuration for resource-limited embedded systems #define CHRONOLOG_MODE 1 #define CHRONOLOG_BUFFER_LEN 64 // Smaller buffer to save memory #define CHRONOLOG_COLOR_ENABLE 0 // Disable colors to save memory #define CHRONOLOG_THREAD_SAFE 0 // Disable if not using RTOS #define CHRONOLOG_PRO_FEATURES 0 // Disable progress bars #define CHRONOLOG_DEFAULT_LEVEL CHRONOLOG_LEVEL_ERROR // Only show errors ``` #### Full-Featured Desktop Configuration ```cpp // Full-featured configuration for desktop applications #define CHRONOLOG_MODE 1 #define CHRONOLOG_BUFFER_LEN 512 // Larger buffer for detailed messages #define CHRONOLOG_COLOR_ENABLE 1 // Enable colors for better readability #define CHRONOLOG_THREAD_SAFE 1 // Essential for multi-threaded desktop apps #define CHRONOLOG_PRO_FEATURES 1 // Enable progress bars and advanced features #define CHRONOLOG_DEFAULT_LEVEL CHRONOLOG_LEVEL_DEBUG // Show all messages during development ``` #### Production Embedded Configuration ```cpp // Production configuration with essential features only #define CHRONOLOG_MODE 1 #define CHRONOLOG_BUFFER_LEN 200 // Moderate buffer size #define CHRONOLOG_COLOR_ENABLE 0 // Disable colors for production #define CHRONOLOG_THREAD_SAFE 1 // Keep thread safety for RTOS #define CHRONOLOG_PRO_FEATURES 0 // Disable progress bars in production #define CHRONOLOG_DEFAULT_LEVEL CHRONOLOG_LEVEL_INFO // Info level for production ``` ### Log Levels ```cpp enum ChronoLogLevel { CHRONOLOG_LEVEL_NONE, // No logging CHRONOLOG_LEVEL_FATAL, // Only fatal errors CHRONOLOG_LEVEL_ERROR, // Errors and above CHRONOLOG_LEVEL_WARN, // Warnings and above CHRONOLOG_LEVEL_INFO, // Info and above (recommended) CHRONOLOG_LEVEL_DEBUG, // All messages (development) CHRONOLOG_LEVEL_PRO_FEATURES // Includes progress bars (only when CHRONOLOG_PRO_FEATURES is enabled) }; ``` **Note**: `CHRONOLOG_LEVEL_PRO_FEATURES` is only available when `CHRONOLOG_PRO_FEATURES` is defined as 1. This conditional level enables advanced features like progress bars while maintaining backward compatibility. ### Runtime Configuration ```cpp ChronoLogger logger("MyModule", CHRONOLOG_LEVEL_INFO); // Change log level at runtime logger.setLevel(CHRONOLOG_LEVEL_DEBUG); // For STM32 platforms, set UART handler #if defined(CHRONOLOG_PLATFORM_STM32_HAL) logger.setUartHandler(&huart2); #endif // Note: Color and timestamp settings are compile-time only // Use the #define directives shown above to control these features ``` ## 🛠️ Platform-Specific Requirements ### Arduino (ESP32) - No additional setup required - Serial output at configured baud rate - For real timestamps, sync system time with NTP ### ESP-IDF - No additional setup required - Output to stdout/console - For real timestamps, configure SNTP ### STM32 HAL - **Required**: Set UART handler using `logger.setUartHandler(&huartX)` - Works with or without FreeRTOS/CMSIS-OS - Output via specified UART peripheral **STM32 Complete Setup Example:** ```cpp #include "ChronoLog.h" ChronoLogger logger("STM32App", CHRONOLOG_LEVEL_DEBUG); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART2_UART_Init(); // Initialize your UART // REQUIRED: Set UART handler for ChronoLog logger.setUartHandler(&huart2); logger.info("STM32 application started"); while (1) { logger.debug("Main loop iteration"); HAL_Delay(1000); } } ``` ### nRF Connect SDK (Zephyr) - No additional setup required - Uses Zephyr's printk for output - Automatic thread name detection ### Desktop Platforms (Linux, Windows, macOS) - **Thread Safety**: Automatic mutex-based synchronization for multi-threaded applications - **Progress Bars**: Full support for visual progress tracking - **System Time**: Uses system clock for real-time timestamps - **File Logging**: Optional file output support (coming in future releases) - **Colors**: Full ANSI color support in compatible terminals ## 🔧 Troubleshooting ### Common Issues & Solutions **STM32: No log output visible** - Ensure `logger.setUartHandler(&huartX)` is called before logging - Verify UART is properly initialized and connected - Check baud rate settings match your serial monitor **Progress bars not working** - Verify `#define CHRONOLOG_PRO_FEATURES 1` is set - Ensure logger level is `CHRONOLOG_LEVEL_PRO_FEATURES` or higher - Progress bars are only available when Pro features are enabled **Compilation errors on platform detection** - Platform detection is automatic; avoid manually defining platform macros - For custom platforms, check the header file for supported detection patterns **Thread safety issues** - Thread safety is enabled by default (`CHRONOLOG_THREAD_SAFE 1`) - On custom RTOS implementations, mutex initialization may need adjustment ## 📁 Repository Structure ``` ChronoLog/ ├── include/ │ └── ChronoLog.h # Main header file ├── examples/ │ ├── PlatformIO/ │ │ ├── Arduino/ # Arduino framework examples │ │ └── ESP-IDF/ # ESP-IDF framework examples │ ├── ESP-IDF/ # Native ESP-IDF examples │ ├── STM32Cube/ # STM32CubeIDE examples │ ├── NRF Connect SDK/ # nRF Connect SDK examples │ ├── Pro Features/ # Advanced features examples │ │ └── ESP32-S3 Progress Bar/ # Progress bar implementation │ ├── ThreadSafe/ # Thread safety examples │ │ └── ESP32-S3 Thread Safety/ # Multi-threading examples │ └── Desktop/ # Desktop application examples ├── CMakeLists.txt # Multi-platform CMake configuration ├── library.json # PlatformIO library manifest ├── library.properties # Arduino library properties ├── idf_component.yml # ESP-IDF component configuration └── README.md ``` ## 🛣️ Roadmap & Upcoming Features ChronoLog is actively developed with exciting features planned for future releases: ### 🔜 Next Major Features - **📡 Remote Logging**: Custom user channels via callbacks to route logs anywhere you need - **💾 Flash File Logging**: Log directly to flash memory with retrieval capabilities - **⚡ Memory & Speed Optimization**: Enhanced performance for resource-constrained systems - **🔧 Robust 8-bit AVR Support**: Full compatibility with Arduino Uno, Nano, and other 8-bit platforms ### 🎯 Advanced Features In My Mind - **🌐 Network Logging**: UDP/TCP log streaming for IoT applications - **📊 Log Analytics**: Built-in log filtering and analysis tools - **🔒 Encrypted Logging**: Secure log transmission and storage - **📱 Mobile App Integration**: Real-time log monitoring via smartphone apps ### 📈 Performance Improvements - **🚀 Zero-copy Logging**: Minimize memory allocations for high-frequency logging - **⚙️ Compile-time Optimization**: Further reduction in code size and RAM usage - **🔄 Circular Buffer Support**: Efficient log rotation for continuous operation **Want to influence the roadmap?** Share your ideas through [GitHub Issues](https://github.com/Hamas888/ChronoLog/issues) or reach out via [Patreon](https://patreon.com/hamas888) for direct feature discussions! ## 💖 Support & Motivation ChronoLog is developed in my spare time with passion for the embedded community. Your support helps motivate continued development of this and other upcoming sensor libraries and embedded tools. ### 🎯 Support the Project - **⭐ Star this repository** - It means a lot and helps others discover ChronoLog - **🔄 Patreon** - [Monthly support for ongoing development](https://patreon.com/hamas888) ### 💬 Get Help & Discuss - **🐛 Issues**: Create a [GitHub Issue](https://github.com/Hamas888/ChronoLog/issues) for bugs or feature requests - **💭 Direct Help**: Reach out on [Patreon](https://patreon.com/hamas888) for direct support and discussions - **📧 Email**: Contact me at hamasaeed@gmail.com for collaboration or questions Your support enables me to: - 🔧 Maintain and improve ChronoLog - 📡 Develop upcoming sensor libraries - 🚀 Create more embedded development tools - 📚 Provide community support and documentation ## 🤝 Contributing Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change. ## 📄 License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. This permissive license allows for both commercial and non-commercial use, making ChronoLog suitable for any embedded project. ## 👨💻 Author **Hamas Saeed** - GitHub: [@Hamas888](https://github.com/Hamas888) - Email: hamasaeed@gmail.com ## ⭐ Show Your Support If this project helped you, please give it a ⭐️ on [GitHub](https://github.com/Hamas888/ChronoLog)!
idf.py add-dependency "hamas888/chronolog^1.1.3"