0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

未来の自分を助ける?不具合調査がラクになる構造化ログ設計(GCP)

0
Last updated at Posted at 2026-07-01

この記事の対象読者

  • 問い合わせ調査や運用調査を担当し始めた人
  • Cloud Loggingでログを見る機会があるけれど、検索の仕方にまだ慣れていない人
  • console.log("エラー") から少しだけ先に進みたい人

本題に入る前に

この話は、問い合わせ対応や運用調査でログを見る機会がある人、またはこれからログ設計に関わるWebエンジニアを想定しています。CSやサポートから「このユーザーで何が起きたか確認してほしい」と相談される立場の人にも役立つ内容です。

最近、業務アプリの運用を考える中で、「機能を作ること」と同じくらい「あとから何が起きたか分かること」が大事だと感じる場面が増えています。画面上ではただ「失敗しました」と見えていても、裏側では外部APIが遅かったのか、入力値が不正だったのか、権限で弾かれたのか、いろいろな可能性があります。

問い合わせを受けたときに、「このユーザーだけ」「この時間帯だけ」「この操作だけ」で見たいこと、ありますよね。ログが文章だけだと、目で追うしかなくなってつらいです。最初から検索しやすい形にしておくと、あとで自分を助けてくれます。

問い合わせを受ける側からすると、最初に欲しいのは完璧な原因ではなく、調査の入口です。「誰の操作か」「いつ起きたか」「どの処理か」が分かるだけでも、見るべき範囲はかなり狭くなります。この記事では、その入口を作るためのログ設計を扱います。

ログはあとから探すための作業メモ

Webサービスを運用していると、ユーザーや社内の担当者から「うまく動きません」「画面に反映されません」といった問い合わせが来ることがあります。

このとき、エンジニアはまず「本当にシステムで何が起きたのか」を確認します。相手の説明だけでは、通信エラーなのか、入力ミスなのか、外部サービス側の失敗なのか、まだ分かりません。

そこで見るのがログです。ログは、システムが裏側で残している作業メモのようなものです。飲食店でたとえるなら、注文が入った時刻、担当者、調理状況、エラーになった理由を厨房側で記録しておくイメージです。

ただし、メモが「なんか失敗した」だけだと後から探せません。「何時に」「誰の」「どの処理が」「どう失敗したか」が分かる形で残っていると、調査が一気に進めやすくなります。

Cloud Loggingは、そのログを集めて検索するためのGoogle Cloudのサービスです。そして構造化ログは、ログをただの文章ではなく、検索しやすい項目つきのデータとして残す考え方です。

ほかにもログを保存するサービスやライブラリはありますが、この記事ではGoogle Cloudを使う現場でよく出てくるCloud Loggingを例にします。大事なのはサービス名を覚えることより、「後から探すために、ログに項目を持たせる」という考え方です。

まずはJSONで1行出す

今回は架空の予約同期APIを例にします。

function writeLog(payload) {
  console.log(JSON.stringify(payload));
}

async function syncReservation({ userId, organizationId, requestId }) {
  const startedAt = Date.now();

  try {
    await new Promise((resolve) => setTimeout(resolve, 100));

    writeLog({
      severity: "INFO",
      message: "reservation_sync_succeeded",
      operation: "reservation_sync",
      status: "success",
      userId,
      organizationId,
      requestId,
      durationMs: Date.now() - startedAt,
    });
  } catch {
    writeLog({
      severity: "ERROR",
      message: "reservation_sync_failed",
      operation: "reservation_sync",
      status: "failure",
      errorCode: "UNKNOWN_ERROR",
      userId,
      organizationId,
      requestId,
      durationMs: Date.now() - startedAt,
    });
  }
}

syncReservation({
  userId: "user_001",
  organizationId: "org_001",
  requestId: "req_001",
});

ローカルではこう実行できます。

node reservation-sync.js

出力例です。

{"severity":"INFO","message":"reservation_sync_succeeded","operation":"reservation_sync","status":"success","userId":"user_001","organizationId":"org_001","requestId":"req_001","durationMs":101}

入れておくと探しやすい項目

最初から完璧なログ設計を目指さなくて大丈夫です。まずはこのあたりがあるだけで、問い合わせ調査がかなり進めやすくなります。

項目 使いどころ
operation どの処理かを絞る
status 成功か失敗かを見る
userId 問い合わせ対象のユーザーで探す
organizationId 組織やテナント単位で探す
requestId 1回のリクエストを追う
errorCode 同じ種類の失敗を探す
durationMs 遅い処理に気づく

Cloud Loggingでの検索例

Google Cloudでは、JSONで取り込まれたログを jsonPayload のフィールドとして検索できます。

予約同期の失敗だけ見たい場合です。

jsonPayload.operation="reservation_sync"
jsonPayload.status="failure"

特定ユーザーのログを見たい場合です。

jsonPayload.userId="user_001"

タイムアウト系のエラーだけ探したい場合です。

jsonPayload.errorCode="EXTERNAL_API_TIMEOUT"

ログがただの文章だけだと、毎回がんばって文字列検索することになります。JSONでキーを決めておくと、あとから落ち着いて絞り込めます。

注意したいこと

ログに何でも入れるのは避けます。

たとえば、認証トークン、APIキー、個人情報、メール本文、自由入力の本文などは、ログに出す前に本当に必要か確認したほうが安全です。

問い合わせ調査では「誰の、どの処理で、どんな種類の失敗が起きたか」まで分かれば十分なことも多いです。まずはIDとエラー種別を残すところから始めるのがよいと思います。

まとめ

構造化ログは、特別な監視基盤を作る前に始められる小さな改善です。

ログを見る未来の自分やチームメンバーが、userIdoperation で検索できるようにしておく。それだけでも、問い合わせ調査の最初の一歩がかなり楽になります。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?