370 lines
16 KiB
Plaintext
370 lines
16 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| LoggingManager.mqh |
|
|
//| Universal Buffer Reader EA v2.0 |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2025"
|
|
#property link ""
|
|
#property version "1.00"
|
|
#property strict
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| CLoggingManager - Smart logging with error deduplication |
|
|
//+------------------------------------------------------------------+
|
|
class CLoggingManager
|
|
{
|
|
private:
|
|
bool m_enable_debug;
|
|
string m_session_id;
|
|
|
|
// Error tracking for deduplication
|
|
struct ErrorRecord
|
|
{
|
|
int error_code;
|
|
string error_message;
|
|
int count;
|
|
datetime first_seen;
|
|
datetime last_seen;
|
|
};
|
|
|
|
ErrorRecord m_error_records[];
|
|
int m_max_error_records;
|
|
|
|
public:
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor |
|
|
//+------------------------------------------------------------------+
|
|
CLoggingManager()
|
|
{
|
|
m_enable_debug = false;
|
|
m_session_id = "";
|
|
m_max_error_records = 50;
|
|
ArrayResize(m_error_records, 0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Destructor |
|
|
//+------------------------------------------------------------------+
|
|
~CLoggingManager()
|
|
{
|
|
ArrayResize(m_error_records, 0);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Set parameters |
|
|
//+------------------------------------------------------------------+
|
|
void SetParameters(bool enable_debug)
|
|
{
|
|
m_enable_debug = enable_debug;
|
|
m_session_id = GenerateSessionID();
|
|
ClearErrorRecords();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Log info message |
|
|
//+------------------------------------------------------------------+
|
|
void LogInfo(string message)
|
|
{
|
|
Print("[INFO] ", message);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Log warning message |
|
|
//+------------------------------------------------------------------+
|
|
void LogWarning(string message)
|
|
{
|
|
Print("[WARNING] ", message);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Get error description |
|
|
//+------------------------------------------------------------------+
|
|
string ErrorDescription(int error_code)
|
|
{
|
|
switch(error_code)
|
|
{
|
|
case 0: return "No error";
|
|
case 1: return "No error, but result is unknown";
|
|
case 2: return "Common error";
|
|
case 3: return "Invalid parameters";
|
|
case 4: return "Trade server is busy";
|
|
case 5: return "Old version of the client terminal";
|
|
case 6: return "No connection with trade server";
|
|
case 7: return "Not enough rights";
|
|
case 8: return "Too frequent requests";
|
|
case 9: return "Malfunctional trade operation";
|
|
case 64: return "Account disabled";
|
|
case 65: return "Invalid account";
|
|
case 128: return "Trade timeout";
|
|
case 129: return "Invalid price";
|
|
case 130: return "Invalid stops";
|
|
case 131: return "Invalid volume";
|
|
case 132: return "Market is closed";
|
|
case 133: return "Trade is disabled";
|
|
case 134: return "Not enough money";
|
|
case 135: return "Price changed";
|
|
case 136: return "No prices";
|
|
case 137: return "Broker is busy";
|
|
case 138: return "New prices (requote)";
|
|
case 139: return "Order locked";
|
|
case 140: return "Long positions only allowed";
|
|
case 141: return "Too many requests";
|
|
case 145: return "Modification denied because order is too close to market";
|
|
case 146: return "Trade context is busy";
|
|
case 147: return "Expirations are denied by broker";
|
|
case 148: return "Too many orders";
|
|
case 149: return "Hedge is prohibited";
|
|
case 150: return "Prohibited by FIFO rules";
|
|
case 4000: return "No error";
|
|
case 4001: return "Wrong function pointer";
|
|
case 4002: return "Array index is out of range";
|
|
case 4003: return "No memory for function call stack";
|
|
case 4004: return "Recursive stack overflow";
|
|
case 4005: return "Not enough stack for parameter";
|
|
case 4006: return "No memory for parameter string";
|
|
case 4007: return "No memory for temp string";
|
|
case 4008: return "Not initialized string";
|
|
case 4009: return "Not initialized arraystring";
|
|
case 4010: return "No memory for arraystring";
|
|
case 4011: return "Too long string";
|
|
case 4012: return "Remainder from zero divide";
|
|
case 4013: return "Zero divide";
|
|
case 4014: return "Unknown command";
|
|
case 4015: return "Wrong jump (never generated error)";
|
|
case 4016: return "Not initialized array";
|
|
case 4017: return "DLL calls are not allowed";
|
|
case 4018: return "Cannot load library";
|
|
case 4019: return "Cannot call function";
|
|
case 4020: return "External function calls are not allowed";
|
|
case 4021: return "Not enough memory for temp string";
|
|
case 4022: return "System is busy (never generated error)";
|
|
case 4023: return "Internal error";
|
|
case 4024: return "Out of memory";
|
|
case 4025: return "Invalid pointer";
|
|
case 4026: return "Too long string (up to 256 characters)";
|
|
case 4027: return "Structures or classes containing objects are not allowed";
|
|
case 4028: return "Not enough memory for string";
|
|
case 4029: return "Not enough memory for arraystring";
|
|
case 4030: return "Not enough memory for array";
|
|
case 4031: return "Unknown object type";
|
|
case 4032: return "Invalid object type";
|
|
case 4033: return "Object is not initialized";
|
|
case 4034: return "Cannot apply delete operation";
|
|
case 4035: return "Too many objects";
|
|
case 4036: return "Cannot create object";
|
|
case 4037: return "Invalid object pointer";
|
|
case 4038: return "Too many array dimensions";
|
|
case 4039: return "Access to arrayindex is out of range";
|
|
case 4040: return "Custom indicator error";
|
|
case 4041: return "Incorrect series array using";
|
|
case 4042: return "Custom indicator error";
|
|
case 4043: return "Arrays are incompatible";
|
|
case 4044: return "Series array cannot be used as timeseries";
|
|
case 4045: return "Custom indicator error";
|
|
case 4046: return "Internal error";
|
|
case 4047: return "Custom indicator error";
|
|
case 4048: return "Internal error";
|
|
case 4049: return "String error";
|
|
case 4050: return "String error";
|
|
case 4051: return "String error";
|
|
case 4052: return "String error";
|
|
case 4053: return "String error";
|
|
case 4054: return "Too long string";
|
|
case 4055: return "String error";
|
|
case 4056: return "String error";
|
|
case 4057: return "String error";
|
|
case 4058: return "String error";
|
|
case 4059: return "String error";
|
|
case 4060: return "String error";
|
|
case 4061: return "Array error";
|
|
case 4062: return "Array error";
|
|
case 4063: return "Array error";
|
|
case 4064: return "Array error";
|
|
case 4065: return "Array error";
|
|
case 4066: return "Array error";
|
|
case 4067: return "Array error";
|
|
case 4068: return "Array error";
|
|
case 4069: return "String error";
|
|
case 4070: return "String error";
|
|
case 4071: return "String error";
|
|
case 4072: return "String error";
|
|
case 4073: return "String error";
|
|
case 4074: return "String error";
|
|
case 4075: return "String error";
|
|
case 4076: return "String error";
|
|
case 4077: return "String error";
|
|
case 4078: return "String error";
|
|
case 4079: return "String error";
|
|
case 4080: return "String error";
|
|
case 4081: return "Too many array dimensions";
|
|
case 4082: return "Too many array dimensions";
|
|
case 4083: return "Too many array dimensions";
|
|
case 4084: return "Too many array dimensions";
|
|
case 4085: return "Array error";
|
|
case 4086: return "Array error";
|
|
case 4087: return "Array error";
|
|
case 4088: return "Array error";
|
|
case 4089: return "Array error";
|
|
case 4090: return "Array error";
|
|
case 4091: return "Array error";
|
|
case 4092: return "Array error";
|
|
case 4093: return "Array error";
|
|
case 4094: return "Array error";
|
|
case 4095: return "Array error";
|
|
case 4096: return "Array error";
|
|
case 4097: return "Array error";
|
|
case 4098: return "Array error";
|
|
case 4099: return "Array error";
|
|
case 4100: return "Array error";
|
|
case 4101: return "Array error";
|
|
case 4102: return "Array error";
|
|
case 4103: return "Array error";
|
|
case 4104: return "Array error";
|
|
case 4105: return "Array error";
|
|
case 4106: return "Array error";
|
|
case 4107: return "Array error";
|
|
case 4108: return "Array error";
|
|
case 4109: return "Array error";
|
|
case 4110: return "Array error";
|
|
case 4111: return "Array error";
|
|
case 4112: return "Array error";
|
|
case 4113: return "Array error";
|
|
case 4114: return "Array error";
|
|
case 4115: return "Array error";
|
|
case 4116: return "Array error";
|
|
case 4117: return "Array error";
|
|
case 4118: return "Array error";
|
|
case 4119: return "Array error";
|
|
case 4200: return "Object is not exist";
|
|
case 4201: return "Unknown object property";
|
|
case 4202: return "Object is not exist";
|
|
case 4203: return "Unknown object type";
|
|
case 4204: return "No object name";
|
|
case 4205: return "Object coordinates error";
|
|
case 4206: return "No specified subwindow";
|
|
case 4207: return "Some object error";
|
|
default: return "Unknown error code: " + IntegerToString(error_code);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Log error with deduplication |
|
|
//+------------------------------------------------------------------+
|
|
void LogError(int error_code, string context)
|
|
{
|
|
string error_message = ErrorDescription(error_code);
|
|
|
|
// Check if this error has been logged before
|
|
if(IsErrorDuplicate(error_code, error_message))
|
|
{
|
|
// Update existing record
|
|
for(int i = 0; i < ArraySize(m_error_records); i++)
|
|
{
|
|
if(m_error_records[i].error_code == error_code &&
|
|
m_error_records[i].error_message == error_message)
|
|
{
|
|
m_error_records[i].count++;
|
|
m_error_records[i].last_seen = TimeCurrent();
|
|
|
|
// Log with repetition count
|
|
Print("[ERROR] ", FormatErrorMessage(error_code, context, m_error_records[i].count));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// New error - add to tracking
|
|
AddErrorRecord(error_code, error_message);
|
|
Print("[ERROR] ", FormatErrorMessage(error_code, context, 1));
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Log debug message (only if enabled) |
|
|
//+------------------------------------------------------------------+
|
|
void LogDebug(string message)
|
|
{
|
|
if(m_enable_debug)
|
|
{
|
|
Print("[DEBUG] ", message);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Clear error records |
|
|
//+------------------------------------------------------------------+
|
|
void ClearErrorRecords()
|
|
{
|
|
ArrayResize(m_error_records, 0);
|
|
}
|
|
|
|
private:
|
|
//+------------------------------------------------------------------+
|
|
//| Check if error has been logged before |
|
|
//+------------------------------------------------------------------+
|
|
bool IsErrorDuplicate(int error_code, string error_message)
|
|
{
|
|
for(int i = 0; i < ArraySize(m_error_records); i++)
|
|
{
|
|
if(m_error_records[i].error_code == error_code &&
|
|
m_error_records[i].error_message == error_message)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Add error to tracking |
|
|
//+------------------------------------------------------------------+
|
|
void AddErrorRecord(int error_code, string error_message)
|
|
{
|
|
int size = ArraySize(m_error_records);
|
|
|
|
// Limit number of tracked errors
|
|
if(size >= m_max_error_records)
|
|
{
|
|
// Remove oldest error by shifting elements
|
|
for(int i = 0; i < size - 1; i++)
|
|
{
|
|
m_error_records[i] = m_error_records[i + 1];
|
|
}
|
|
size = m_max_error_records - 1;
|
|
}
|
|
|
|
ArrayResize(m_error_records, size + 1);
|
|
m_error_records[size].error_code = error_code;
|
|
m_error_records[size].error_message = error_message;
|
|
m_error_records[size].count = 1;
|
|
m_error_records[size].first_seen = TimeCurrent();
|
|
m_error_records[size].last_seen = TimeCurrent();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Format error message for display |
|
|
//+------------------------------------------------------------------+
|
|
string FormatErrorMessage(int error_code, string context, int count)
|
|
{
|
|
string error_msg = ErrorDescription(error_code);
|
|
string result = error_msg + " (Code: " + IntegerToString(error_code) + ")";
|
|
|
|
if(count > 1)
|
|
{
|
|
result += " [REPEATED " + IntegerToString(count) + "x]";
|
|
}
|
|
|
|
result += "\nContext: " + context;
|
|
return result;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Generate session ID |
|
|
//+------------------------------------------------------------------+
|
|
string GenerateSessionID()
|
|
{
|
|
datetime now = TimeCurrent();
|
|
return TimeToString(now, TIME_DATE|TIME_MINUTES|TIME_SECONDS);
|
|
}
|
|
};
|
|
//+------------------------------------------------------------------+ |