
ログレコードをマスターする(第3回):ログを保存するためのハンドラの調査
はじめに
本連載最初の記事、「ログレコードをマスターする(第1回):MQL5の基本概念と最初のステップ」では、エキスパートアドバイザー(EA)開発に最適化したログライブラリの作成に着手しました。そこで、MetaTrader 5の標準ログの制限を克服し、MQL5の世界に堅牢でカスタマイズ可能な強力なソリューションをもたらすという、この重要なツールを作る動機を探りました。
前回の記事で取り上げた主なポイントを振り返ると、私たちは次のような基本要件をもとにライブラリの基盤を構築しました。
- シングルトンによる堅牢な構造で、コードコンポーネント間の一貫性を確保
- データベースへの永続的な保存により、詳細な監査や分析を可能にする追跡可能な履歴の実現
- 柔軟な出力形式に対応し、コンソール、ファイル、端末、データベースなど多様な出力先をサポート
- ログレベルによる分類で、情報メッセージと重大なアラート・エラーを明確に区別
- 出力フォーマットのカスタマイズにより、開発者やプロジェクトごとの個別ニーズに対応
このような強固な基盤を構築したことで、私たちのログフレームワークは単なるイベントログではなく、EAの動作をリアルタイムで把握・監視・最適化するための戦略的ツールとしての価値を持つことが明らかになりました。
さて、この第3回の記事では、ハンドラ概念を理解するという重要な一歩を踏み出します。フォーマッターがデータを整理する役割を担うのに対し、ハンドラはログをどこに送るかを決定します。ハンドラは「配管工」のように機能し、ファイルやコンソール、データベース、通知システムなど適切な宛先へメッセージを届けます。この記事では、ハンドラの背後にあるロジックを理解し、様々なシナリオで使える実用的な例を作成、さらにフォーマッターとの連携についても探ります。この記事を読み終える頃には、高度にカスタマイズ可能で効率的なログストリームを構築するためのすべてのツールが手に入るでしょう。では、始めましょう。
ハンドラとは何か
ハンドラは、ログメッセージを送信する先を決める基本的なコンポーネントです。ロガーから情報を受け取り、コンソールやファイル、メール、リモートサーバーなど、適切な宛先へとメッセージを振り分ける「メッセージの配達係」のような役割を担っています。
例えば、あなたが工場を管理していると想像してください。製品(ログメッセージ)はそれぞれ異なる場所へ運ばれる必要があります。倉庫に送られるものもあれば、出荷されるもの、そして履歴として保管されるものもあります。配達係は各製品の送り先を決定する役割を持ち、これがハンドラの役目です。
各ハンドラには、例えば「重大度レベル(例:エラーメッセージのみ送る)」「出力フォーマット(例:タイムスタンプを含めるかどうか)」「出力先」などの設定が個別に指定できます。
これらのコンポーネントは、ログメッセージの振り分けや効率的なルーティングを実現するうえで非常に重要です。特に中規模以上のアプリケーションでは必須と言えます。ハンドラを使うことで、開発者はコンソール上でリアルタイムにエラーをデバッグしたり、詳細なログを保存して後から分析したり、緊急時には重要なメール通知を送信したり、監視情報を中央サーバーに送ったりすることが可能になります。これらすべてを複雑な設定なしで同時に実現できるのがハンドラの強みです。
ハンドラの仕組み
ハンドラが実際にどのように機能するかを理解するために、ライブラリの例を見てみましょう。下の図は、メッセージログの基本的な流れを示しています。
現在のフローにおいて、CLogifyクラスの主な関数は、ログエントリの重大度レベル、メッセージ、ソース、時間などのログデータを受け取るAppendメソッドです。このメソッドは受け取ったデータからMqlLogifyModel型の変数を生成し、その変数をネイティブのPrint関数を通じて端末のコンソールに送信します。
このフローは動作しますが、制約もあります。すべてのログはコンソールにのみ表示され、他の場所でメッセージを処理したり保存したりする柔軟性がありません。
しかし、ハンドラを実装することで、このフローは大幅に改善されました。以下の新しい図をご覧ください。
新しいフローでは以下のようになります。
- Appendメソッドは引き続き、ログ情報(重大度、メッセージ、ソース、時間など)を受け取ります。
- 受け取ったデータを格納するために、同じくMqlLogifyModel型の変数を生成します。
- これまでのように直接コンソールに送信する代わりに、ログはHandlers配列で管理される複数のハンドラに渡されます。
各ハンドラは独立してデータを処理できるため、ログメッセージを複数の宛先に振り分けることが可能になります。
このシステムで利用できる基本的なハンドラの例を3つ紹介します。
- HandlerTerminal:MetaTrader 5の端末にログを直接表示し、リアルタイムの診断やデバッグに役立ちます。
- HandlerFile:ログを.txtや.log形式のファイルに保存し、実行履歴の記録や将来の分析のための詳細なレポート作成に最適です。
- HandlerDatabase:SQLiteなどのデータベースにログを保存し、傾向分析やより複雑な監査に対応する高度なデータクエリを可能にします。
ハンドラの有用性を具体例で説明しましょう。たとえば、取引ロボットを開発し、その実行状況を効率的に監視するためのログシステムが必要だとします。ハンドラは次のように設定できます。
- 市場のエントリー・エグジットを含むすべての操作を記録するために、DEBUGとINFOレベルのメッセージのみをファイルに保存する。
- 問題をリアルタイムで追跡できるよう、WARNとERRORレベルのメッセージを端末に表示する。
- 重大なエラーはデータベースに保存し、エンジニアやアナリストが後から情報を取得・分析できるようにする。
このように構成することで、堅牢かつ整理された効率的なログシステムが実現します。ハンドラを活用することで、ログの処理方法や保存場所を自在にコントロールできるのです。
ハンドラ基底クラスの実装
まず、すべてのハンドラの共通の基底クラス(親クラス)となるCLogifyHandlerを実装しましょう。ライブラリのルートディレクトリに「Handlers」というフォルダを作成し、その中に「LogifyHandler」というファイルを新規作成します。このファイル内に、CLogifyHandlerクラスを定義します。最初は基本的なコンストラクタとデストラクタだけを持つシンプルなクラスです。初期のコードは以下のようになります。
//+------------------------------------------------------------------+ //| LogifyHandler.mqh | //| joaopedrodev | //| https://www.mql5.com/ja/users/joaopedrodev | //+------------------------------------------------------------------+ #property copyright "joaopedrodev" #property link "https://www.mql5.com/ja/users/joaopedrodev" //+------------------------------------------------------------------+ //| class : CLogifyHandler | //| | //| [PROPERTY] | //| Name : CLogifyHandler | //| Heritage : No heritage | //| Description : Base class for all log handlers. | //| | //+------------------------------------------------------------------+ class CLogifyHandler { public: CLogifyHandler(void); ~CLogifyHandler(void); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CLogifyHandler::CLogifyHandler(void) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CLogifyHandler::~CLogifyHandler(void) { } //+------------------------------------------------------------------+
この時点で、CLogifyHandlerクラスは「骨組み」として機能しており、今後さらに機能を拡張していきます。
次に、必要なインポートを追加しましょう。まずは、ハンドラで使用するログモデルが定義されているLogifyModel.mqhファイルをインクルードします。
//+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "../LogifyModel.mqh"
このファイルには、重大度レベル、メッセージ、ソースなど、各ログメッセージのデータをカプセル化するために使われるMqlLogifyModelクラスまたは構造体の定義が含まれています。
次に、クラスに以下の2つのprotected属性を追加します。
- m_name:ハンドラの名前を保持します。デバッグやレポート作成時の識別に役立ちます。
- m_level:ハンドラが処理するログの重大度レベルを定義します(例:DEBUG、INFO、ERROR)。
また、これらの属性を設定・取得するためのpublicメソッドも実装します。
class CLogifyHandler { protected: string m_name; ENUM_LOG_LEVEL m_level; public: //--- Set/Get void SetLevel(ENUM_LOG_LEVEL level); string GetName(void); ENUM_LOG_LEVEL GetLevel(void); }; //+------------------------------------------------------------------+ //| Set level | //+------------------------------------------------------------------+ void CLogifyHandler::SetLevel(ENUM_LOG_LEVEL level) { m_level = level; } //+------------------------------------------------------------------+ //| Get name | //+------------------------------------------------------------------+ string CLogifyHandler::GetName(void) { return(m_name); } //+------------------------------------------------------------------+ //| Get level | //+------------------------------------------------------------------+ ENUM_LOG_LEVEL CLogifyHandler::GetLevel(void) { return(m_level); } //+------------------------------------------------------------------+
m_name属性は、派生クラスのコンストラクタ内でのみ設定可能とし、セキュリティとカプセル化を強化しています。そのため、SetNameメソッドは用意していません。
すべてのハンドラが実装すべき基本的なメソッドは以下の3つです。
- Emit(MqlLogifyModel &data):ログメッセージを処理し、指定された宛先(ファイル、コンソール、データベースなど)に送信します。
- Flush():保留中の操作を終了またはクリアします。
- Close():ハンドラを閉じ、関連するリソースを解放します。
現時点では、これらの関数は仮想関数として定義し、デフォルトでは空の実装とします。これにより、各派生クラスが必要に応じて動作をカスタマイズできるようになります。
class CLogifyHandler { public: //--- Handler methods virtual void Emit(MqlLogifyModel &data); // Processes a log message and sends it to the specified destination virtual void Flush(void); // Clears or completes any pending operations virtual void Close(void); // Closes the handler and releases any resources }; //+------------------------------------------------------------------+ //| Processes a log message and sends it to the specified destination| //+------------------------------------------------------------------+ void CLogifyHandler::Emit(MqlLogifyModel &data) { } //+------------------------------------------------------------------+ //| Clears or completes any pending operations | //+------------------------------------------------------------------+ void CLogifyHandler::Flush(void) { } //+------------------------------------------------------------------+ //| Closes the handler and releases any resources | //+------------------------------------------------------------------+ void CLogifyHandler::Close(void) { } //+------------------------------------------------------------------+
この段階では、各メソッドは何も処理をおこないません。具体的な動作は、HandlerFileやHandlerDatabaseといった子クラスが実装することになります。
ハンドラの実装
基底クラスCLogifyHandlerを実装したら、それを継承する専門的なハンドラの作成に取りかかることができます。このアプローチは、継承やポリモーフィズムなどオブジェクト指向プログラミングの基本原則に則っており、コードのモジュール性と柔軟性を高めます。各専門ハンドラは、基底クラスの共通構造を活用しつつ、Emit、Flush、Closeメソッドに対して独自のロジックを実装し、それぞれの方法でログを処理します。
ハンドラの実装に入る前に、プロジェクトを整理しましょう。Handlersフォルダ内に、LogifyHandlerConsole.mqh、LogifyHandlerDatabase.mqh、LogifyHandlerFile.mqhの3つのファイルを新規作成します。最終的なフォルダ構成は以下のようになります。
LogifyHandlerConsole.mqhファイルでは、基底クラスCLogifyHandlerの属性とメソッドを継承するCLogifyHandlerConsoleクラスを作成します。最初の変更点のひとつとして、m_name変数の値をクラスのコンストラクタ内で「console」に設定します。これにより、実行時にハンドラを明確に識別しやすくなります。以下はクラスの初期定義です。
//+------------------------------------------------------------------+ //| Include files | //+------------------------------------------------------------------+ #include "LogifyHandler.mqh" //+------------------------------------------------------------------+ //| class : CLogifyHandlerConsole | //| | //| [PROPERTY] | //| Name : CLogifyHandlerConsole | //| Heritage : CLogifyHandler | //| Description : Log handler, inserts data into terminal window. | //| | //+------------------------------------------------------------------+ class CLogifyHandlerConsole : public CLogifyHandler { public: CLogifyHandlerConsole(void); ~CLogifyHandlerConsole(void); virtual void Emit(MqlLogifyModel &data); // Processes a log message and sends it to the specified destination virtual void Flush(void); // Clears or completes any pending operations virtual void Close(void); // Closes the handler and releases any resources }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CLogifyHandlerConsole::CLogifyHandlerConsole(void) { m_name = "console"; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CLogifyHandlerConsole::~CLogifyHandlerConsole(void) { } //+------------------------------------------------------------------+
Emit関数は、主にログメッセージを処理し、適切な宛先に送信する役割を持ちます。コンソールの場合は、フォーマットされたメッセージをMetaTraderの端末に表示するだけです。以下がそのメソッドの実装です。
//+------------------------------------------------------------------+ //| Processes a log message and sends it to the specified destination| //+------------------------------------------------------------------+ void CLogifyHandlerConsole::Emit(MqlLogifyModel &data) { if(data.level >= this.GetLevel()) { Print("Console handler: ",data.formated); } } //+------------------------------------------------------------------+
メッセージを表示する前に、ログレベル(data.level)がハンドラで設定されたレベルと一致しているかを確認している点に注意してください。これにより、重要または関連性のあるメッセージのみが表示されます。
コンソールハンドラと同様の考え方で、データベースやファイル用の他の専用ハンドラも作成可能です。対象ファイルはLogifyHandlerDatabase.mqhとLogifyHandlerFile.mqhです。これらのハンドラは基本的なロジックを共有しつつも、Emitメソッドの実装はそれぞれ異なる場合があります。
このハンドラはログをデータベースに保存することを目的としていますが、ここではデモ用にコンソールにメッセージを表示する形で示します。Emit関数のコードは以下のようになります。
//+------------------------------------------------------------------+ //| Processes a log message and sends it to the specified destination| //+------------------------------------------------------------------+ void CLogifyHandlerDatabase::Emit(MqlLogifyModel &data) { if(data.level >= this.GetLevel()) { Print("Database handler: ",data.formated); } } //+------------------------------------------------------------------+
LogifyHandlerFileハンドラは、ログを特定のファイルに書き込むために使用されます。Emitの初期実装は以下のとおりです。
//+------------------------------------------------------------------+ //| Processes a log message and sends it to the specified destination| //+------------------------------------------------------------------+ void CLogifyHandlerFile::Emit(MqlLogifyModel &data) { if(data.level >= this.GetLevel()) { Print("File handler: ",data.formated); } } //+------------------------------------------------------------------+
基底クラスでFlushメソッドとCloseメソッドを定義していますが、すべてのハンドラがすぐにこれらを実装する必要はありません。
- Flushメソッドは、ファイル書き込みやリアルタイムストリーミングのような、より複雑なハンドラで役立ちます。
- Closeメソッドは、データベース接続の解放や書き込みストリームのクローズなど、リソースを解放する際に必須です。
コンソールハンドラの場合は、これらのメソッドは空のままにしており、追加の処理はおこないません。なお、ここで示しているのはコードの断片であり、完全版は記事の最後からダウンロード可能です。
CLogifyクラスへのハンドラの追加
ハンドラを実装して個別に動作することを確認したので、次はライブラリのメインクラスであるCLogifyに統合します。そのために、まずはすべてのハンドラに共通の基盤となるクラスCLogifyHandlerをインポートします。これにより、ハンドラの基本構造を利用できるようになります。
#include "Handlers/LogifyHandler.mqh" #include "Handlers/LogifyHandlerConsole.mqh" #include "Handlers/LogifyHandlerDatabase.mqh" #include "Handlers/LogifyHandlerFile.mqh"
CLogifyクラスの実装では、使用するハンドラを格納するためのprivate属性を追加します。ハンドラは動的に管理されるため、CLogifyHandler型のポインタ配列を選択しました。
また、ハンドラを管理するための専用メソッドもクラスに用意します。
- AddHandler:配列に新しいハンドラを追加します。
- HasHandler:特定のハンドラが名前を基準としてリスト内に既に存在するかどうかを確認します。
- GetHandler:名前または配列内のインデックスによってハンドラを取得します。
- SizeHandlers:リスト内のハンドラの合計数を返します。
以下は、CLogifyクラスの更新されたコードです。次のメソッドが追加されています。
class CLogify { private: CLogifyHandler *m_handlers[]; public: //--- Handler void AddHandler(CLogifyHandler *handler); bool HasHandler(string name); CLogifyHandler *GetHandler(string name); CLogifyHandler *GetHandler(int index); int SizeHandlers(void); }; //+------------------------------------------------------------------+ //| Add handler to handlers array | //+------------------------------------------------------------------+ void CLogify::AddHandler(CLogifyHandler *handler) { int size = ArraySize(m_handlers); ArrayResize(m_handlers,size+1); m_handlers[size] = GetPointer(handler); } //+------------------------------------------------------------------+ //| Checks if handler is already in the array by name | //+------------------------------------------------------------------+ bool CLogify::HasHandler(string name) { int size = ArraySize(m_handlers); for(int i=0;i<size;i++) { if(m_handlers[i].GetName() == name) { return(true); } } return(false); } //+------------------------------------------------------------------+ //| Get handler by name | //+------------------------------------------------------------------+ CLogifyHandler *CLogify::GetHandler(string name) { int size = ArraySize(m_handlers); for(int i=0;i<size;i++) { if(m_handlers[i].GetName() == name) { return(m_handlers[i]); } } return(NULL); } //+------------------------------------------------------------------+ //| Get handler by index | //+------------------------------------------------------------------+ CLogifyHandler *CLogify::GetHandler(int index) { return(m_handlers[index]); } //+------------------------------------------------------------------+ //| Gets the total size of the handlers array | //+------------------------------------------------------------------+ int CLogify::SizeHandlers(void) { return(ArraySize(m_handlers)); } //+------------------------------------------------------------------+
ハンドラ管理用のメソッドが整ったので、ログ処理時にハンドラを利用するようにAppend関数の動作を調整しましょう。
Appendメソッドは、配列内のすべてのハンドラを順に処理し、それぞれのEmitメソッドを呼び出してログを適切な宛先(コンソールやデータベースなど)に送信します。
以下は、Appendメソッドの更新されたコードです。
//+------------------------------------------------------------------+ //| Generic method for adding logs | //+------------------------------------------------------------------+ bool CLogify::Append(ENUM_LOG_LEVEL level,string msg, string origin = "", string args = "",string filename="",string function="",int line=0) { //--- If the formatter is not configured, the log will not be recorded. if(m_formatter == NULL) { return(false); } //--- Textual name of the log level string levelStr = ""; switch(level) { case LOG_LEVEL_DEBUG: levelStr = "DEBUG"; break; case LOG_LEVEL_INFOR: levelStr = "INFOR"; break; case LOG_LEVEL_ALERT: levelStr = "ALERT"; break; case LOG_LEVEL_ERROR: levelStr = "ERROR"; break; case LOG_LEVEL_FATAL: levelStr = "FATAL"; break; } //--- Creating a log template with detailed information datetime time_current = TimeCurrent(); MqlLogifyModel data("",levelStr,msg,args,time_current,time_current,level,origin,filename,function,line); data.formated = m_formatter.FormatLog(data); //--- Call handlers int size = this.SizeHandlers(); for(int i=0;i<size;i++) { m_handlers[i].Emit(data); } return(true); } //+------------------------------------------------------------------+
観察点
- フォーマット済みのログはdata.formattedに格納されており、すべてのハンドラで完全な情報を利用可能にしています。
- 各ハンドラは独立してログを処理し、それぞれのEmitメソッドを呼び出します。
最後の調整として、クラスのデストラクタでハンドラ配列のポインタを削除してメモリリークを防止します。
//+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CLogify::~CLogify() { //--- Delete formatter if(m_formatter != NULL) { delete m_formatter; } //--- Delete handlers int size_handlers = ArraySize(m_handlers); for(int i=0;i<size_handlers;i++) { delete m_handlers[i]; } } //+------------------------------------------------------------------+
ハンドラのテスト
この例では、前述のテストファイル「LogifyTest.mq5」を使用します。目的は、それぞれ異なるログレベルで動作する2つのログハンドラを設定し、設定されたフィルターに基づいてログがどのように記録されるかを示すことです。
まず、異なる場所とレベルでログを記録する2つのハンドラを作成します。
- コンソール:CLogifyHandlerConsoleのインスタンスで、DEBUGレベルのメッセージ、つまり最も詳細なものから重大なエラーまで、すべてのメッセージを記録するように設定します。
- ファイル:CLogifyHandlerFileのインスタンスで、INFOレベル以上のメッセージのみを取得し、DEBUGメッセージは除外するように設定します。
以下はこれらのハンドラを設定するコードです。
int OnInit() { //--- Console CLogifyHandler *handler_console = new CLogifyHandlerConsole(); handler_console.SetLevel(LOG_LEVEL_DEBUG); //--- File CLogifyHandler *handler_file = new CLogifyHandlerFile(); handler_file.SetLevel(LOG_LEVEL_INFOR); return(INIT_SUCCEEDED); }
ハンドラを設定した後、次のステップは、アプリケーションのすべてのログを管理する基底クラスであるCLogifyにこれらのハンドラを追加することです。
さらに、ログの表示形式を定義するフォーマッターも追加します。この例で使うフォーマッターは、ログを「時:分:秒, [ログレベル], メッセージ」というパターンで整形します。
ハンドラとフォーマッターを設定した後、異なるレベルのログメッセージを3つ出力します。以下にこのステップの完全なコードを示します。
int OnInit() { //--- Console CLogifyHandler *handler_console = new CLogifyHandlerConsole(); handler_console.SetLevel(LOG_LEVEL_DEBUG); //--- File CLogifyHandler *handler_file = new CLogifyHandlerFile(); handler_file.SetLevel(LOG_LEVEL_INFOR); //--- Config logify.SetFormatter(new CLogifyFormatter("hh:mm:ss","{date_time} [{levelname}] {msg}")); logify.AddHandler(handler_console); logify.AddHandler(handler_file); //--- Logs logify.Debug("Debug Message"); logify.Infor("Information Message"); logify.Error("Error Message"); return(INIT_SUCCEEDED); }
上記のコードを実行すると、コンソールに次の出力が表示されます。
Console handler: 03:20:05 [DEBUG] Debug Message Console handler: 03:20:05 [INFOR] Information Message File handler: 03:20:05 [INFOR] Information Message Console handler: 03:20:05 [ERROR] Error Message File handler: 03:20:05 [ERROR] Error Message
結果の理解
- コンソールハンドラ(handler_console):このハンドラはDEBUGからERRORまでのすべてのメッセージをキャプチャしました。したがって、発行されたログごとに3つのエントリがコンソールに記録されました。
- ファイルハンドラ(handler_file):こちらはINFOレベル以上のメッセージのみを記録するように設定されていました。そのため、DEBUGログは無視され、INFOとERRORメッセージのみが記録され、ログファイルには合計2つのエントリが保存されました。
結論
この記事を通じて、MQL5ログライブラリの構築において重要な一歩を踏み出しました。ハンドラの概念を理解し、ログメッセージを異なる宛先へ「導く」役割を果たす重要な存在であることを学びました。ハンドラがフォーマッターと連携し、一体的でモジュール化されたログ処理システムを形成する様子も確認しました。
実践では、将来のすべての実装の基盤となる抽象クラスとしてハンドラの基本構造を作成しました。また、初期ハンドラとしてConsole、Database、Fileの3種類を開発しました。それぞれがコンソール、データベース、ファイルにログを出力する役割を担っています。現時点ではすべてPrint()関数でのシミュレーションですが、この堅牢な基盤をもとに、今後の記事で各クラスを拡張し、実用的な機能を持たせていくことが可能です。
テストを通してハンドラとライブラリの統合が確認でき、柔軟にハンドラを追加・利用する方法を示しました。この過程で、ハンドラがさまざまなログニーズに対応できるモジュール型コンポーネントとしての大きな可能性を持つことが明らかになりました。
この記事で使用したすべてのコードは以下に添付されています。ライブラリ内の各ファイルの説明を記載した表を以下に示します。
ファイル名 | 詳細 |
---|---|
Experts/Logify/LogiftTest.mq5 | ライブラリの機能をテストするファイル。実用的な例が含まれています。 |
Include/Logify/Formatter/LogifyFormatter.mqh | ログレコードのフォーマット、プレースホルダーを特定の値に置き換えるクラス |
Include/Logify/Handlers/LogifyHandler.mqh | レベル設定やログ送信を含むログハンドラを管理するための基本クラス |
Include/Logify/Handlers/LogifyHandlerConsole.mqh | フォーマットされたログをMetaTraderの端末コンソールに直接送信するログハンドラ |
Include/Logify/Handlers/LogifyHandlerDatabase.mqh | フォーマットされたログをデータベースに送信するログハンドラ(現在は出力のみが含まれているが、すぐに実際のSQLiteデータベースに保存する予定) |
Include/Logify/Handlers/LogifyHandlerFile.mqh | フォーマットされたログをファイルに送信するログハンドラ(現在は出力のみが含まれているが、すぐに実際のSQLiteデータベースに保存する予定) |
Include/Logify/Logify.mqh | ログ管理、レベル、モデル、フォーマットの統合のためのコアクラス |
Include/Logify/LogifyLevel.mqh | Logifyライブラリのログレベルを定義するファイル。詳細な制御が可能 |
Include/Logify/LogifyModel.mqh | レベル、メッセージ、タイムスタンプ、コンテキストなどの詳細を含むログレコードをモデル化する構造 |
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/16866





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索