# ASF Logger - Architecture and Design Document ## Table of Contents 1. [Overview](#overview) 2. [Architecture Design](#architecture-design) 3. [UML Diagrams](#uml-diagrams) 4. [Design Patterns](#design-patterns) 5. [Component Structure](#component-structure) 6. [API Design](#api-design) 7. [Performance Analysis](#performance-analysis) 8. [Integration Guide](#integration-guide) 9. [Testing Strategy](#testing-strategy) 10. [Future Enhancements](#future-enhancements) ## Overview The ASF Logger is a high-performance, low-overhead logging wrapper for ESP-IDF that provides structured, traceable logging with unique message identifiers. It abstracts the underlying ESP-IDF logging mechanism while adding enhanced formatting, filtering, and configuration capabilities. ### Key Design Goals - **Zero Overhead Abstraction**: Minimal performance impact over direct ESP-IDF calls - **Structured Logging**: Consistent format with timestamps, tags, levels, and unique IDs - **Easy Integration**: Simple namespace-based API with convenient macros - **Thread Safety**: Built on ESP-IDF's thread-safe logging infrastructure - **Compile-Time Efficiency**: Header-only interface with minimal dependencies - **Memory Efficiency**: No dynamic allocation, fixed memory footprint ## Architecture Design ### High-Level Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ Application Layer │ ├─────────────────────────────────────────────────────────────┤ │ GPIO Wrapper │ UART Wrapper │ I2C Wrapper │ Other Modules │ ├─────────────────────────────────────────────────────────────┤ │ ASF Logger │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ │ │ Config │ │ Formatter │ │ Convenience │ │ │ │ Manager │ │ Engine │ │ Macros │ │ │ └─────────────┘ └─────────────┘ └─────────────────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ ESP-IDF Log System │ ├─────────────────────────────────────────────────────────────┤ │ Hardware Layer │ └─────────────────────────────────────────────────────────────┘ ``` ### Component Architecture The ASF Logger consists of three main functional components: 1. **Configuration Manager**: Handles logger settings and runtime configuration 2. **Message Formatter**: Formats log messages with timestamps, colors, and IDs 3. **API Layer**: Provides the public interface with functions and macros ## UML Diagrams ### Class Diagram ```mermaid classDiagram namespace asf_logger { class LogLevel { <> VERBOSE : 0 DEBUG : 1 INFO : 2 WARNING : 3 ERROR : 4 NONE : 5 } class LoggerConfig { +LogLevel minLevel +bool enableTimestamp +bool enableColor +bool enableId +uint32_t maxMessageLength } class Logger { <> -LoggerConfig s_config -COLOR_RESET : char* -COLOR_VERBOSE : char* -COLOR_DEBUG : char* -COLOR_INFO : char* -COLOR_WARNING : char* -COLOR_ERROR : char* +initialize(config: LoggerConfig) void +setLogLevel(level: LogLevel) void +getLogLevel() LogLevel +enableTimestamp(enable: bool) void +enableColor(enable: bool) void +enableId(enable: bool) void +getIsoTimestamp(buffer: char*, size: size_t) char* +log(tag: char*, id: uint32_t, level: LogLevel, format: char*, ...) void +logVerbose(tag: char*, id: uint32_t, format: char*, ...) void +logDebug(tag: char*, id: uint32_t, format: char*, ...) void +logInfo(tag: char*, id: uint32_t, format: char*, ...) void +logWarning(tag: char*, id: uint32_t, format: char*, ...) void +logError(tag: char*, id: uint32_t, format: char*, ...) void +getDefaultConfig() LoggerConfig +logLevelToString(level: LogLevel) char* +logLevelToColor(level: LogLevel) char* } Logger --> LoggerConfig : uses Logger --> LogLevel : uses } class ESP_IDF_Log { <> +ESP_LOGV(tag, format, ...) +ESP_LOGD(tag, format, ...) +ESP_LOGI(tag, format, ...) +ESP_LOGW(tag, format, ...) +ESP_LOGE(tag, format, ...) } Logger --> ESP_IDF_Log : delegates to ``` ### Sequence Diagram - Logging Flow ```mermaid sequenceDiagram participant App as Application participant Macro as ASF_LOGI Macro participant Logger as asf::logger participant Formatter as Message Formatter participant ESP as ESP-IDF Log participant Output as Console/UART App->>Macro: ASF_LOGI(TAG, ID, format, args) Macro->>Logger: logInfo(TAG, ID, format, args) alt Log level check Logger->>Logger: Check if INFO >= minLevel alt Level allowed Logger->>Formatter: Format message with timestamp, color, ID Formatter->>Logger: Formatted message string Logger->>ESP: ESP_LOGI("ASF", formatted_message) ESP->>Output: Write to console/UART else Level filtered Logger-->>App: Return (no output) end end ``` ### State Diagram - Logger Configuration ```mermaid stateDiagram-v2 [*] --> Uninitialized Uninitialized --> Initialized : initialize(config) state Initialized { [*] --> DefaultConfig DefaultConfig --> CustomConfig : setLogLevel() / enableTimestamp() / etc. CustomConfig --> DefaultConfig : initialize(defaultConfig) state "Runtime Configuration" as Runtime { [*] --> LevelFiltering LevelFiltering --> TimestampEnabled TimestampEnabled --> ColorEnabled ColorEnabled --> IdEnabled IdEnabled --> LevelFiltering } DefaultConfig --> Runtime CustomConfig --> Runtime } Initialized --> [*] : Application Exit ``` ### Component Diagram ```mermaid graph TB subgraph "ASF Logger Component" subgraph "Public API" A[Logger Functions] B[Convenience Macros] C[Configuration API] end subgraph "Core Implementation" D[Message Formatter] E[Level Filter] F[Timestamp Generator] G[Color Manager] end subgraph "Configuration" H[Static Config] I[Runtime Settings] end end subgraph "External Dependencies" J[ESP-IDF Log System] K[POSIX Time Functions] L[Standard C Library] end A --> D A --> E B --> A C --> H C --> I D --> F D --> G D --> J F --> K D --> L E --> H ``` ## Design Patterns ### 1. Namespace Pattern The logger uses a namespace-based design instead of a class-based approach: **Benefits:** - Zero instantiation overhead - No virtual function calls - Simple include and use - Thread-safe by design (minimal shared state) ```cpp namespace asf { namespace logger { void logInfo(const char* tag, uint32_t id, const char* format, ...); } } ``` ### 2. Configuration Object Pattern Configuration is encapsulated in a structure for easy management: ```cpp struct LoggerConfig { LogLevel minLevel; bool enableTimestamp; bool enableColor; bool enableId; uint32_t maxMessageLength; }; ``` ### 3. Template Specialization for Performance The logger uses compile-time optimizations where possible: ```cpp // Macros provide compile-time string concatenation #define ASF_LOGI(tag, id, format, ...) \ asf::logger::logInfo(tag, id, format, ##__VA_ARGS__) ``` ### 4. Facade Pattern The logger acts as a facade over the ESP-IDF logging system, providing a simplified interface: ```cpp // Complex ESP-IDF logging ESP_LOGI(TAG, "Message with %d parameters", value); // Simplified ASF logging ASF_LOGI(TAG, 1001, "Message with %d parameters", value); ``` ## Component Structure ### File Organization ``` components/utils/logger/ ├── CMakeLists.txt # Build configuration ├── README.md # User documentation ├── ARCHITECTURE.md # This document ├── com/ # Core implementation │ ├── logger.hpp # Public API header │ └── logger.cpp # Implementation ├── test/ # Unit tests │ ├── CMakeLists.txt │ └── test_logger.cpp └── example/ # Usage examples └── gpio_wrapper_example.cpp ``` ### Header Dependencies ```mermaid graph TD A[logger.hpp] --> B[cstdint] A --> C[cstdarg] A --> D[esp_log.h] A --> E[esp_timer.h] F[logger.cpp] --> A F --> G[cstdio] F --> H[cstring] F --> I[ctime] F --> J[sys/time.h] ``` ## API Design ### Function Hierarchy ``` asf::logger namespace ├── Configuration Functions │ ├── initialize(config) │ ├── setLogLevel(level) │ ├── getLogLevel() │ ├── enableTimestamp(enable) │ ├── enableColor(enable) │ └── enableId(enable) ├── Core Logging Functions │ ├── log(tag, id, level, format, ...) │ ├── logVerbose(tag, id, format, ...) │ ├── logDebug(tag, id, format, ...) │ ├── logInfo(tag, id, format, ...) │ ├── logWarning(tag, id, format, ...) │ └── logError(tag, id, format, ...) ├── Utility Functions │ ├── getIsoTimestamp(buffer, size) │ ├── logLevelToString(level) │ ├── logLevelToColor(level) │ └── getDefaultConfig() └── Convenience Macros ├── ASF_LOG_VERBOSE(tag, id, format, ...) ├── ASF_LOG_DEBUG(tag, id, format, ...) ├── ASF_LOG_INFO(tag, id, format, ...) ├── ASF_LOG_WARNING(tag, id, format, ...) ├── ASF_LOG_ERROR(tag, id, format, ...) ├── ASF_LOGV(tag, id, format, ...) ├── ASF_LOGD(tag, id, format, ...) ├── ASF_LOGI(tag, id, format, ...) ├── ASF_LOGW(tag, id, format, ...) └── ASF_LOGE(tag, id, format, ...) ``` ### Message Flow Architecture ```mermaid flowchart TD A[Application Code] --> B{Macro Call} B --> C[Level Check] C --> D{Level >= MinLevel?} D -->|No| E[Return - No Output] D -->|Yes| F[Format Message] F --> G[Add Timestamp] G --> H[Add Color Codes] H --> I[Add Message ID] I --> J[Call ESP-IDF Log] J --> K[Output to Console/UART] style A fill:#e1f5fe style E fill:#ffebee style K fill:#e8f5e8 ``` ## Performance Analysis ### Memory Usage | Component | Flash (bytes) | RAM (bytes) | Stack (bytes/call) | |-----------|---------------|-------------|-------------------| | Core Implementation | ~2048 | ~20 (static config) | ~400 | | Macros | ~0 | ~0 | ~0 | | Per Log Call | ~0 | ~0 | ~400 | | **Total** | **~2KB** | **~20B** | **~400B** | ### Performance Characteristics ```mermaid graph LR subgraph "Performance Metrics" A[Level Check: O(1)] B[Message Format: O(n)] C[Timestamp: O(1)] D[ESP-IDF Call: O(1)] end subgraph "Optimization Techniques" E[Early Level Filtering] F[Stack-based Buffers] G[Compile-time Macros] H[Minimal Function Calls] end A --> E B --> F C --> G D --> H ``` ### Timing Analysis | Operation | Typical Time (μs) | Notes | |-----------|------------------|-------| | Level Check | < 0.1 | Simple integer comparison | | Message Formatting | 10-50 | Depends on message complexity | | Timestamp Generation | 5-10 | System call overhead | | ESP-IDF Output | 100-1000 | UART/Console output speed | ## Integration Guide ### Step-by-Step Integration 1. **Include Header** ```cpp #include "logger.hpp" ``` 2. **Initialize Logger** ```cpp void app_main() { asf::logger::LoggerConfig config = asf::logger::getDefaultConfig(); config.minLevel = asf::logger::LogLevel::DEBUG; asf::logger::initialize(config); } ``` 3. **Define Module Constants** ```cpp // module_log_ids.hpp static const char* TAG = "MY_MODULE"; namespace MyModuleLogIds { static const uint32_t INIT_SUCCESS = 1001; static const uint32_t CONFIG_ERROR = 1601; } ``` 4. **Replace Existing Logging** ```cpp // Before ESP_LOGI(TAG, "Module initialized"); // After ASF_LOGI(TAG, MyModuleLogIds::INIT_SUCCESS, "Module initialized"); ``` ### Integration Patterns #### Pattern 1: Module-Specific Wrapper ```cpp class ModuleLogger { private: static const char* TAG; public: static void info(uint32_t id, const char* format, ...) { va_list args; va_start(args, format); asf::logger::logInfo(TAG, id, format, args); va_end(args); } }; ``` #### Pattern 2: Macro Wrapper ```cpp #define MODULE_LOGI(id, format, ...) \ ASF_LOGI("MODULE_NAME", id, format, ##__VA_ARGS__) ``` #### Pattern 3: Template Wrapper ```cpp template class TypedLogger { public: static void info(uint32_t id, const char* format, ...) { // Implementation } }; ``` ## Testing Strategy ### Test Categories ```mermaid mindmap root((ASF Logger Tests)) Unit Tests Configuration Tests Level Filtering Tests Message Formatting Tests Utility Function Tests Integration Tests ESP-IDF Integration Multi-threaded Usage Performance Tests System Tests Memory Usage Tests Real-world Scenarios Error Handling Tests ``` ### Test Coverage Matrix | Component | Unit Tests | Integration Tests | Performance Tests | |-----------|------------|------------------|------------------| | Configuration Manager | ✅ | ✅ | ✅ | | Message Formatter | ✅ | ✅ | ✅ | | Level Filtering | ✅ | ✅ | ✅ | | Timestamp Generation | ✅ | ✅ | ✅ | | Color Management | ✅ | ✅ | ❌ | | Macro Interface | ✅ | ✅ | ✅ | | Error Handling | ✅ | ✅ | ❌ | ### Automated Testing Pipeline ```mermaid flowchart LR A[Code Commit] --> B[Build Tests] B --> C[Unit Tests] C --> D[Integration Tests] D --> E[Performance Tests] E --> F[Memory Tests] F --> G{All Pass?} G -->|Yes| H[Deploy] G -->|No| I[Report Failure] I --> J[Fix Issues] J --> A ``` ## Future Enhancements ### Planned Features 1. **Log Rotation** - File-based logging with rotation - Configurable file sizes and retention 2. **Remote Logging** - Network-based log transmission - Log aggregation support 3. **Structured Logging** - JSON format support - Key-value pair logging 4. **Performance Monitoring** - Built-in performance metrics - Log frequency analysis 5. **Advanced Filtering** - Tag-based filtering - Runtime filter configuration ### Architecture Evolution ```mermaid timeline title ASF Logger Evolution section Phase 1 (Current) Basic Logging : Core functionality : ESP-IDF integration : Message formatting section Phase 2 (Next) Enhanced Features : File logging : Network logging : JSON support section Phase 3 (Future) Advanced Analytics : Performance monitoring : Log analysis : Machine learning integration ``` ### Extensibility Points The logger is designed with several extensibility points: 1. **Custom Formatters**: Plugin architecture for message formatting 2. **Output Backends**: Support for multiple output destinations 3. **Filter Plugins**: Custom filtering logic 4. **Compression**: Log compression for storage efficiency ## Conclusion The ASF Logger provides a robust, efficient, and extensible logging solution for ESP-IDF applications. Its namespace-based design ensures minimal overhead while providing rich functionality for structured logging with unique message identification. The architecture balances performance, usability, and maintainability, making it suitable for both development and production environments. The comprehensive testing strategy and clear integration patterns ensure reliable operation across various use cases. Future enhancements will focus on advanced features while maintaining the core design principles of simplicity, performance, and reliability.