1
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?

【Google Cloud】Cloud Run FunctionsでChatwork通知を自動化する方法(完全版)

Posted at

この記事では、GCPのCloud Loggingで検知したエラーログを、Pub/SubとCloud Run Functionsを経由してChatworkに自動通知するシステムの構築方法を解説します。

システム構成

前提条件

  • GCPプロジェクトが作成済み
  • Chatworkアカウントを持っている
  • GCP Consoleへのアクセス権限がある

利用するGCPサービス

  • Cloud Logging(ログ収集・フィルタリング)
  • Pub/Sub(メッセージキュー)
  • Cloud Run Functions(サーバーレス実行環境)
  • Secret Manager(認証情報管理)
  • Eventarc(イベント駆動型トリガー)

セットアップ手順

全体の流れは以下の6ステップです:

  1. Chatwork準備(APIトークン、Room ID取得)
  2. Pub/Sub Topic作成
  3. ログシンク作成
  4. Secret Manager設定
  5. Cloud Run Functions作成・デプロイ
  6. テスト・動作確認

Step 1: Chatwork準備

1-1. APIトークンの取得

  1. Chatworkにログイン
  2. 右上のアイコン → サービス連携 をクリック
  3. 左メニューから API Token を選択
  4. 新しいトークンを発行する をクリック
  5. 表示されたAPIトークンをコピーして保存

APIトークンは一度しか表示されません。必ず安全な場所に保存してください。

1-2. Room IDの取得

  1. 通知を送りたいチャットルームを開く
  2. ブラウザのURLを確認:https://www.chatwork.com/#!rid123456789
  3. rid の後の数字(例: 123456789)がRoom ID

取得した情報をメモしておきましょう:

  • APIトークン: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
  • Room ID: 123456789

Step 2: Pub/Sub Topic作成

2-1. GCP Consoleでの操作

  1. GCP Console にアクセス
  2. ナビゲーションメニュー → Pub/Sub を選択
  3. プロジェクト test-logging を選択

2-2. トピック作成

トピック作成 ボタンをクリックし、以下を設定:

項目 設定値
トピック ID error-log-notifications
デフォルトのサブスクリプションを追加 チェックなし
暗号化 Google管理の暗号鍵(デフォルト)

pub_sub.png

その他の設定はデフォルトのまま 作成 をクリック。


Step 3: ログシンク作成

3-1. ログルーター画面を開く

  1. ナビゲーションメニュー → ロギングログ ルーター を選択
  2. シンクを作成 をクリック

3-2. シンクの設定

シンクの詳細

項目 設定値
シンク名 error-log-sink
シンクの説明 ERRORレベル以上のログをPub/Subに転送

シンクの送信先

項目 設定値
シンク サービス Cloud Pub/Sub トピック
トピック projects/test-logging/topics/error-log-notifications

ログフィルタ

severity >= ERROR

このフィルタでERROR、CRITICAL、ALERTレベルのログのみを転送します。

log-sink.png

シンクを作成 をクリック。

3-3. 権限付与(重要)

シンク作成後、Pub/Subへの書き込み権限を付与する必要があります。

Cloud Shellを開いて以下を実行:

# ログシンクのwriterIdentityを取得
WRITER_IDENTITY=$(gcloud logging sinks describe error-log-sink \
    --project=test-logging \
    --format="value(writerIdentity)")

echo "Writer Identity: $WRITER_IDENTITY"

# Pub/Subトピックに権限付与
gcloud pubsub topics add-iam-policy-binding error-log-notifications \
    --member="${WRITER_IDENTITY}" \
    --role='roles/pubsub.publisher' \
    --project=test-logging

権限付与が成功すると、Updated IAM policy for topic [error-log-notifications] と表示されます。


Step 4: Secret Manager設定

4-1. Secret Manager APIの有効化

  1. ナビゲーションメニュー → セキュリティSecret Manager を選択
  2. 初回の場合、APIを有効にする をクリック

4-2. シークレット作成

Chatwork APIトークン

シークレットを作成 をクリックし、以下を設定:

項目 設定値
名前 chatwork-api-token
シークレットの値 (Step 1で取得したAPIトークン)

Chatwork Room ID

同様に、もう1つシークレットを作成:

項目 設定値
名前 chatwork-room-id
シークレットの値 (Step 1で取得したRoom ID)

