LoginSignup
3
4

More than 3 years have passed since last update.

【QuickFIX】11 ログ出力設定

Last updated at Posted at 2017-04-28

今後のためにログ出力の仕組みを追加しときます

GitHub 程よいパッケージ?を発見
https://github.com/SergiusTheBest/plog

include 追加するだけで使えるってのが簡単でいいですね
詳しくは README.md でも眺めてください

まとめてくださっている方も
Qiita :: C++のLoggingライブラリ plog

インストール

適当な場所でダウンロードして

$ git clone https://github.com/SergiusTheBest/plog.git

quickfix の include ディレクトリにコピーしときます

  $ ls plog
  LICENSE  README.md  include  pom  samples
  $ ls plog/include/
  plog
  $ cp -pr plog/include/plog  quickfix/include/

組み込み Application.h ヘッダーに

examples/tradeclient/Application.h
        @@ -39,6 +39,8 @@

         #include "Rate.h"

1)      +#include <plog/Log.h>            // https://github.com/SergiusTheBest/plog
        +
         #include <queue>
         #include <vector>
         #include <map>
        @@ -63,6 +65,10 @@ public:
             m_accountID = getSetting("AccountID");
             m_partyID = getSetting("PartyID");
             m_tradingSessionStatus = 0;
2)      +    plog::init( (plog::Severity)std::stoi(getSetting("LOGLevel", "3"))  // default warning(3)
        +              , getSetting("LOGFile", "tradeclient.log").c_str()        // default filename
        +              , std::stoul(getSetting("LOGMaxSize", "10240000"))        // default 10MB=10,240,000byte
        +              , std::stoi(getSetting("LOGMaxFiles", "10")) );            // default files= 10
           }

           ~Application()
        @@ -96,7 +102,7 @@ private:
           void toApp( FIX::Message&, const FIX::SessionID& )
           throw( FIX::DoNotSend );
           void fromAdmin( const FIX::Message&, const FIX::SessionID& )
        -  throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::RejectLogon ) {}
3)      +  throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::RejectLogon );
           void fromApp( const FIX::Message& message, const FIX::SessionID& sessionID )
           throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::UnsupportedMessageType );

        @@ -130,7 +136,7 @@ private:

           void SetMessageHeader( FIX::Message&, const char* = SessionTypeTrade );
           FIX::MySQLConnection *MySQLConnect();
        -  std::string getSetting( const char* );
4)      +  std::string getSetting( const char*, const char* = "" );
           std::string YmdHMSs( const char* = "%04d%02d%02d-%02d%02d%02d.%03d" );

         };

1) ダウンロードした plog を include
2) ログ出力設定:出力するログレベルとかファイル名を設定ファイルから取ってきます
  もし設定が無かったらデフォルトを適用します
3) ログに fromAdmin の内容も出したいので、実体を書けるように {} を削除
4) 設定がファイルになかったら、第2引数のデフォルト値を返すように修正

Application.cpp も改修

