Cloud Pub/SubのBigQuery Subscriptionでエラー内容を取得できるようになった話

ZOZO Advent Calendar 2023 23日目の記事になります。

これまでCloud Pub/SubのBigQuery SubscriptionにDead-letter topicを設定した際、Dead-letter topicに書き込まれた場合のエラー詳細を取得できませんでした。 例としてDead-letter topicに書き込まれた際、下記attributeが書き込まれます。何回書き込みに失敗したかはわかりますが、エラー内容についてはattributeへ書き込まれていません。

{
  "CloudPubSubDeadLetterSourceDeliveryCount": "5",
  "CloudPubSubDeadLetterSourceSubscription": "hoge",
  "CloudPubSubDeadLetterSourceSubscriptionProject": "project",
  "CloudPubSubDeadLetterSourceTopicPublishTime": "2023-07-19T04:09:56.723+00:00",
  "googclient_schemaencoding": "JSON",
  "googclient_schemaname": "projects/project/schemas/sample",
  "googclient_schemarevisionid": "11111"
}

12月時点でDead-letter topicに書き込まれたメッセージを確認すると、CloudPubSubDeadLetterSourceDeliveryErrorMessageが新しく追加され、BigQueryのテーブル書き込み時のエラーを確認できるようになりました。

{
  "CloudPubSubDeadLetterSourceDeliveryCount": "5",
  "CloudPubSubDeadLetterSourceDeliveryErrorMessage": "Error Detail",
  "CloudPubSubDeadLetterSourceSubscription": "hoge",
  "CloudPubSubDeadLetterSourceSubscriptionProject": "project",
  "CloudPubSubDeadLetterSourceTopicPublishTime": "2023-12-21T17:05:38.712+00:00",
  "googclient_schemaencoding": "JSON",
  "googclient_schemaname": "projects/project/schemas/sample",
  "googclient_schemarevisionid": "1111"
}

jsonデータだけの説明だとどのような挙動かわからないため、試しに検証環境を準備して書き込まれるか確認します。

検証環境の準備

Topicの作成

メッセージをPublishするTopicとDead-letter topic用のTopicを作成します。

メッセージをPublishするTopicをsample-topic、Dead-letter topic用のTopicをdeadletter-topicと名付けて作成します。

Tableの作成

下記テーブルスキーマhogehogeというテーブルを作成します。

{
   "fields":[
      {
         "name":"sample_timestamp",
         "type":"TIMESTAMP",
         "mode":"NULLABLE"
      }
   ]
}

BigQuery Subscriptionの作成

下記設定でBigQuery Subsciptionを作成します。正常時はBigQueryに作成したテーブル(hogehoge)へ書き込まれるようにし、エラー時はDead-letter topic(deadletter-topic)へ書き込まれます。

動作確認

正常系のメッセージと異常系のメッセージをそれぞれPublishし、Dead-letter topicへ書き込まれた際の挙動を確認します。

正常系のメッセージ

下記jsonデータをtopicへPublishします。

{
   "sample_timestamp":"2023-12-23 10:00:00"
}

BigQuery Subscriptionに紐づいているテーブルを確認すると、きちんと書き込まれていることが確認できます。

異常系のメッセージ

次に下記jsonデータをtopicへPublishします。BigQueryのテーブルスキーマはtimestamp型なのでこのjsonデータはBigQueryへ書き込まれずDead-letter topicへ書き込まれるはずです。

{
   "sample_timestamp":"aaaaaaaa"
}

下記コマンドを実行し、Dead-letter topicに紐づいているSubscriptionを確認します。

gcloud pubsub subscriptions pull deadletter-subscription --format=json

上記コマンドを実行し、取得できたjsonデータは下記になります。CloudPubSubDeadLetterSourceDeliveryErrorMessageにBigQueryへinsertできなかった原因が書き込まれていることがわかります。

{
  "ackId": "",
  "message": {
    "attributes": {
      "CloudPubSubDeadLetterSourceDeliveryCount": "5",
      "CloudPubSubDeadLetterSourceDeliveryErrorMessage": "Could not parse 'aaaaaaaa' as a timestamp. Required format is YYYY-MM-DD HH:MM[:SS[.SSSSSS]]",
      "CloudPubSubDeadLetterSourceSubscription": "bigquery-subscription",
      "CloudPubSubDeadLetterSourceSubscriptionProject": "",
      "CloudPubSubDeadLetterSourceTopicPublishTime": "2023-12-23T09:25:44.378+00:00",
      "googclient_schemaencoding": "JSON",
      "googclient_schemaname": "sample-schema",
      "googclient_schemarevisionid": ""
    },
    "data": "",
    "messageId": "",
    "publishTime": "2023-12-23T09:25:48.511Z"
  }
}

まとめ

BigQuery Subscriptionを利用し、Dead-letter topicへ送られたデータのエラー原因を取得できるようになっていました。BigQuery Subscriptionを利用しはじめた当初はエラー原因が取得できず都度データを再度Publishして検証する手間があったので非常にありがたいです…!