UTE/Strategy/Logs.mqh

356 lines
31 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:34:43 +02:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Logs.mqh |
//| Copyright 2016, Vasiliy Sokolov, St-Petersburg, Russia |
//| https://www.mql5.com/ru/users/c-4 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, Vasiliy Sokolov."
#property link "https://www.mql5.com/ru/users/c-4"
#include <Object.mqh>
#include <Arrays\ArrayObj.mqh>
#include "Message.mqh"
//+------------------------------------------------------------------+
//| ;0AA, >@30=87CNI89 ;>38@>20=85 A>>1I5=89, 2 2845 A8=3;B>=0 |
//+------------------------------------------------------------------+
class CLog
{
private:
static CLog* m_log; // #:070B5;L =0 3;>10;L=K9 AB0B8G5A:89 M:75<?;O@
CArrayObj m_messages; // !?8A>: A>E@0=5==KE A>>1I5=89
bool m_terminal_enable; // AB8=0, 5A;8 B@51C5BAO 2K2>48BL ?>;CG5=>5 A>>1I5=85 2 B>@3>2K9 B5@<8=0;
ENUM_MESSAGE_TYPE m_terminal_priority; // !>45@68B 7040==K9 ?@8>@8B5B >BAK;:8 A>>1I5=89 =0 <>18;L=K5 CAB@>9AB20 04@5A0B>2.
bool m_push_enable; // A;8 8AB8=0, ?@>8AE>48B >B?@02:0 Push-C254><;5=89.
ENUM_MESSAGE_TYPE m_push_priority; // !>45@68B 7040==K9 ?@8>@8B5B 2K2>40 A>>1I5=89 2 >:=> B5@<8=0;0.
bool m_email_enable; // A;8 8AB8=0, ?@>8AE>48B >B?@02:0 email-C254><;5=89.
ENUM_MESSAGE_TYPE m_email_priority; // !>45@68B 7040==K9 ?@8>@8B5B 2K2>40 A>>1I5=89 email.
//
bool m_recursive; // $;03 C:07K20NI89 =0 @5:C@A82=K9 2K7>2 45AB@C:B>@0.
void CheckMessage(CMessage *msg);
CLog(void); // @820B=K9 :>=AB@C:B>@
~CLog(void);
string GetName(void);
void DeleteOldLogs(int day_history=30);
void DeleteOldLog(string file_name,int day_history);
// Added in v1.10
bool SendPush(CMessage *msg);
bool SendEmail(CMessage *msg);
public:
static CLog *GetLog(void); // 5B>4, 4;O ?>;CG5=8O AB0B8G5A:>3> >1J5:B0.
bool AddMessage(CMessage *msg);
void Clear(void);
bool Save(string path);
CMessage *MessageAt(int index)const;
int Total(void);
void TerminalEnable(bool enable);
bool TerminalEnable(void);
void PushEnable(bool enable);
bool PushEnable(void);
void PushPriority(ENUM_MESSAGE_TYPE type);
ENUM_MESSAGE_TYPE PushPriority(void);
void TerminalPriority(ENUM_MESSAGE_TYPE type);
ENUM_MESSAGE_TYPE TerminalPriority(void);
bool SaveToFile(void);
static bool DeleteLog(void);
// Added in v1.10
void EmailEnable(bool enable);
bool EmailEnable(void);
void EmailPriority(ENUM_MESSAGE_TYPE type);
ENUM_MESSAGE_TYPE EmailPriority(void);
};
CLog *CLog::m_log;
//+------------------------------------------------------------------+
//| >=AB@C:B>@ 3;>10;L=>3> >1J5:B0 |
//+------------------------------------------------------------------+
CLog::CLog(void) : m_terminal_enable(true),
m_email_enable(false),
m_push_enable(false),
m_recursive(false)
{
DeleteOldLogs();
m_terminal_priority = MESSAGE_WARNING;
m_push_priority = MESSAGE_ERROR;
m_email_priority =MESSAGE_ERROR;
}
CLog::~CLog(void)
{
}
//+------------------------------------------------------------------+
//| >72@0I05B >1J5:B-;>38@>2I8: |
//+------------------------------------------------------------------+
static CLog *CLog::GetLog()
{
if(CheckPointer(m_log)==POINTER_INVALID)
m_log=new CLog();
return m_log;
}
//+------------------------------------------------------------------+
//| #40;O5B >1J5:B-;>38@>2I8: |
//+------------------------------------------------------------------+
bool CLog::DeleteLog(void)
{
bool res=CheckPointer(m_log)!=POINTER_INVALID;
if(res)
delete m_log;
return res;
}
//+------------------------------------------------------------------+
//| >72@0I05B A>>1I5=85, =0E>4OI55AO ?> 8=45:AC index |
//+------------------------------------------------------------------+
CMessage *CLog::MessageAt(int index)const
{
CMessage *msg=m_messages.At(index);
return msg;
}
//+------------------------------------------------------------------+
//| >72@0I05B >1I55 :>;8G5AB2> A>>1I5=89. |
//+------------------------------------------------------------------+
int CLog::Total(void)
{
return m_messages.Total();
}
//+------------------------------------------------------------------+
//| !>E@0=O5B A>>1I5=8O 2 CSV D09;. |
//+------------------------------------------------------------------+
bool CLog::Save(string path)
{
return false;
}
//+------------------------------------------------------------------+
//| G8I05B ;>38@>2I8:. |
//+------------------------------------------------------------------+
void CLog::Clear(void)
{
m_messages.Clear();
}
//+------------------------------------------------------------------+
//| >102;O5B =>2>5 A>>1I5=85 2 A?8A>:. |
//+------------------------------------------------------------------+
bool CLog::AddMessage(CMessage *msg)
{
CheckMessage(msg);
if((m_terminal_enable) & ((int)msg.Type()>=(int)m_terminal_priority))
printf(msg.ToConsoleType());
if((m_email_enable) & ((int)msg.Type()>=(int)m_email_priority))
SendEmail(msg);
if((m_push_enable) & ((int)msg.Type()>=(int)m_push_priority))
SendPush(msg);
return m_messages.Add(msg);
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B D;03, C:07K20NI89 =5>1E>48<> ;8 2K2>48BL |
//| ?5@540==>5 A>>1I5=85 2 >:=> ?;0BD>@<K. |
//+------------------------------------------------------------------+
void CLog::TerminalEnable(bool enable)
{
m_terminal_enable=enable;
}
//+------------------------------------------------------------------+
//| >72@0I05B D;03, C:07K20NI89, ?@>8AE>48B ;8 2K2>4 ?@8=OB>3> |
//| A>>1I5=8O 2 >:=> B>@3>2>9 ?;0BD>@<K (2:;04:0 M:A?5@BK) |
//+------------------------------------------------------------------+
bool CLog::EmailEnable(void)
{
return m_email_enable;
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B D;03, C:07K20NI89 =5>1E>48<> ;8 2K2>48BL |
//| ?5@540==>5 A>>1I5=85 2 >:=> ?;0BD>@<K. |
//+------------------------------------------------------------------+
void CLog::EmailEnable(bool enable)
{
m_email_enable=enable;
}
//+------------------------------------------------------------------+
//| >72@0I05B D;03, C:07K20NI89, ?@>8AE>48B ;8 2K2>4 ?@8=OB>3> |
//| A>>1I5=8O 2 >:=> B>@3>2>9 ?;0BD>@<K (2:;04:0 M:A?5@BK) |
//+------------------------------------------------------------------+
bool CLog::TerminalEnable(void)
{
return m_terminal_enable;
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B D;03, C:07K20NI89, =5>1E>48<> ;8 >B?@02;OBL |
//| ?5@540==>5 A>>1I5=85 =0 <>18;L=K5 B5;5D>=K 04@5A0B>2. |
//+------------------------------------------------------------------+
void CLog::PushEnable(bool enable)
{
m_push_enable=enable;
}
//+------------------------------------------------------------------+
//| >72@0I05B D;03, C:07K20NI89, ?@>8AE>48B ;8 >B?@02:0 push |
//| C254><;5=89 =0 <>18;L=K5 B5;5D>=K 04@5A0B>2. |
//+------------------------------------------------------------------+
bool CLog::PushEnable(void)
{
return m_push_enable;
}
//+------------------------------------------------------------------+
//| B?@02;O5B ?5@540==>5 A>>1I5=85 =0 <>18;L=K5 CAB@>9AB20 C:070=K< |
//| 04@5A0B0<. >;55 ?>4@>1=>: |
//| https://www.mql5.com/ru/docs/common/sendnotification |
//| RETURN: |
//| AB8=0, 5A;8 >B?@02:0 ?@>H;0 CA?5H=>, ;>6L 2 ?@>B82=>< |
//| A;CG05. |
//+------------------------------------------------------------------+
bool CLog::SendPush(CMessage *msg)
{
string d="\t";
string stype= EnumToString(msg.Type());
string date = TimeToString(msg.TimeServer(), TIME_DATE|TIME_MINUTES|TIME_SECONDS);
string line = stype + d + date + d + msg.Source() + d + msg.Text();
if(StringLen(line)>255)
line=StringSubstr(line,0,255);
bool res=SendNotification(line);
return res;
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B ?@8>@8B5B >B?@02:8 =0 <>18;L=K5 CAB@>9AB20 |
//| 04@5A0B>2. 0?@8<5@ 5A;8 priority = MESSAGE_ERROR, 2A5 A>>>1I5=8O|
//| B8?0 MESSAGE_INFO 8 MESSAGE_WARNING =5 ?>?04CB 2 >B?@02:C. A;8 |
//| priority = MESSAGE_WARNING, 2 >B?@02:C 1C4CB =0?@02;5=K A>>1I5=8O|
//| B8?>2 MESSAGE_WARNING 8 MESSAGE_ERROR. |
//+------------------------------------------------------------------+
void CLog::PushPriority(ENUM_MESSAGE_TYPE priority)
{
m_push_priority=priority;
}
//+------------------------------------------------------------------+
//| >72@0I05B ?@8>@8B5B >B?@02:8 push-A>>1I5=89. |
//+------------------------------------------------------------------+
ENUM_MESSAGE_TYPE CLog::PushPriority(void)
{
return m_push_priority;
}
//+------------------------------------------------------------------+
bool CLog::SendEmail(CMessage *msg)
{
string d="\t";
string stype= EnumToString(msg.Type());
string date = TimeToString(msg.TimeServer(), TIME_DATE|TIME_MINUTES);
string line = stype + d + date + d + msg.Source();
bool res=SendMail(line,msg.Text());
return res;
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B ?@8>@8B5B >B?@02:8 =0 email |
//+------------------------------------------------------------------+
void CLog::EmailPriority(ENUM_MESSAGE_TYPE priority)
{
m_email_priority=priority;
}
//+------------------------------------------------------------------+
//| >72@0I05B ?@8>@8B5B >B?@02:8 email-A>>1I5=89. |
//+------------------------------------------------------------------+
ENUM_MESSAGE_TYPE CLog::EmailPriority(void)
{
return m_email_priority;
}
//+------------------------------------------------------------------+
//| #AB0=02;8205B ?@8>@8B5B >B?@02:8 A>>1I5=8O 2 B5@<8=0; |
//| 0?@8<5@ 5A;8 priority = MESSAGE_ERROR, 2A5 A>>>1I5=8O |
//| B8?0 MESSAGE_INFO 8 MESSAGE_WARNING =5 ?>?04CB 2 B5@<8=0;. A;8 |
//| priority = MESSAGE_WARNING, 2 B5@<8=0; 1C4CB =0?@02;5=K A>>1I5=8O|
//| B8?>2 MESSAGE_WARNING 8 MESSAGE_ERROR. |
//+------------------------------------------------------------------+
void CLog::TerminalPriority(ENUM_MESSAGE_TYPE priority)
{
m_terminal_priority=priority;
}
//+------------------------------------------------------------------+
//| >72@0I05B ?@8>@8B5B >B?@02:8 B5@<8=0;L=KE A>>1I5=89. |
//+------------------------------------------------------------------+
ENUM_MESSAGE_TYPE CLog::TerminalPriority(void)
{
return m_terminal_priority;
}
//+------------------------------------------------------------------+
//| @>25@O5B 70?>;=5=K ;8 2 ?5@540==>< A>>1I5=88 8AB>G=8:, B5:AB |
//| A>>1I5=8O. A;8 =5B, A>7405B =>2>5 ?@54C?@5640NI55 >1 MB>< |
//| A>>1I5=85. |
//+------------------------------------------------------------------+
void CLog::CheckMessage(CMessage *msg)
{
if(msg.Source()==UNKNOW_SOURCE || msg.Source()==NULL || msg.Source()=="")
{
string text="5@540==>5 A>>1I5=85 =5 A>45@68B 8AB>G=8:0 53> A>740=8O.";
CMessage *msg_info=new CMessage(MESSAGE_INFO,"CLog::AddMessage",text);
AddMessage(msg_info);
}
if(msg.Text()==NULL || msg.Text()=="")
{
string text="5@540==>5 A>>1I5=85 =5 A>45@68B B5:AB0 A>>1I5=8O.";
CMessage *msg_info=new CMessage(MESSAGE_INFO,"CLog::AddMessage",text);
AddMessage(msg_info);
}
}
//+------------------------------------------------------------------+
//| !>E@0=O5B A>>1I5=8O 2 D09;. >?8AK20O 8E 2 :>=5F. |
//+------------------------------------------------------------------+
bool CLog::SaveToFile(void)
{
int h=INVALID_HANDLE;
// 5;05< B@8 ?>?KB:8 =0 >B:@KB85 D09;0 A 7045@6:>9 200 <A5:.
for(int i=0; i<3; i++)
{
h=FileOpen(GetName(),FILE_TXT|FILE_READ|FILE_WRITE|FILE_COMMON);
if(h!=INVALID_HANDLE)break;
Sleep(200);
}
if(h==INVALID_HANDLE)
{
string text="Unable to open file "+GetName()+" Reason: "+(string)GetLastError();
CMessage *msg=new CMessage(MESSAGE_ERROR,__FUNCTION__,text);
m_log.AddMessage(msg);
return false;
}
FileSeek(h,0,SEEK_END);
for(int i=0; i<m_messages.Total(); i++)
{
CMessage *msg=m_messages.At(i);
FileWriteString(h,msg.ToCSVType()+"\n");
}
FileClose(h);
return true;
}
//+------------------------------------------------------------------+
//| 5=5@8@C5B 8<O ;>30 4;O 70?8A8, >?8@0OAL =0 B5:CICN 40BC. |
//+------------------------------------------------------------------+
string CLog::GetName(void)
{
string date=TimeToString(TimeCurrent(),TIME_DATE);
return "Logs\\log_"+date+".txt";
}
//+------------------------------------------------------------------+
//| #40;O5B ;>38 A>>1I5=89, GLO 40B0 A>740=8O AB0@H5 day_history |
//| 4=59 (?> C<>;G0=8N 30 4=59). |
//+------------------------------------------------------------------+
void CLog::DeleteOldLogs(int day_history=30)
{
string file_name="";
string filter="Logs\\log_*.txt";
long h=FileFindFirst(filter,file_name,FILE_COMMON);
DeleteOldLog("Logs\\"+file_name,day_history);
while(FileFindNext(h,file_name))
DeleteOldLog("Logs\\"+file_name,day_history);
int b=2;
}
//+------------------------------------------------------------------+
//| #40;O5B ?5@540==K9 D09;, 5A;8 53> 40B0 A>740=8O AB0@H5 |
//| day_history 4=59. |
//+------------------------------------------------------------------+
void CLog::DeleteOldLog(string file_name,int day_history)
{
int h= FileOpen(file_name,FILE_READ|FILE_BIN|FILE_COMMON);
if(h == INVALID_HANDLE)return;
MqlDateTime dt;
TimeToStruct((datetime)FileGetInteger(h,FILE_ACCESS_DATE),dt);
int seconds=(int)(TimeCurrent()-FileGetInteger(h,FILE_CREATE_DATE));
FileClose(h);
int days = seconds/3600/24;
if(days >= day_history)
FileDelete(file_name,FILE_COMMON);
}
//+------------------------------------------------------------------+