# CTsLogger - Simple and Flexible Logger for Trading Systems ***CTsLogger*** is a simple and flexible logging system specifically designed for creating and debugging trading systems in MQL5. The main advantage of CTsLogger is the ability to temporarily enable debug mode for specific modules or code sections while maintaining a lower global logging level. This allows you to get detailed logging of specific code areas without "drowning" in a flood of messages, and then disable it with a single command. ## Key Benefits - **Ease of Use**: Minimal initialization and easy invocation of logging methods - **Debugging Flexibility**: Ability to enable debug mode for individual modules even with a low global logging level - **Hierarchical Structure**: Support for hierarchical module identifiers for logical organization - **State Management**: Ability to pause and resume debug mode without losing settings - **Reliability**: Continues to work even with file system errors (graceful degradation to terminal output) - **Minimal Dependencies**: Works independently without requiring other components ## Getting Started ```mql5 // Include the logger #include "CTsLogger.mqh" // Create an instance CTsLogger *Logger = new CTsLogger(); // Initialize with file and terminal output Logger.Initialize("mylog.log", true); // Set the global logging level Logger.SetGlobalLogLevel(LOG_LEVEL_INFO); // Use logging Logger.Info("MyModule", "System initialized"); // Important: don't forget to free resources when finished delete Logger; Logger = NULL; ``` ## Logging Levels CTsLogger supports 4 logging levels, in order of increasing detail: 1. `LOG_LEVEL_ERROR` - errors only 2. `LOG_LEVEL_WARNING` - warnings and errors 3. `LOG_LEVEL_INFO` - informational messages, warnings, and errors 4. `LOG_LEVEL_DEBUG` - debug messages, informational messages, warnings, and errors ## Hierarchical Module Identifiers CTsLogger supports hierarchical module identifiers separated by dots, allowing you to organize modules into a logical structure: ```mql5 // Enable debugging for the parent module Logger.EnableDebugMode("TradeModule"); // All child modules are automatically in debug mode Logger.Debug("TradeModule.OrderExecution", "This log will be displayed"); Logger.Debug("TradeModule.RiskControl", "This one will be displayed too"); // Disable debugging for the parent module Logger.DisableDebugMode("TradeModule"); // Now logs won't be displayed for either the parent or child modules Logger.Debug("TradeModule", "This log will NOT be displayed"); Logger.Debug("TradeModule.OrderExecution", "This log will NOT be displayed either"); ``` Hierarchy can have any depth of nesting: - "TradeModule" - "TradeModule.OrderExecution" - "TradeModule.OrderExecution.StopLoss" - "TradeModule.RiskControl.Sizing" ## Flexible Debug Control The main advantage of CTsLogger is the ability to temporarily enable debug mode for specific modules while maintaining a lower global logging level. ```mql5 // Enable debugging for a specific module Logger.EnableDebugMode("TradeModule.OrderExecution"); // Now these messages will be output even with a global INFO level Logger.Debug("TradeModule.OrderExecution", "Checking parameters..."); // Check if debug mode is enabled if(Logger.IsInDebugMode("TradeModule.OrderExecution")) { // Perform additional actions } // Disable debug mode Logger.DisableDebugMode("TradeModule.OrderExecution"); ``` ## Pausing and Resuming Debug Mode CTsLogger allows you to temporarily pause debug mode for all modules: ```mql5 // Enable debugging for multiple modules Logger.EnableDebugMode("TradeModule"); Logger.EnableDebugMode("RiskManager"); Logger.EnableDebugMode("Analytics"); // Pause debug mode for all modules Logger.PauseDebugMode(); // At this point, debug messages will not be displayed Logger.Debug("TradeModule", "This log will NOT be displayed"); Logger.Debug("RiskManager", "This log will NOT be displayed"); // Resume debug mode Logger.ResumeDebugMode(); // Now debug messages will be displayed again Logger.Debug("TradeModule", "This log will be displayed"); Logger.Debug("RiskManager", "This log will be displayed"); ``` ## Complete API ### Creation and Initialization - `CTsLogger()` - constructor - `~CTsLogger()` - destructor - `Initialize(string logFileName, bool logToTerminal = true)` - logger initialization - `SetGlobalLogLevel(ENUM_LOG_LEVEL level)` - setting the global logging level ### Logging Methods - `Error(string moduleId, string message)` - error logging - `Warning(string moduleId, string message)` - warning logging - `Info(string moduleId, string message)` - information message logging - `Debug(string moduleId, string message)` - debug message logging ### Basic Debug Mode Control - `EnableDebugMode(string moduleId)` - enable debug mode for a module - `DisableDebugMode(string moduleId)` - disable debug mode for a module and all its child modules - `IsInDebugMode(string moduleId)` - check if debug mode is enabled - `EnableDebugModeAll()` - enable debug mode for all modules - `DisableDebugModeAll()` - disable global debug mode while preserving module settings ### Advanced Debug Mode Control - `PauseDebugMode()` - temporarily pause debug mode for all modules - `ResumeDebugMode()` - resume debug mode for previously configured modules - `IsDebugModePaused()` - check if debug mode is paused - `ResetDebugModules()` - completely reset all debug modules - `HasChildDebugModules(string parentModule)` - check for child modules in debug mode ## Usage Examples ### Basic Logging ```mql5 // Creation and initialization CTsLogger *Logger = new CTsLogger(); Logger.Initialize("system.log"); Logger.SetGlobalLogLevel(LOG_LEVEL_INFO); // Logging Logger.Info("System", "System started"); Logger.Warning("Trade", "Unusual market volume"); Logger.Error("DataFeed", "Data retrieval error"); Logger.Debug("Strategy", "Indicator calculation: RSI=70.2"); // won't be displayed at INFO level // Resource cleanup delete Logger; Logger = NULL; ``` ### Debugging Problem Areas Using Module Hierarchy ```mql5 CTsLogger *Logger = new CTsLogger(); Logger.Initialize("debug.log"); // Enable debugging for the entire order module Logger.EnableDebugMode("OrderManager"); // Debug messages will be visible for all submodules Logger.Debug("OrderManager.Market", "Checking market orders"); Logger.Debug("OrderManager.Pending", "Checking pending orders"); Logger.Debug("OrderManager.StopLoss", "Calculating stop loss level"); // Disable debugging only for the market orders submodule Logger.DisableDebugMode("OrderManager.Market"); // This message won't be displayed Logger.Debug("OrderManager.Market", "This will NOT be displayed"); // But these messages will continue to be displayed Logger.Debug("OrderManager.Pending", "This will be displayed"); Logger.Debug("OrderManager.StopLoss", "This will be displayed"); // Disable debugging for the entire order module and its submodules Logger.DisableDebugMode("OrderManager"); // Resource cleanup delete Logger; Logger = NULL; ``` ### Using Debug Mode Pause ```mql5 CTsLogger *Logger = new CTsLogger(); Logger.Initialize("debug.log"); // Configure multiple modules in debug mode Logger.EnableDebugMode("TradeModule"); Logger.EnableDebugMode("RiskManager"); Logger.EnableDebugMode("Analytics"); // During critical operation execution, temporarily disable debugging Logger.PauseDebugMode(); // Execute operation without debug message output ExecuteCriticalOperation(); // Resume debugging with previously configured modules Logger.ResumeDebugMode(); // If you need to completely reset all debug modules Logger.ResetDebugModules(); // Resource cleanup delete Logger; Logger = NULL; ``` ### Using in an Expert Advisor ```mql5 // Global class variable CTsLogger *Logger = NULL; int OnInit() { // Create logger instance Logger = new CTsLogger(); Logger.Initialize("ea_" + Symbol() + ".log"); Logger.SetGlobalLogLevel(LOG_LEVEL_INFO); // Enable debugging for specific modules if(IsTesting()) { Logger.EnableDebugMode("Signal"); Logger.EnableDebugMode("OrderExecution"); } Logger.Info("Expert", "Expert Advisor initialized on " + Symbol()); return INIT_SUCCEEDED; } void OnDeinit(const int reason) { if(Logger != NULL) { Logger.Info("Expert", "Expert Advisor stopped. Reason: " + string(reason)); // Free logger resources delete Logger; Logger = NULL; } } void OnTick() { if(Logger == NULL) return; Logger.Debug("Expert.OnTick", "New tick received"); // Main Expert Advisor logic // If necessary, temporarily pause debugging if(IsHighVolatilityPeriod()) { Logger.PauseDebugMode(); ExecuteHighPriorityOperations(); Logger.ResumeDebugMode(); } } ``` ## Optimization Tips - **Use hierarchical module structure**: - Divide functionality into logical groups - Use prefixes for related modules (e.g., "Trade.Open", "Trade.Close") - Limit hierarchy depth to 2-3 levels for readability - **Manage debugging efficiently**: - Enable debugging only for problematic modules - Use PauseDebugMode() to temporarily disable large amounts of logs - Disable debugging for modules after solving problems - **Resource management**: - Always free memory using delete at the end of operation - Set pointer to NULL after deletion to avoid problems with reuse - Check for NULL before using the logger