Step 5: Cloud Run Functions作成・デプロイ

5-1. Cloud Functions APIの有効化

  1. ナビゲーションメニュー → Cloud Run functions を選択
  2. 初回の場合、APIを有効にする をクリック

5-2. 関数作成

関数を作成 をクリックし、基本設定を行います。

基本設定

項目 設定値
関数名 chatwork-notifier-function
リージョン asia-northeast1
ランタイム Node.js 24
トリガーのタイプ Pub/Sub トリガー

Eventarcトリガー設定

1.Eventarc APIの有効化

  1. ナビゲーションメニュー → Eventarc を選択
  2. 初回の場合、APIを有効にする をクリック

基本設定

項目 設定値
トリガーの名前 pubsub-to-chatwork-trigger
トリガーのタイプ Google のソース
イベント プロバイダ Cloud Pub/Sub
イベント タイプ google.cloud.pubsub.topic.v1.messagePublished
Pub/Subトピック projects/test-logging/topics/error-log-notifications
リージョン asia-northeast1
サービス アカウント Default compute service account

警告が表示された場合は 付与 ボタンをクリックして権限を自動付与してください。

Eventarc.png

トリガーを保存 をクリック。

シークレット設定

シークレットと環境変数 タブで、以下の2つを追加:

1つ目:

  • 参照するシークレット: chatwork-api-token
  • 参照方法: 環境変数として公開
  • バージョン: latest
  • 環境変数: CHATWORK_API_TOKEN

2つ目:

  • 参照するシークレット: chatwork-room-id
  • 参照方法: 環境変数として公開
  • バージョン: latest
  • 環境変数: CHATWORK_ROOM_ID

設定完了後、次へ をクリック。

5-3. コード入力

package.json

{
  "name": "chatwork-notifier-function",
  "version": "1.0.0",
  "main": "index.js",
  "dependencies": {
    "@google-cloud/functions-framework": "^3.3.0",
    "axios": "^1.6.2"
  },
  "engines": {
    "node": ">=18"
  }
}

index.js

const functions = require('@google-cloud/functions-framework');
const axios = require('axios');

// CloudEventハンドラー
functions.cloudEvent('chatworkNotifierFunction', async (cloudEvent) => {
  try {
    console.log('Received CloudEvent:', JSON.stringify(cloudEvent, null, 2));

    // Pub/Subメッセージのデコード
    const base64Data = cloudEvent.data.message.data;
    const messageData = Buffer.from(base64Data, 'base64').toString('utf-8');
    const logEntry = JSON.parse(messageData);

    console.log('Log entry:', JSON.stringify(logEntry, null, 2));

    // ログ情報の抽出
    const severity = logEntry.severity || 'UNKNOWN';
    const timestamp = logEntry.timestamp || '';
    const resource = logEntry.resource || {};
    const textPayload = logEntry.textPayload || '';
    const jsonPayload = logEntry.jsonPayload || {};
    const logName = logEntry.logName || '';

    // リソース情報
    const resourceType = resource.type || 'unknown';
    const resourceLabels = resource.labels || {};
    const projectId = resourceLabels.project_id || 'unknown';
    const serviceName = resourceLabels.service_name || resourceLabels.function_name || 'unknown';

    // エラーメッセージの取得
    const errorMessage = textPayload || jsonPayload.message || JSON.stringify(jsonPayload) || 'No message';

    // Chatworkメッセージの構築
    const chatworkMessage = buildChatworkMessage(
      severity,
      timestamp,
      projectId,
      serviceName,
      resourceType,
      errorMessage,
      logName
    );

    // Chatworkに送信
    await sendToChatwork(chatworkMessage);

    console.log('Successfully sent notification to Chatwork');

  } catch (error) {
    console.error('Error processing CloudEvent:', error);
    throw error;
  }
});

/**
 * Chatwork用のメッセージを構築
 */
function buildChatworkMessage(severity, timestamp, projectId, serviceName, resourceType, errorMessage, logName) {
  // 絵文字を選択
  const emoji = severity === 'ERROR' ? '🚨' : severity === 'CRITICAL' ? '🔥' : '⚠️';

  // タイムスタンプを読みやすく整形
  const displayTime = timestamp.replace('T', ' ').replace('Z', ' UTC');

  // エラーメッセージを500文字に制限
  const truncatedMessage = errorMessage.length > 500 
    ? errorMessage.substring(0, 500) + '...' 
    : errorMessage;

  const message = `[info][title]${emoji} エラー検知 - ${severity}[/title]
【プロジェクト】${projectId}
【サービス】${serviceName}
【リソースタイプ】${resourceType}
【時刻】${displayTime}

【エラー内容】
${truncatedMessage}

【ログ名】
${logName}
[/info]`;

  return message;
}

