//+------------------------------------------------------------------+ //| 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 #include #include "Message.mqh" //+------------------------------------------------------------------+ //| Класс, организующий логирование сообщений, в виде синглтона | //+------------------------------------------------------------------+ class CLog { private: static CLog* m_log; // Указатель на глобальный статический экземпляр CArrayObj m_messages; // Список сохраненных сообщений bool m_terminal_enable; // Истина, если требуется выводить полученое сообщение в торговый терминал ENUM_MESSAGE_TYPE m_terminal_priority; // Содержит заданный приоритет отсылки сообщений на мобильные устройства адресатов. bool m_push_enable; // Если истина, происходит отправка Push-уведомлений. ENUM_MESSAGE_TYPE m_push_priority; // Содержит заданный приоритет вывода сообщений в окно терминала. bool m_email_enable; // Если истина, происходит отправка email-уведомлений. ENUM_MESSAGE_TYPE m_email_priority; // Содержит заданный приоритет вывода сообщений email. // bool m_recursive; // Флаг указывающий на рекурсивный вызов деструктора. void CheckMessage(CMessage *msg); CLog(void); // Приватный конструктор ~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); // Метод, для получения статического объекта. 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; //+------------------------------------------------------------------+ //| Конструктор глобального объекта | //+------------------------------------------------------------------+ 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) { } //+------------------------------------------------------------------+ //| Возвращает объект-логировщик | //+------------------------------------------------------------------+ static CLog *CLog::GetLog() { if(CheckPointer(m_log)==POINTER_INVALID) m_log=new CLog(); return m_log; } //+------------------------------------------------------------------+ //| Удаляет объект-логировщик | //+------------------------------------------------------------------+ bool CLog::DeleteLog(void) { bool res=CheckPointer(m_log)!=POINTER_INVALID; if(res) delete m_log; return res; } //+------------------------------------------------------------------+ //| Возвращает сообщение, находящееся по индексу index | //+------------------------------------------------------------------+ CMessage *CLog::MessageAt(int index)const { CMessage *msg=m_messages.At(index); return msg; } //+------------------------------------------------------------------+ //| Возвращает общее количество сообщений. | //+------------------------------------------------------------------+ int CLog::Total(void) { return m_messages.Total(); } //+------------------------------------------------------------------+ //| Сохраняет сообщения в CSV файл. | //+------------------------------------------------------------------+ bool CLog::Save(string path) { return false; } //+------------------------------------------------------------------+ //| Очищает логировщик. | //+------------------------------------------------------------------+ void CLog::Clear(void) { m_messages.Clear(); } //+------------------------------------------------------------------+ //| Добавляет новое сообщение в список. | //+------------------------------------------------------------------+ 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); } //+------------------------------------------------------------------+ //| Устанавливает флаг, указывающий необходимо ли выводить | //| переданное сообщение в окно платформы. | //+------------------------------------------------------------------+ void CLog::TerminalEnable(bool enable) { m_terminal_enable=enable; } //+------------------------------------------------------------------+ //| Возвращает флаг, указывающий, происходит ли вывод принятого | //| сообщения в окно торговой платформы (вкладка эксперты) | //+------------------------------------------------------------------+ bool CLog::EmailEnable(void) { return m_email_enable; } //+------------------------------------------------------------------+ //| Устанавливает флаг, указывающий необходимо ли выводить | //| переданное сообщение в окно платформы. | //+------------------------------------------------------------------+ void CLog::EmailEnable(bool enable) { m_email_enable=enable; } //+------------------------------------------------------------------+ //| Возвращает флаг, указывающий, происходит ли вывод принятого | //| сообщения в окно торговой платформы (вкладка эксперты) | //+------------------------------------------------------------------+ bool CLog::TerminalEnable(void) { return m_terminal_enable; } //+------------------------------------------------------------------+ //| Устанавливает флаг, указывающий, необходимо ли отправлять | //| переданное сообщение на мобильные телефоны адресатов. | //+------------------------------------------------------------------+ void CLog::PushEnable(bool enable) { m_push_enable=enable; } //+------------------------------------------------------------------+ //| Возвращает флаг, указывающий, происходит ли отправка push | //| уведомлений на мобильные телефоны адресатов. | //+------------------------------------------------------------------+ bool CLog::PushEnable(void) { return m_push_enable; } //+------------------------------------------------------------------+ //| Отправляет переданное сообщение на мобильные устройства указаным | //| адресатам. Более подробно: | //| https://www.mql5.com/ru/docs/common/sendnotification | //| RETURN: | //| Истина, если отправка прошла успешно, ложь в противном | //| случае. | //+------------------------------------------------------------------+ 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; } //+------------------------------------------------------------------+ //| Устанавливает приоритет отправки на мобильные устройства | //| адресатов. Например если priority = MESSAGE_ERROR, все соообщения| //| типа MESSAGE_INFO и MESSAGE_WARNING не попадут в отправку. Если | //| priority = MESSAGE_WARNING, в отправку будут направлены сообщения| //| типов MESSAGE_WARNING и MESSAGE_ERROR. | //+------------------------------------------------------------------+ void CLog::PushPriority(ENUM_MESSAGE_TYPE priority) { m_push_priority=priority; } //+------------------------------------------------------------------+ //| Возвращает приоритет отправки push-сообщений. | //+------------------------------------------------------------------+ 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; } //+------------------------------------------------------------------+ //| Устанавливает приоритет отправки на email | //+------------------------------------------------------------------+ void CLog::EmailPriority(ENUM_MESSAGE_TYPE priority) { m_email_priority=priority; } //+------------------------------------------------------------------+ //| Возвращает приоритет отправки email-сообщений. | //+------------------------------------------------------------------+ ENUM_MESSAGE_TYPE CLog::EmailPriority(void) { return m_email_priority; } //+------------------------------------------------------------------+ //| Устанавливает приоритет отправки сообщения в терминал | //| Например если priority = MESSAGE_ERROR, все соообщения | //| типа MESSAGE_INFO и MESSAGE_WARNING не попадут в терминал. Если | //| priority = MESSAGE_WARNING, в терминал будут направлены сообщения| //| типов MESSAGE_WARNING и MESSAGE_ERROR. | //+------------------------------------------------------------------+ void CLog::TerminalPriority(ENUM_MESSAGE_TYPE priority) { m_terminal_priority=priority; } //+------------------------------------------------------------------+ //| Возвращает приоритет отправки терминальных сообщений. | //+------------------------------------------------------------------+ ENUM_MESSAGE_TYPE CLog::TerminalPriority(void) { return m_terminal_priority; } //+------------------------------------------------------------------+ //| Проверяет заполнены ли в переданном сообщении источник, текст | //| сообщения. Если нет, создает новое предупреждающее об этом | //| сообщение. | //+------------------------------------------------------------------+ void CLog::CheckMessage(CMessage *msg) { if(msg.Source()==UNKNOW_SOURCE || msg.Source()==NULL || msg.Source()=="") { string text="Переданное сообщение не содержит источника его создания."; CMessage *msg_info=new CMessage(MESSAGE_INFO,"CLog::AddMessage",text); AddMessage(msg_info); } if(msg.Text()==NULL || msg.Text()=="") { string text="Переданное сообщение не содержит текста сообщения."; CMessage *msg_info=new CMessage(MESSAGE_INFO,"CLog::AddMessage",text); AddMessage(msg_info); } } //+------------------------------------------------------------------+ //| Сохраняет сообщения в файл. Дописывая их в конец. | //+------------------------------------------------------------------+ bool CLog::SaveToFile(void) { int h=INVALID_HANDLE; // Делаем три попытки на открытие файла с задержкой 200 мсек. 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= day_history) FileDelete(file_name,FILE_COMMON); } //+------------------------------------------------------------------+