239 lines
6.0 KiB
Markdown
239 lines
6.0 KiB
Markdown
# 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
|