結論から言う
プログラムは嘘をつきます。
人間はもっと嘘をつきます。
ログだけが事実を残します。
ログは飾りじゃありません。デバッグ用のおまけでもありません。
ログがないコードは、どこで壊れたか分からないプログラムです。
この記事では、ログがなぜ「盾」であり「武器」なのか、そしてどう書けば真実を残せるのかを、初心者でも実践できる形でお伝えします。
なぜログは「盾」になるのか
盾は守ってくれる
ログがあれば、こう言えます。
- 「自分のコードは正常に動いていた」
- 「問題は環境にあった」
- 「入力データが想定外だった」
言い訳ではありません。証拠です。
console.log({
action: "createOrder",
input: orderData,
result: "validation_error"
});
このログがあれば分かります。
- 入力は何だったか
- どこまで処理が進んだか
- 落ちた理由は何か
「あとから条件を変えた」と疑われることもありません。
ログには時刻が残ります。「その時」何が起きたかを、誰も否定できません。
なぜログは「武器」になるのか
武器は攻めさせてくれる
ログがあれば、バグを最短でなくせます。
- 再現条件を特定できる
- 勘で直さない
- 祈らない
- 試行回数が減る
開発スピードが上がります。
「なんとなく直った」は、「なんとなく壊れる」の始まりです。バグは「雰囲気」を読んで消えてくれません。ログがあれば、原因を特定して、一点突破で修正できます。
調査時間が10分の1になることも珍しくありません。
ダメなログ / 良いログ
❌ ダメなログ
console.log("エラーが発生しました");
ここは国語の授業ではありません。
それは感想文です。
提出するなら、国語の先生へ。
- 何の処理?
- どの状態?
- 何が入ってた?
- いつ?
何も分かりません。
⭕ 良いログ
console.log({
level: "error",
action: "fetchUser",
userId: userId,
isLogin: isLogin,
error: err.message
});
これは証拠です。
- 状態が分かる
- 比較できる
- 検索できる
- 後から並べ替えできる
この差が、デバッグ時間を決めます。
構造化ロギングとは何か
一文で言うと
構造化ロギング = 文章を書くのをやめて、事実を並べること
ログに「主語・感情・修飾語」は要りません。
難しくありません。特別なライブラリも不要です。
console.log({}) で十分です。
console.log({
step: "beforeSave",
dataLength: items.length,
isValid: isValid
});
これだけで構造化です。
難しい言葉ですが、やってることは「整理整頓」です。
※本番環境では専用のロガー(winston / pino / bunyanなど)を使うことが多いですが、考え方はconsole.log({})と全く同じです。
なぜオブジェクトで書くのか
文章は検索できません。比較もできません。
// ❌ 検索できない
console.log("ユーザー123がログインしました");
console.log("ユーザー456がログインしました");
// ⭕ 検索できる
console.log({ action: "login", userId: 123 });
console.log({ action: "login", userId: 456 });
後者なら、action: "login" で絞り込めます。特定のユーザーだけを追跡することもできます。
ログレベルについて
console.log({ level: "info", action: "startProcess" });
console.log({ level: "warn", action: "retry", count });
console.log({ level: "error", action: "saveFailed", error });
levelは「重要度」ではなく、あとで絞り込むためのタグです。
エラーだけ見たいとき、警告だけ見たいとき、フィルタで一発です。
構造化ログがあると何が変わるか
Before(ログなし)
- バグが再現できない
- 記憶に頼る
- 「たぶんこうだった」という会話が続く
After(構造化ログあり)
- 状態が一発で見える
- 条件が分かる
- 修正が一点突破になる
「調査」が「確認」に変わります。
いつ・どこにログを書くべきか
初心者向けルール
ログを書く場所は3つだけです。
- 分岐の直前
- 外部との境界(API / DB)
- 失敗したとき
// 1. 分岐の直前
console.log({ step: "beforeIf", value });
if (value > 100) {
// ...
}
// 2. 外部との境界
console.log({ step: "beforeFetch", url });
const res = await fetch(url);
console.log({ step: "afterFetch", status: res.status });
// 3. 失敗したとき
try {
await saveData();
} catch (err) {
console.log({
step: "saveFailed",
error: err.message,
data: data
});
}
これだけで十分戦えます。
ログは未来の自分への手紙
ログは上司のためじゃありません。
ユーザーのためでもありません。
3日後の自分を救うためのメモです。
未来の自分は他人です。今のあなたが何を考えていたか、覚えていません。しかもめっちゃ機嫌が悪い可能性が高いです。
だから、説明できるように書いてください。
// ❌ 自分にしか分からない
console.log({ x: true });
// ⭕ 未来の自分に伝わる
console.log({ isUserAuthenticated: true });
チェックリスト
ログを書く前に、自分に聞いてください。
- 文章じゃなくデータか?
- 状態が分かるか?
- 後から再現できるか?
- 比較できるか?
全部YESならOKです。
まとめ
- ログは守ってくれる
- ログは攻めさせてくれる
- ログは裏切らない
だから、こう言えます。
神より信頼できるのはログ
特に、構造化されたログ
ログは「後から原因を探すためのもの」ではありません。
最初から真実を残すためのものです。
最後に
コードは壊れる。
記憶は歪む。
でもログは残る。
だから今日から、ログを書きましょう。
ログを書け。未来の自分を助けろ。