giip
SES案件登録
9分で読了

MQE 通知メッセージ登録ガイド

GIIP の通知キュー MQE は、SQL Server のテーブル tMQLog で動作します。本書では、メッセージをキューに投入する方法(コピーしてそのまま実行できる例)、レスポンスの読み方、そして送信先(メール・Slack)の設定方法を説明します。

🔔 MQE 通知設定画面へ移動 →

⚠️ 名前が似ている 2 つのパス

パス実体
/ja/guides/mq-config本ガイド文書
/ja/mq-configMQE 通知設定管理画面tMQENotificationConfig にメール受信者 / Slack ボットを登録する画面

GIIP に外部メッセージブローカーはありません。MQE は tMQLog テーブル 1 つをキューとして使い、送信ワーカーが定期的にこのテーブルを走査してメール / Slack へ送り出す構造です。他の文書や本ページの旧版で外部ブローカー製品・専用キュープロトコル・別途の通信ポートを前提とした説明を見たことがあっても、それは本システムの実際の構造ではありません。

📋 1 分でわかる要点

  1. メッセージ登録 = ストアドプロシージャ pApiMQLogPutbyAk の呼び出し。HTTP(giipApiJson)と T-SQL 直接実行の 2 経路があります。
  2. 認証は SK(Secret Key) です。パラメータ名は @ak / usertoken ですが、AK ではなく SK を渡します。
  3. メッセージが どの顧客(cSn)に入るかは SK が決めます。 cSn パラメータは存在しません。
  4. レスポンスの mqSn0 の場合は保存されていません(重複防止ゲート)。RstVal が 200 でも同じです。
  5. 実際の送信先(Slack ボットトークン / メール受信者)は /ja/mq-config 画面 で設定します。

🚀 メッセージ登録 — HTTP 経路

  • エンドポイント: https://giipfaw.azurewebsites.net/api/giipApiJson
  • メソッド: POST
  • Content-Type: application/x-www-form-urlencoded; charset=utf-8
フォーム項目
usertoken使用する SK。この値が対象顧客(cSn)を決定します。
text固定文字列 MQLogPut
jsondataメッセージ内容の JSON(下表参照)

内部では exec pApiMQLogPutbyAK N'<usertoken>', N'<jsondata>' が実行されます。

例 1 — ASCII 本文(bash + curl)

SK="YOUR_SECRET_KEY"

curl -s -X POST "https://giipfaw.azurewebsites.net/api/giipApiJson" \
  -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" \
  --data-urlencode "usertoken=${SK}" \
  --data-urlencode "text=MQLogPut" \
  --data-urlencode 'jsondata={"mqTo":"C0AAC08GBA6","mqSubject":"[MyApp] daily report 2026-09-16","mqBody":"processed 128 items","mqType":"SLACK"}'

実測レスポンス(2026-09-16):

{
  "RstMsg": "Success",
  "mqSn": "30326",
  "RstVal": "200"
}

例 2 — 日本語など非 ASCII 本文(必須パターン)

非 ASCII 文字をシェル引数で直接渡してはいけません。 Windows のシェルでは引数がシステムコードページに変換され、日本語がすべて ? になった状態で登録されることを実測しました(2026-09-16、mqSn 30324・30325)。リクエストボディを UTF-8 ファイルにして --data-binary @ファイル で送れば、そのまま保持されます(同日 mqSn 30326 で確認)。

SK="YOUR_SECRET_KEY"

# 1) メッセージ JSON を UTF-8 ファイルとして作成する
cat > /tmp/mq-payload.json <<'JSON'
{"mqTo":"C0AAC08GBA6","mqSubject":"[MyApp] 日次レポート 2026-09-16","mqBody":"本日の処理件数: 128 件","mqType":"SLACK"}
JSON

# 2) form-urlencoded ボディを UTF-8 ファイルとして作成する
node -e '
const fs = require("fs");
const jsondata = fs.readFileSync("/tmp/mq-payload.json", "utf8").trim();
const body = new URLSearchParams({
  usertoken: process.argv[1],
  text: "MQLogPut",
  jsondata
}).toString();
fs.writeFileSync("/tmp/mq-body.txt", body, "utf8");
' "$SK"

# 3) ファイルをそのまま送信する
curl -s -X POST "https://giipfaw.azurewebsites.net/api/giipApiJson" \
  -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" \
  --data-binary "@/tmp/mq-body.txt"

例 3 — Windows PowerShell

Invoke-RestMethod はこのエンドポイントで応答待ちのまま停止する事例が報告されているため、curl.exe を使います。

