feat: logging service
This commit is contained in:
238
docs/LoggingService.md
Normal file
238
docs/LoggingService.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# LoggingService - Centralized Event-Based Logging
|
||||
|
||||
The LoggingService provides a centralized, event-driven logging system for the SPORE framework. It allows components to log messages through the event system, enabling flexible log routing and filtering.
|
||||
|
||||
## Features
|
||||
|
||||
- **Event-Driven Architecture**: Uses the SPORE event system for decoupled logging
|
||||
- **Multiple Log Levels**: DEBUG, INFO, WARN, ERROR with configurable filtering
|
||||
- **Multiple Destinations**: Serial output (extensible)
|
||||
- **Component-Based Logging**: Tag messages with component names
|
||||
- **API Configuration**: Configure logging via HTTP API endpoints
|
||||
- **Easy Integration**: Simple macros and functions for logging
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Logging
|
||||
|
||||
```cpp
|
||||
#include "spore/services/LoggingService.h"
|
||||
|
||||
// Using convenience macros (requires NodeContext)
|
||||
LOG_DEBUG(ctx, "ComponentName", "Debug message");
|
||||
LOG_INFO(ctx, "ComponentName", "Info message");
|
||||
LOG_WARN(ctx, "ComponentName", "Warning message");
|
||||
LOG_ERROR(ctx, "ComponentName", "Error message");
|
||||
|
||||
// Using global functions
|
||||
logDebug(ctx, "ComponentName", "Debug message");
|
||||
logInfo(ctx, "ComponentName", "Info message");
|
||||
logWarn(ctx, "ComponentName", "Warning message");
|
||||
logError(ctx, "ComponentName", "Error message");
|
||||
```
|
||||
|
||||
### Event System Integration
|
||||
|
||||
The logging system uses the following events:
|
||||
|
||||
- `log/debug` - Debug level messages
|
||||
- `log/info` - Info level messages
|
||||
- `log/warn` - Warning level messages
|
||||
- `log/error` - Error level messages
|
||||
- `log/serial` - Messages routed to serial output
|
||||
|
||||
You can subscribe to these events for custom log handling:
|
||||
|
||||
```cpp
|
||||
// Subscribe to all debug messages
|
||||
ctx.on("log/debug", [](void* data) {
|
||||
LogData* logData = static_cast<LogData*>(data);
|
||||
// Custom handling for debug messages
|
||||
delete logData;
|
||||
});
|
||||
|
||||
// Subscribe to serial log output
|
||||
ctx.on("log/serial", [](void* data) {
|
||||
LogData* logData = static_cast<LogData*>(data);
|
||||
// Custom serial formatting
|
||||
Serial.println("CUSTOM: " + logData->message);
|
||||
delete logData;
|
||||
});
|
||||
```
|
||||
|
||||
### LoggingService Class
|
||||
|
||||
The LoggingService class provides programmatic control over logging:
|
||||
|
||||
```cpp
|
||||
LoggingService logger(ctx, apiServer);
|
||||
|
||||
// Configure logging
|
||||
logger.setLogLevel(LogLevel::DEBUG);
|
||||
logger.enableSerialLogging(true);
|
||||
|
||||
// Direct logging
|
||||
logger.debug("MyComponent", "Debug message");
|
||||
logger.info("MyComponent", "Info message");
|
||||
logger.warn("MyComponent", "Warning message");
|
||||
logger.error("MyComponent", "Error message");
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
The LoggingService provides HTTP API endpoints for configuration with proper parameter validation:
|
||||
|
||||
### Get Log Level
|
||||
```
|
||||
GET /api/logging/level
|
||||
```
|
||||
Returns current log level as JSON.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"level": "INFO"
|
||||
}
|
||||
```
|
||||
|
||||
### Set Log Level
|
||||
```
|
||||
POST /api/logging/level
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
level=DEBUG
|
||||
```
|
||||
Sets the log level with parameter validation.
|
||||
|
||||
**Parameters:**
|
||||
- `level` (required): One of `DEBUG`, `INFO`, `WARN`, `ERROR`
|
||||
|
||||
**Success Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"level": "DEBUG"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response:**
|
||||
```json
|
||||
{
|
||||
"error": "Invalid log level. Must be one of: DEBUG, INFO, WARN, ERROR"
|
||||
}
|
||||
```
|
||||
|
||||
### Get Configuration
|
||||
```
|
||||
GET /api/logging/config
|
||||
```
|
||||
Returns complete logging configuration.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"level": "INFO",
|
||||
"serialEnabled": true
|
||||
}
|
||||
```
|
||||
|
||||
## Log Levels
|
||||
|
||||
- **DEBUG**: Detailed information for debugging
|
||||
- **INFO**: General information about system operation
|
||||
- **WARN**: Warning messages for potentially harmful situations
|
||||
- **ERROR**: Error messages for serious problems
|
||||
|
||||
Only messages at or above the current log level are processed.
|
||||
|
||||
## Log Format
|
||||
|
||||
Log messages are formatted as:
|
||||
```
|
||||
[timestamp] [level] [component] message
|
||||
```
|
||||
|
||||
Example:
|
||||
```
|
||||
[12345] [INFO] [Spore] Framework setup complete
|
||||
[12350] [DEBUG] [Network] WiFi connection established
|
||||
[12355] [WARN] [Cluster] Node timeout detected
|
||||
[12360] [ERROR] [API] Failed to start server
|
||||
```
|
||||
|
||||
## Integration with SPORE
|
||||
|
||||
The LoggingService is automatically registered as a core service in the SPORE framework. It's initialized before other services to ensure logging is available throughout the system.
|
||||
|
||||
## Example
|
||||
|
||||
See `examples/logging_example/main.cpp` for a complete example demonstrating the logging system.
|
||||
|
||||
## Extending the Logging System
|
||||
|
||||
### Adding New Log Destinations
|
||||
|
||||
To add new log destinations (e.g., network logging, database logging):
|
||||
|
||||
1. Subscribe to the appropriate log events:
|
||||
```cpp
|
||||
ctx.on("log/info", [](void* data) {
|
||||
LogData* logData = static_cast<LogData*>(data);
|
||||
// Send to your custom destination
|
||||
sendToNetwork(logData->message);
|
||||
delete logData;
|
||||
});
|
||||
```
|
||||
|
||||
2. Or create a custom LoggingService subclass:
|
||||
```cpp
|
||||
class CustomLoggingService : public LoggingService {
|
||||
public:
|
||||
CustomLoggingService(NodeContext& ctx, ApiServer& apiServer)
|
||||
: LoggingService(ctx, apiServer) {
|
||||
// Register custom event handlers
|
||||
ctx.on("log/custom", [this](void* data) {
|
||||
this->handleCustomLog(data);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
void handleCustomLog(void* data) {
|
||||
// Custom log handling
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Custom Log Formatting
|
||||
|
||||
Override the `formatLogMessage` method in a custom LoggingService to change log formatting:
|
||||
|
||||
```cpp
|
||||
String CustomLoggingService::formatLogMessage(const LogData& logData) {
|
||||
// Custom formatting
|
||||
return "CUSTOM[" + logData.component + "] " + logData.message;
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Log messages are processed asynchronously through the event system
|
||||
- Memory is allocated for each log message (LogData struct)
|
||||
- Consider log level filtering to reduce overhead in production
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Logs Not Appearing
|
||||
1. Check that LoggingService is registered
|
||||
2. Verify log level is set appropriately
|
||||
3. Ensure serial logging is enabled
|
||||
4. Check Serial.begin() is called before logging
|
||||
|
||||
### Memory Issues
|
||||
1. Reduce log frequency
|
||||
2. Use higher log levels to filter messages
|
||||
|
||||
### Custom Event Handlers Not Working
|
||||
1. Ensure event handlers are registered before logging starts
|
||||
2. Check that LogData is properly deleted in custom handlers
|
||||
3. Verify event names match exactly
|
||||
Reference in New Issue
Block a user