# 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