$sk = "YOUR_SECRET_KEY"
$json = '{"mqTo":"C0AAC08GBA6","mqSubject":"[MyApp] 日次レポート 2026-09-16","mqBody":"本日の処理件数: 128 件","mqType":"SLACK"}'

$body = "usertoken=" + [Uri]::EscapeDataString($sk) +
        "&text=MQLogPut" +
        "&jsondata=" + [Uri]::EscapeDataString($json)

$bodyFile = Join-Path $env:TEMP "mq-body.txt"
[System.IO.File]::WriteAllText($bodyFile, $body, (New-Object System.Text.UTF8Encoding $false))

curl.exe -s -X POST "https://giipfaw.azurewebsites.net/api/giipApiJson" `
  -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" `
  --data-binary "@$bodyFile"

🗄️ メッセージ登録 — T-SQL 直接経路

DB に直接アクセスできるバッチ / スケジューラであれば、SP を直接呼び出しても構いません。非 ASCII 文字を含む場合は文字列リテラルの先頭に N を必ず 付けます。

EXEC dbo.pApiMQLogPutbyAk
     @ak       = 'YOUR_SECRET_KEY',
     @jsondata = N'{"mqTo":"C0AAC08GBA6","mqSubject":"[MyApp] 日次レポート 2026-09-16","mqBody":"本日の処理件数: 128 件","mqType":"SLACK","mqFromName":"MyApp Batch"}';

実測結果(2026-09-16):

RstVal | RstMsg  | mqSn
200    | Success | 30323

🧾 jsondata 項目

キー必須型 / 長さ説明
mqSubject必須nvarchar(500)件名。重複防止ゲートの判定対象です。
mqBody必須nvarchar(max)本文
mqTo任意nvarchar(200)mqTypeSLACK なら Slack チャンネル ID(例: C0AAC08GBA6)、EMAIL なら受信メールアドレス
mqType任意varchar(16)省略時は EMAIL。大文字小文字は区別しません(DB 照合順序 SQL_Latin1_General_CP1_CI_AS)。運用で実際に使われている値は EMAIL / SLACK です。
mqFromEmail任意varchar(255)送信元メールアドレス
mqFromName任意nvarchar(100)送信者表示名

mqSubject または mqBody が無い場合は保存されず、次のレスポンスが返ります。

{
  "RstMsg": "Missing required fields (mqSubject, mqBody)",
  "mqSn": "0",
  "RstVal": "400"
}

mqTo を省略する場合

mqTo を空にすると、/ja/mq-config 画面に 同じ mqType の有効な設定が登録されている場合にのみ 送信対象になります。設定が無ければメッセージは保存されるものの 永久に送信されません。 本番 DB には実際にそのようなメッセージが残っています(cSn 47、mqTo NULL、mqType email、2026-02-05 登録以降未送信)。確実を期すなら mqTo を明示してください。

📨 レスポンスの読み方

RstValmqSn意味対処
2001 以上キューに保存された正常
2000重複防止ゲートにより破棄RstMsgSkipped: ...件名を変えて再登録する
4000mqSubject または mqBody の欠落必須項目を埋めて再呼び出し
5000SP 内部例外。RstMsg に SQL エラーメッセージエラーメッセージに従って対処

結果が 1 件のときレスポンスは 配列ではなく単一オブジェクト で返ります。配列のみを処理する実装は、正常レスポンスを「結果なし」と誤認します。

🔴 必ず押さえるべき 3 つの落とし穴

1. @ak / usertoken は AK ではなく SK

pApiMQLogPutbyAk の内部は次のとおりです。

-- treating @ak as sk for this context
SELECT @cSn = csn FROM tSecretKey WITH(NOLOCK) WHERE skey = @ak;

AK を渡すと @cSn が NULL になり、どの顧客にも属さないメッセージが作られて送信されません。cSn をパラメータで指定する方法はありません。 特定の顧客に送るには、その顧客の SK を使う必要があります。

2. 同じ件名を再送すると黙って破棄される

SP には次のゲートがあります。

IF EXISTS (
    SELECT 1 FROM tMQLog WITH(NOLOCK)
    WHERE mqSentdt IS NULL
      AND mqSubject = @mqSubject
      AND mqTo      = @mqTo
      AND cSn       = @cSn
)
BEGIN
    SELECT 200 AS RstVal, N'Skipped: Identical unsent message already exists' AS RstMsg, 0 AS mqSn;
    RETURN;
END

つまり 同じ件名 + 同じ送信先 + 同じ顧客の未送信メッセージが 1 件でもあれば、新しいメッセージは保存されないのに成功(RstVal=200)のように応答します。実測(2026-09-16):

{
  "RstMsg": "Skipped: Identical unsent message already exists",
  "mqSn": "0",
  "RstVal": "200"
}

