cleanup
This commit is contained in:
601
1 software design/components/utils/logger/ARCHITECTURE.md
Normal file
601
1 software design/components/utils/logger/ARCHITECTURE.md
Normal file
@@ -0,0 +1,601 @@
|
||||
# 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 {
|
||||
<<enumeration>>
|
||||
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 {
|
||||
<<namespace>>
|
||||
-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 {
|
||||
<<external>>
|
||||
+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<const char* ModuleTag>
|
||||
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.
|
||||
Reference in New Issue
Block a user