/**
 * Chatwork APIにメッセージを送信
 */
async function sendToChatwork(message) {
  const apiToken = process.env.CHATWORK_API_TOKEN;
  const roomId = process.env.CHATWORK_ROOM_ID;

  if (!apiToken || !roomId) {
    throw new Error('CHATWORK_API_TOKEN or CHATWORK_ROOM_ID not set');
  }

  const url = `https://api.chatwork.com/v2/rooms/${roomId}/messages`;

  try {
    const response = await axios.post(
      url,
      `body=${encodeURIComponent(message)}`,
      {
        headers: {
          'X-ChatWorkToken': apiToken,
          'Content-Type': 'application/x-www-form-urlencoded'
        }
      }
    );

    console.log('Chatwork API response:', response.data);
    return response.data;

  } catch (error) {
    console.error('Chatwork API error:', error.response?.data || error.message);
    throw error;
  }
}

5-4. デプロイ

デプロイ ボタンをクリックし、完了を待ちます(2〜3分)。

関数一覧に chatwork-notifier-function が表示され、緑のチェックマークが付けば成功です。


Step 6: テスト・動作確認

6-1. テストログ送信

Cloud Shellで以下を実行:

# プロジェクト設定
gcloud config set project test-logging

# テストログ送信
gcloud logging write test-error \
    "Test ERROR: Chatwork notification test from Cloud Shell" \
    --severity=ERROR \
    --project=test-logging

成功すると Created log entry. と表示されます。

6-2. ログ確認

Cloud Functionsのログ

gcloud functions logs read chatwork-notifier-function \
    --gen2 \
    --region=asia-northeast1 \
    --limit=30 \
    --test-logging

以下のようなログが表示されればOK:

LEVEL: INFO
LOG:   Received CloudEvent: {...}

LEVEL: INFO
LOG:   Log entry: {"severity":"ERROR",...}

LEVEL: INFO
LOG:   Chatwork API response: {"message_id":"..."}

LEVEL: INFO
LOG:   Successfully sent notification to Chatwork

GCP Consoleでの確認

  1. Cloud Run functions → chatwork-notifier-functionログ タブ
  2. 最新のログを確認

6-3. Chatwork通知確認

指定したChatworkルームを開き、以下のような通知が届いていることを確認:

エラーテンプ-ト.jpg


トラブルシューティング

通知が届かない場合

1. Cloud Functionsのエラーログを確認

gcloud functions logs read chatwork-notifier-function \
    --gen2 \
    --region=asia-northeast1 \
    --limit=50 \
    --project=test-logging | grep -i error

よくあるエラーと対処法:

エラーメッセージ 原因 対処法
CHATWORK_API_TOKEN not set Secret Managerの設定漏れ Step 4とStep 5-2を再確認
status code 401 APIトークンが無効 Chatworkでトークンを再発行
status code 404 Room IDが間違っている Room IDを再確認

Cloud Functionsが起動しない場合

Eventarcトリガーの状態確認

Eventarc → pubsub-to-chatwork-trigger でステータスが アクティブ になっているか確認

Pub/Subの権限確認

gcloud pubsub topics get-iam-policy error-log-notifications \
    --project=test-logging

service-XXXXX@gcp-sa-pubsub.iam.gserviceaccount.comroles/iam.serviceAccountTokenCreator があることを確認

ログがPub/Subに届かない場合

ログシンクの権限確認

# ログシンクの状態確認
gcloud logging sinks describe error-log-sink \
    --project=test-logging

# Pub/Subトピックの権限確認
gcloud pubsub topics get-iam-policy error-log-notifications \
    --project=test-logging

service-XXXXX@gcp-sa-logging.iam.gserviceaccount.comroles/pubsub.publisher があることを確認

権限がない場合は、Step 3-3を再実行してください。


まとめ

本記事では、GCPのCloud LoggingからChatworkへの自動通知システムを構築しました。


参考リンク

1
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
1
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?