【QuickFIX】11 ログ出力設定

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

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

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

まとめてくださっている方も
[Qiita :: C++のLoggingライブラリ plog](http://qiita.com/ignis_fatuus/items/308cdb85a4efde174b7f)


## インストール

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

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

```

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

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

```

## 組み込み Application.h ヘッダーに
```cpp: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)　設定がファイルになかったら、第２引数のデフォルト値を返すように修正


## Application.cpp も改修
```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 の追加
■　設定ファイルに無かった場合にデフォルト値を戻すように改修



## 設定ファイル

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

```bash: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";


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

```bash: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 デモ環境サーバへ接続](https://qiita.com/nobu-maple/items/52de92892a03f59c7368)
次＞ [【QuickFIX】12 マーケット情報要求 < V > MarketDataRequest](https://qiita.com/nobu-maple/items/1c4f2d27cabde8eff713)

---
# 一覧
[01 サンプルのコンパイル](https://qiita.com/nobu-maple/items/051188f21efc59429808)
[02 ログイン時にPassword(554)を送信](https://qiita.com/nobu-maple/items/649f1fd2525523f12064)
[03 送受信ログをMySQLに保存](https://qiita.com/nobu-maple/items/cc943f0c1028f21161c0)
[04 情報保存用にMySQLコネクションを保持..他](https://qiita.com/nobu-maple/items/cfe505ad984e16d46af9)
[05 各種メッセージの枠を作成](https://qiita.com/nobu-maple/items/770d8da8c50c4f5a5a54)
[06 独自メッセージ仕様](https://qiita.com/nobu-maple/items/580815f3c304d96bde31)
[07 セッション開始 <h> TradingSessionStatus](https://qiita.com/nobu-maple/items/98369bad8351cb662740)
[08 通貨ペア要求 <x> SecurityListRequest](https://qiita.com/nobu-maple/items/ba0fb7175c378bc4c608)
[09 通貨ペア取得 <y> SecurityList](https://qiita.com/nobu-maple/items/66feda02d9a717bd31b9)
[10 デモ環境サーバへ接続](https://qiita.com/nobu-maple/items/52de92892a03f59c7368)
[11 ログ出力設定](https://qiita.com/nobu-maple/items/828d3859ebf2ab2237f8)
[12 マーケット情報要求 < V > MarketDataRequest](https://qiita.com/nobu-maple/items/1c4f2d27cabde8eff713)
[13 マーケット情報受信 < X > MarketDataIncrementalRefresh](https://qiita.com/nobu-maple/items/eb7855841000eb2b0f04)
[14 口座情報要求 < AN > RequestForPositions](https://qiita.com/nobu-maple/items/30c286f8dbf1e9b0e173)
[15 口座情報取得 < AZ > CollateralResponse](https://qiita.com/nobu-maple/items/a16e3c787ef5e83f3971)

---