MQE 通知メッセージ登録ガイド
GIIP の通知キュー MQE は、SQL Server のテーブル tMQLog で動作します。本書では、メッセージをキューに投入する方法(コピーしてそのまま実行できる例)、レスポンスの読み方、そして送信先(メール・Slack)の設定方法を説明します。
⚠️ 名前が似ている 2 つのパス
| パス | 実体 |
|---|---|
/ja/guides/mq-config | 本ガイド文書 |
/ja/mq-config | MQE 通知設定管理画面 — tMQENotificationConfig にメール受信者 / Slack ボットを登録する画面 |
GIIP に外部メッセージブローカーはありません。MQE は tMQLog テーブル 1 つをキューとして使い、送信ワーカーが定期的にこのテーブルを走査してメール / Slack へ送り出す構造です。他の文書や本ページの旧版で外部ブローカー製品・専用キュープロトコル・別途の通信ポートを前提とした説明を見たことがあっても、それは本システムの実際の構造ではありません。
📋 1 分でわかる要点
- メッセージ登録 = ストアドプロシージャ
pApiMQLogPutbyAkの呼び出し。HTTP(giipApiJson)と T-SQL 直接実行の 2 経路があります。 - 認証は SK(Secret Key) です。パラメータ名は
@ak/usertokenですが、AK ではなく SK を渡します。 - メッセージが どの顧客(cSn)に入るかは SK が決めます。 cSn パラメータは存在しません。
- レスポンスの
mqSnが0の場合は保存されていません(重複防止ゲート)。RstValが 200 でも同じです。 - 実際の送信先(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) | mqType が SLACK なら 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 を明示してください。
📨 レスポンスの読み方
RstVal | mqSn | 意味 | 対処 |
|---|---|---|---|
| 200 | 1 以上 | キューに保存された | 正常 |
| 200 | 0 | 重複防止ゲートにより破棄(RstMsg が Skipped: ...) | 件名を変えて再登録する |
| 400 | 0 | mqSubject または mqBody の欠落 | 必須項目を埋めて再呼び出し |
| 500 | 0 | SP 内部例外。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、タイプ、受信者 / チャンネル、優先度、状態、説明、アクションの列があり、各行に 編集 / テスト / 削除 ボタンがあります。
新規設定の追加
- [➕ 新規設定追加] を押します。
- メッセージタイプ を
emailまたはslackから選びます。(保存後にタイプは変更できません。) - タイプ別の項目を入力します。
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〜10、小さいほど先に送信)、有効化 チェックボックス、説明 を入力します。
- [保存] を押します。
テスト送信
行の [テスト] ボタンを押すと、その設定のままテストメッセージをキューに入れます。成功するとダイアログが表示され、失敗時は失敗理由が表示されます。
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;
mqSentdtがNULLならまだ送信待ちです。- 実測(2026-09-16)では登録から送信まで概ね 2 秒〜7 分 です。送信ワーカーが数分間隔のバッチで動作するためです。
mqRetryCntが 3 でmqErrMsgが入っていれば、リトライ上限(3 回)を使い切った状態です。
❗ トラブルシューティング
| 症状 | 原因 | 解決 |
|---|---|---|
RstVal=200 なのに mqSn=0 | 同じ件名・送信先・顧客の未送信メッセージが既にある | 件名に日付 / 時刻を入れて一意にする |
RstVal=400 Missing required fields | mqSubject または mqBody の欠落 | 両方の項目を埋める |
登録できたが何時間経っても mqSentdt が NULL | mqTo が空で、その mqType の有効な送信先設定も無い | mqTo を明示するか、/ja/mq-config にそのタイプの設定を追加する |
日本語の件名・本文が ???? で保存され、送信もされない(mqErrMsg に MOJIBAKE: ...、mqRetryCnt が上限到達) | 非 ASCII 文字をシェル引数で直接渡した。送信ワーカーが壊れた本文を検知して送信を拒否する | リクエストボディを UTF-8 ファイルにして --data-binary @ファイル で送る(例 2)。壊れた行は復旧できないので件名を変えて新規登録する |
| メッセージが意図しない顧客に入る | SK が意図した顧客のものではない | cSn は SK で決まる。対象顧客の SK を使う |
mqRetryCnt=3、mqErrMsg に account_inactive など | Slack ボット / メールアカウントの問題で 3 回リトライ失敗 | /ja/mq-config でトークン・受信者を修正し、新しいメッセージを登録する |
🔗 関連文書
- MQE 技術仕様 — テーブルスキーマ、SP シグネチャ、送信パイプライン
- Slack ボット設定ガイド — Bot Token の発行とチャンネル招待
バージョン: 2.0
最終更新: 2026-09-16
ソースファイル: giipv3/public/help/mq-config.ja.md