hiro99ma blog

何か技術的なこと

年始 (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 なタイプで出力していたかもしれない。忘れた。

まあ、動作ログではなくデバッグログだからどうでもいいんだけどね。
集計するログだったらちゃんと考えると良い。

< Top page