年始 (3)
2025/01/10
はじめに
2025年になったが少なくとも今週はダラダラやっていく。
__FUNCTION__
標準 C のマクロに __FILE__
と __LINE__
はあるが、関数名の __FUNCTION__
や __FUNC__
はない。
が、C99 からは __func__
がある。
最初は「GCC の __FUNCTION__
しかない」という話にするつもりで書き始めていたのだが、調べ直して良かった。。
なんで小文字なんだろうかと思ったが、これはマクロじゃなくて識別子だそうだ。
ログ用のマクロ
なんで __func__
の話が出てきたかというとログ用のマクロを書いていたからだ。
#if defined(LOG_LEVEL) && LOG_LEVEL >= LOG_LEVEL_INFO
#define LOG_INFO(fmt, ...) fprintf(LOG_OUTPUT, "INFO(%s:%d %s): " fmt "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#else
#define LOG_INFO(fmt, ...)
#endif
これの前は __func__
がなくて自分で関数名を埋め込んでいた。
そしてコードの整理をしているとログの関数名を書き換えになってイライラしたのだ。
修正漏れもたくさん出てきたし。
「もう GCC 専用のマクロでもいいから使ってやる!」という寸前で気付いたのだった。
いまは C99 くらいは普通になっていると思うが、どうなんだろうね。
for
文の局所変数をわざわざ外で定義したくないし。
ログのフォーマット
組み込み向けだとログ出力すること自体できないこともあるからあまり考えてなかったのだが、 ばんばん出力してよいといわれるとフォーマットがちょっと悩ましいと思った。
この前 AWS や GCP のログを集めるやつを使ったのだけど、確か JSON になっていた(誰かが設定してくれたのかもしれんが)。
C 言語だとログの出力を JSON フォーマットにわざわざするのが面倒だと思う。
いや、今回のようにヘッダの部分で出力するものが決まっていればそうでもないか。
こんな感じか?
fprintf(LOG_OUTPUT, "{\"level\":\"INFO\",\"filename\":\"%s\",\"line\":%d,\"func\":\"%s\",\"message\":\"" fmt "\"", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
JSON は末尾のコンマを許容しないのが面倒なのだ。
許容したらこんな if
文無しで済むのに。
const char keys[] = { "aaa", "bbb", "ccc" };
const char values[] = { "123", "456", "789" };
for (int i = 0; i < 3; i++) {
if (i != 0) {
printf(",");
}
printf("\"%s\":\"%s\"", keys[i], values[i]);
}
個人的には、これよりも CSV の方が短くて好きなのだが、ログにコンマが入るとちょっと嫌だな。
golang だと key=value なタイプで出力していたかもしれない。忘れた。
まあ、動作ログではなくデバッグログだからどうでもいいんだけどね。
集計するログだったらちゃんと考えると良い。