回避策: 繰り返し送信するものは件名に日付(または時刻)を入れます。

  • 悪い例: 日次コストレポート
  • 良い例: [Azure Cost] 日次コストレポート - 2026-09-16

呼び出し側の必須処理: レスポンスの mqSn が 0 なら送信されていないのでログに残してください。RstVal だけを見て成功扱いにすると、障害が静かに埋もれます。

3. 送信されずに残ったメッセージは、その件名を永久に塞ぐ

ゲートの判定対象は 未送信メッセージ です。送信先設定が無いために送信できなかったメッセージがキューに残っていると、同じ件名の新しいメッセージはその後ずっとスキップされ続けます。件名がスキップされ続ける場合は次を確認してください。

SELECT mqSn, cSn, mqType, mqTo, mqSubject, mqRegdt, mqRetryCnt, mqErrMsg
FROM tMQLog
WHERE mqSentdt IS NULL
ORDER BY mqRegdt;

🖥️ 設定画面の使い方(/ja/mq-config

この画面は MQE 通知設定管理 画面で、tMQENotificationConfig に顧客ごとの送信先を登録します。ブローカー接続設定の画面ではありません。

一覧には ID、タイプ、受信者 / チャンネル、優先度、状態、説明、アクションの列があり、各行に 編集 / テスト / 削除 ボタンがあります。

新規設定の追加

  1. [➕ 新規設定追加] を押します。
  2. メッセージタイプemail または slack から選びます。(保存後にタイプは変更できません。)
  3. タイプ別の項目を入力します。

email を選んだ場合

項目必須説明
受信者 (To)必須カンマ(,)区切りで複数指定可。例: admin@company.com, ops@company.com
CC任意例: manager@company.com
BCC任意例: backup@company.com

slack を選んだ場合

項目必須説明
Bot Token必須Slack App の Bot User OAuth Token。xoxb- で始まります。
Channel ID必須チャンネルを右クリック →「リンクをコピー」→ URL の最後の部分。例: C0AAC08GBA6
チャンネル名任意表示用。例: #alerts-production
  1. 優先度(1〜10、小さいほど先に送信)、有効化 チェックボックス、説明 を入力します。
  2. [保存] を押します。

テスト送信

行の [テスト] ボタンを押すと、その設定のままテストメッセージをキューに入れます。成功するとダイアログが表示され、失敗時は失敗理由が表示されます。

Slack の注意: Bot Token と Channel ID が正しくても、チャンネルにボットを招待しないと送信されません。 招待方法は Slack ボット設定ガイド を参照してください。

🔎 登録・送信の確認

GIIP には tMQLog を直接表示する画面がありません。登録結果は DB 照会で確認します。

SELECT TOP 10 mqSn, cSn, mqType, mqTo, mqSubject, mqRegdt, mqSentdt, mqRetryCnt, mqErrMsg
FROM tMQLog
WHERE cSn = 47          -- 確認する顧客番号
ORDER BY mqSn DESC;
  • mqSentdtNULL ならまだ送信待ちです。
  • 実測(2026-09-16)では登録から送信まで概ね 2 秒〜7 分 です。送信ワーカーが数分間隔のバッチで動作するためです。
  • mqRetryCnt が 3 で mqErrMsg が入っていれば、リトライ上限(3 回)を使い切った状態です。

❗ トラブルシューティング

症状原因解決
RstVal=200 なのに mqSn=0同じ件名・送信先・顧客の未送信メッセージが既にある件名に日付 / 時刻を入れて一意にする
RstVal=400 Missing required fieldsmqSubject または mqBody の欠落両方の項目を埋める
登録できたが何時間経っても mqSentdt が NULLmqTo が空で、その mqType の有効な送信先設定も無いmqTo を明示するか、/ja/mq-config にそのタイプの設定を追加する
日本語の件名・本文が ???? で保存され、送信もされない(mqErrMsgMOJIBAKE: ...mqRetryCnt が上限到達)非 ASCII 文字をシェル引数で直接渡した。送信ワーカーが壊れた本文を検知して送信を拒否するリクエストボディを UTF-8 ファイルにして --data-binary @ファイル で送る(例 2)。壊れた行は復旧できないので件名を変えて新規登録する
メッセージが意図しない顧客に入るSK が意図した顧客のものではないcSn は SK で決まる。対象顧客の SK を使う
mqRetryCnt=3mqErrMsgaccount_inactive などSlack ボット / メールアカウントの問題で 3 回リトライ失敗/ja/mq-config でトークン・受信者を修正し、新しいメッセージを登録する

🔗 関連文書


バージョン: 2.0 最終更新: 2026-09-16 ソースファイル: giipv3/public/help/mq-config.ja.md