概要
ごくごく簡単なログ機能がほしかった。
ライブラリに頼るほどでもないので、ヘッダにマクロを書いてソースで呼び出せるようにした。
ソースコード
Logger.h
#ifndef LOGGER_H
#define LOGGER_H
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
// ログのベースとなるマクロ
// ログレベル、ファイル名、行数と任意のメッセージを標準出力する。
#define LOG_BASE(LEVEL, ...) \
{ \
printf("[%s] [%s:%dL] : ", LEVEL, __FILE__, __LINE__); \
printf(__VA_ARGS__); printf("\n"); \
}
// ログ出力を定期実行するマクロ
// 指定rateは秒単位
#define LOG_THROTTLE(rate, level, ...) \
do \
{ \
time_t current_time = time(NULL); \
static time_t last_time = -rate - current_time; \
if (last_time + rate <= current_time) \
{ \
last_time = current_time; \
if (!strcmp(level, "DEBUG")) \
{ \
LOG_DEBUG(__VA_ARGS__); \
} \
else if (!strcmp(level, "INFO")) \
{ \
LOG_INFO(__VA_ARGS__); \
} \
else if (!strcmp(level, "WARN")) \
{ \
LOG_WARN(__VA_ARGS__); \
} \
else if (!strcmp(level, "ERROR")) \
{ \
LOG_ERROR(__VA_ARGS__); \
} \
else if (!strcmp(level, "FATAL")) \
{ \
LOG_FATAL(__VA_ARGS__); \
} \
} \
} while(0); \
// ログ出力を初回のみ行うマクロ
#define LOG_ONCE(level, ...) \
do \
{ \
static time_t is_first_time = true; \
if (is_first_time) \
{ \
is_first_time = false; \
if (!strcmp(level, "DEBUG")) \
{ \
LOG_DEBUG(__VA_ARGS__); \
} \
else if (!strcmp(level, "INFO")) \
{ \
LOG_INFO(__VA_ARGS__); \
} \
else if (!strcmp(level, "WARN")) \
{ \
LOG_WARN(__VA_ARGS__); \
} \
else if (!strcmp(level, "ERROR")) \
{ \
LOG_ERROR(__VA_ARGS__); \
} \
else if (!strcmp(level, "FATAL")) \
{ \
LOG_FATAL(__VA_ARGS__); \
} \
} \
} while(0); \
// LOG_BASEにログレベルを指定するマクロ
#define LOG_DEBUG(...) LOG_BASE("DEBUG", __VA_ARGS__)
#define LOG_INFO(...) LOG_BASE(" INFO", __VA_ARGS__)
#define LOG_WARN(...) LOG_BASE(" WARN", __VA_ARGS__)
#define LOG_ERROR(...) LOG_BASE("ERROR", __VA_ARGS__)
#define LOG_FATAL(...) LOG_BASE("FATAL", __VA_ARGS__)
#endif
main.cpp
#include <Windows.h>
#include "stdafx.h"
#include "Logger.h"
int main()
{
LOG_INFO("INFO情報");
LOG_DEBUG("DEBUG情報");
LOG_WARN("WARN情報");
LOG_ERROR("ERROR情報");
LOG_FATAL("FATAL情報");
for (int ii = 0; ii < 10; ii++)
{
LOG_THROTTLE(2, "INFO", "THROTTLE情報");
Sleep(1000);
}
for (int ii = 0; ii < 10; ii++)
{
LOG_ONCE("INFO", "ONCE出力");
}
system("pause");
return 0;
}
実行結果
各ログレベルでの出力、またTHROTTLEによる定期出力、ONCEによる初回出力をしているのが
確認できます。
まとめ
ヘッダのみで初回出力、定期出力のログ機能を作成できます。
ファイルへダンプしたい際には、別cppファイル等でファイルポインタを宣言してマクロに入れ込むとよいでしょう。
参考
http://docs.ros.org/diamondback/api/rosconsole/html/console_8h_source.html