examples/tradeclient/Application.cpp
        @@ -7,18 +7,40 @@
         void Application::onLogon( const FIX::SessionID& sessionID )
         {
           std::cout << std::endl << "Logon - " << sessionID << std::endl;
      +  LOG_INFO << "Logon - " << sessionID;
         }

         void Application::onLogout( const FIX::SessionID& sessionID )
         {
           std::cout << std::endl << "Logout - " << sessionID << std::endl;
      +  LOG_INFO << "Logout - " << sessionID;
         }

         void Application::fromApp( const FIX::Message& message, const FIX::SessionID& sessionID )
         throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::UnsupportedMessageType )
         {
        -  crack( message, sessionID );
        -  std::cout << std::endl << "IN: " << message << std::endl;
      +  const std::string& msgTypeValue = message.getHeader().getField( FIX::FIELD::MsgType );
      +  if( msgTypeValue != "X" )
      +  {
      +    // std::cout << std::endl << "IN: " << message << std::endl;
      +    LOG_DEBUG << "IN: " << message;
      +    LOG_VERBOSE << std::endl << message.toXML();
      +  }
      +
      +  if( msgTypeValue == "PU" )
      +    onMessage( (const FIX44::OrderRateUpdate&)message, sessionID );
      +  else
      +  if( msgTypeValue == "CG" )
      +    onMessage( (const FIX44::PartyDetailsListReport&)message, sessionID );
      +  else
      +    crack( message, sessionID );
      +}
        +
      +void Application::fromAdmin( const FIX::Message& message, const FIX::SessionID& sessionID )
      +throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::RejectLogon )
      +{
      +  LOG_DEBUG << message;
      +  LOG_VERBOSE << std::endl << message.toXML();
         }

         void Application::toAdmin( FIX::Message& message, const FIX::SessionID& sessionID )
        @@ -29,6 +51,8 @@ void Application::toAdmin( FIX::Message& message, const FIX::SessionID& sessionI
             if (dic.has("Password"))
               message.getHeader().setField(FIX::Password(dic.getString("Password")));
           }
      +  LOG_DEBUG << message;
      +  LOG_VERBOSE << std::endl << message.toXML();
         }

         void Application::toApp( FIX::Message& message, const FIX::SessionID& sessionID )
        @@ -42,8 +66,9 @@ throw( FIX::DoNotSend )
           }
           catch ( FIX::FieldNotFound& ) {}

        -  std::cout << std::endl
        -  << "OUT: " << message << std::endl;
      +  // std::cout << std::endl << "OUT: " << message << std::endl;
      +  LOG_DEBUG << "OUT: " << message;
      +  LOG_VERBOSE << std::endl << message.toXML();
         }

         void Application::run()
        @@ -57,6 +82,7 @@ void Application::run()
                 << "quit) Quit" << std::endl
                 << "Action: ";
               std::cin >> action;
      +      LOG_DEBUG << "COMMAND: " << action;

               if ( action == "quit" )
                 break;
        @@ -64,6 +90,7 @@ void Application::run()
             catch ( std::exception & e )
             {
               std::cout << "Message Not Sent: " << e.what();
      +      LOG_WARNING << "Message Not Sent: " << e.what();
             }
           }
         }
        @@ -111,11 +138,11 @@ FIX::MySQLConnection *Application::MySQLConnect()
           return new FIX::MySQLConnection( m_database, m_user, m_pass, m_host, m_port );
         }

        -std::string Application::getSetting( const char* key )
      +std::string Application::getSetting( const char* key, const char* default_value )
         {
           const FIX::Dictionary dic = m_settings.get();
           if (dic.has(key)) return dic.getString(key);
        -  return key;
      +  return default_value;
         }

         std::string Application::YmdHMSs( const char* format )

★ ログ出力部分を追加
◆ 追加メッセージの CG と PU の振り分け処理を追加(忘れてました)
▲ fromAdmin の追加
■ 設定ファイルに無かった場合にデフォルト値を戻すように改修

設定ファイル

設定ファイルにログ出力設定を追記です

examples/tradeclient/tradeclient.cfg
@@ -25,6 +25,19 @@ MySQLLogUser=QuickUSER
 MySQLLogPassword=QuickPASS
 MySQLLogHost=localhost

+# -- LOG Level ------
+#  0 none
+#  1 fatal
+#  2 error
+#  3 warning
+#  4 info
+#  5 debug
+#  6 verbose
+LOGLevel=6
+LOGFile=tradeclient.log
+LOGMaxSize=10240000
+LOGMaxFiles=10
+
 [SESSION]
 BeginString=FIX.4.4
 SenderCompID=CAXDemo_Account_Trd

これで、指定したログファイルに時刻付きでログを記録できるようになりました。

