spdlogを使うJSONの例を見かけなかったので、私たちが使った方法を共有します。人間が読めるログと、JSONによる機械可読なログを用意するのは難しくありません。

// Set up the opening brace and an array named "log"
// we're setting a global format here but as per the docs you can set this on an individual log as well
spdlog::set_pattern(set_pattern("{\n \"log\": [");

auto mylogger = spdlog::basic_logger_mt("json_logger", "mylog.json");
mylogger->info(""); // this initializes the log file with the opening brace and the "log" array as above

// We have some extra formatting on the log level %l below to keep color coding when dumping json to the console and we use a full ISO 8601 time/date format
std::string jsonpattern = {"{\"time\": \"%Y-%m-%dT%H:%M:%S.%f%z\", \"name\": \"%n\", \"level\": \"%^%l%$\", \"process\": %P, \"thread\": %t, \"message\": \"%v\"},"};

spdlog::set_pattern(jsonpattern);

その後は、通常どおり好きな内容を記録します。たとえば次のようにします。

mylogger->info(“We have started.”);

次のような構造のログエントリーが得られます。ただし、実際にはすべて1行になります。

{
     "time": "2021-01-10T13:44:14.567117-07:00",
     "name": "json_logger",
     "level": "info",
     "process": 6828,
     "thread": 23392,
     "message": "We have started."
}

ログメッセージへ入れる内容が有効なJSONであることは、自分で確認する必要があります。必要なら完全なJSONオブジェクトを使い、必要なだけ複雑にできます。多くのC++用JSONライブラリは、JSONとして解析できるstd::stringを出力でき、それをspdlogの引数へ渡せます。また、この例のようにプレーンテキストのメッセージを使うこともできます。

ログ記録が終わったら、"log"配列を閉じる必要があります。私たちはログをdropして、自分たちで片付ける処理も行います。

auto mylogger = spdlog::get("json_logger");

// All we're doing below is setting the same log format, without the "," at the end
std::string jsonlastlogpattern = { "{\"time\": \"%Y-%m-%dT%H:%M:%S.%f%z\", \"name\": \"%n\", \"level\": \"%^%l%$\", \"process\": %P, \"thread\": %t, \"message\": \"%v\"}" };
spdlog::set_pattern(jsonlastlogpattern);

// below is our last log entry
mylogger->info("Finished.");

// set the last pattern to close out the "log" json array and the closing brace
spdlog::set_pattern("]\n}");

// this writes out the closed array to the file
mylogger->info("");
spdlog::drop("json_logger");

最終的に、次のようなログファイルになります。私たちの設定・drop処理は、実際の作業とは別のスレッドで行うため、スレッドIDが異なります。

{
   "log": [
      {
         "time": "2021-01-10T13:44:14.567117-07:00",
         "name": "json_logger",
         "level": "info",
         "process": 6828,
         "thread": 23392,
         "message": "We have started."
      },
      {
         "time": "2021-01-10T13:44:23.932518-07:00",
         "name": "json_logger",
         "level": "info",
         "process": 6828,
         "thread": 8048,
         "message": "We are doing something."
      },
      {
         "time": "2021-01-10T13:44:26.927726-07:00",
         "name": "json_logger",
         "level": "info",
         "process": 6828,
         "thread": 8048,
         "message": "Look a number 123.456"
      },
      {
         "time": "2021-01-10T13:44:29.631340-07:00",
         "name": "json_logger",
         "level": "info",
         "process": 6828,
         "thread": 23392,
         "message": "Finished."
      }
   ]
}

コンパイル時に有効にした最小ログレベルに注意してください。"info"を無効にしている場合、最初のJSONの設定と最後に閉じる処理では、より高い重大度を使う必要があります。