# 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(data); // Custom handling for debug messages delete logData; }); // Subscribe to serial log output ctx.on("log/serial", [](void* data) { LogData* logData = static_cast(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(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