ログを出力したいときはこんな感じで使います
 LOG_VERBOSE << "verbose";
 LOG_DEBUG << "debug";
 LOG_INFO << "info";
 LOG_WARNING << "warning";
 LOG_ERROR << "error";
 LOG_FATAL << "fatal";

ログファイルにはこんな感じで記録されます

tradeclient.log
$ cat tradeclient.log
2017-04-14 10:37:31.096 DEBUG [3445] [Application::toAdmin@43]  8=FIX.4.49=9635=A34=149=CAXDemo_Account_Str52=20170414-01:37:31.09656=CNX554=Pass123498=0108=30141=Y10=126
2017-04-14 10:37:31.097 VERB  [3445] [Application::toAdmin@44]
<message>
  <header>
    <field number="8"><![CDATA[FIX.4.4]]></field>
    <field number="9"><![CDATA[96]]></field>
    <field number="35"><![CDATA[A]]></field>
    <field number="34"><![CDATA[1]]></field>
    <field number="49"><![CDATA[CAXDemo_Account_Str]]></field>
    <field number="52"><![CDATA[20170414-01:37:31.096]]></field>
    <field number="56"><![CDATA[CNX]]></field>
    <field number="554"><![CDATA[Pass1234]]></field>
  </header>
  <body>
    <field number="98"><![CDATA[0]]></field>
    <field number="108"><![CDATA[30]]></field>
    <field number="141"><![CDATA[Y]]></field>
  </body>
  <trailer>
    <field number="10"><![CDATA[126]]></field>
  </trailer>
</message>
2017-04-14 10:37:31.253 DEBUG [3445] [Application::toAdmin@43]  8=FIX.4.49=9635=A34=149=CAXDemo_Account_Trd52=20170414-01:37:31.25456=CNX554=Pass123498=0108=30141=Y10=107
2017-04-14 10:37:31.254 VERB  [3445] [Application::toAdmin@44]
<message>
  <header>
    <field number="8"><![CDATA[FIX.4.4]]></field>
    <field number="9"><![CDATA[96]]></field>
    <field number="35"><![CDATA[A]]></field>
    <field number="34"><![CDATA[1]]></field>
    <field number="49"><![CDATA[CAXDemo_Account_Trd]]></field>
    <field number="52"><![CDATA[20170414-01:37:31.254]]></field>
    <field number="56"><![CDATA[CNX]]></field>
    <field number="554"><![CDATA[Pass1234]]></field>
  </header>
  <body>
    <field number="98"><![CDATA[0]]></field>
    <field number="108"><![CDATA[30]]></field>
    <field number="141"><![CDATA[Y]]></field>
  </body>
  <trailer>
    <field number="10"><![CDATA[107]]></field>
  </trailer>
</message>
2017-04-14 10:37:31.281 INFO  [3445] [Application::onLogout@16] Logout - FIX.4.4:CAXDemo_Account_Str->CNX
2017-04-14 10:37:31.290 INFO  [3445] [Application::onLogout@16] Logout - FIX.4.4:CAXDemo_Account_Trd->CNX
2017-04-14 10:37:34.784 DEBUG [3425] [Application::run@74] COMMAND: quit


<前 【QuickFIX】10 デモ環境サーバへ接続
次> 【QuickFIX】12 マーケット情報要求 < V > MarketDataRequest


一覧

01 サンプルのコンパイル
02 ログイン時にPassword(554)を送信
03 送受信ログをMySQLに保存
04 情報保存用にMySQLコネクションを保持..他
05 各種メッセージの枠を作成
06 独自メッセージ仕様
07 セッション開始 TradingSessionStatus
08 通貨ペア要求 SecurityListRequest
09 通貨ペア取得 SecurityList
10 デモ環境サーバへ接続
11 ログ出力設定
12 マーケット情報要求 < V > MarketDataRequest
13 マーケット情報受信 < X > MarketDataIncrementalRefresh
14 口座情報要求 < AN > RequestForPositions
15 口座情報取得 < AZ > CollateralResponse


3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4