「ポスモ」って呼んでます
こんにちは、 Smith (@do_low) です。
ドリコムの一部のプロジェクトでは、障害や深刻な不具合が発生した場合、そのポストモーテムを書いています。
ポストモーテム自体については様々なサイトで説明がなされているので詳細は省きますが、おおよその説明通り、発生してしまった問題から教訓を得て今後に活かすためのチームの取り組みとして実施しています。
テックブログは普通、イケてる技術的取り組みだったり、登壇報告だったりと、良いことばっかり書くものですが、 Tech Inside Drecom では、ドリコムの等身大のエンジニアリングをお伝えするため、また、ドリコムだけでなく読者の皆様も教訓を得られる機会を提供するため、共有できそうなポストモーテムは公開することにしました。
資料は可能な限り原文のまま記載していますが、人物名、プロジェクトコード、日付や時刻、仕様に関する情報は一部、ぼかしていたり改変していることもありますのでご了承ください。
本稿では 2本のポストモーテムを公開します。
本番デプロイしたら Apple Pay で決済できなくなった
この概要だけでも胃が痛くなりますね。
まずは本文を御覧ください。
20xx/xx/10
# 障害発生期間
20xx/xx/9 11時頃
該当のSDKデプロイ
~
20xx/xx/10 15時頃
デベロッパー側の本番メンテナンス終了後事象確認
~
20xx/xx/10 18時頃
収束
# 作者
xxxx事業本部 開発部
O.S
# レビュー
・M.J 済
・M.K 済
・H.Y
# ステータス
対応済み
# サマリ
iOSでApplePayを使用するボタンが押せない
ボタンのイベント発火の仕方がtouchstartイベントになってしまい、iOSでユーザーインタラクションではないという判定になり処理が止まってしまう
併せて、クレジットカード決済モーダルから決済方法を変更するボタンを押したときに1タップで変更モーダルが出て、その裏のApplePayボタンがクリックされたことになってしまう問題が出た
# インパクト
iOSのApplePayによる決済ができない
上記に関するエラーが39ユーザー/111件発生
# 根本原因
ApplePayの支払いがユーザーインタラクションと認識されないと不正と判定される考慮漏れ
# 発生原因
正常に判定できていなかったtouchデバイス判定を修正したため、押下イベントでは常にclickイベントが使われていたのが、touchデバイスでは、clickイベントからtouchstartイベントに変更されてしまいユーザインタラクションを求められる処理で不都合となってしまった。
結合テストのケース漏れ
課金処理の正常系のみの確認しかしていなかったため
# 対応
ボタンイベント発火方法をtouchstartイベントからclickイベントへの変更を行った
決済方法変更のボタンも同様の対応を行った
# 検出
デベロッパー側開発メンバーからのアラート
# アクションアイテム
## 1. 調査
対応者: O.S
エラー内容の確認
ユーザーインタラクションによる処理ではないというようなエラーだったため、該当ボタンのイベント処理の確認
## 2. 修正
対応者: O.S
イベントがtouchstartになっていたのでclickイベントへ変更
## 3. 確認
対応者: M.K
sandbox環境にて、charlesを使ってSDKをローカルのものと置き換えて検証
決済方法変更のボタンを押した際に、タップした瞬間にApplePayのモーダルが出てきて、タップを離すとApplePayのボタンがclickされたとこになり決済開始されてしまうバグが発覚
## 4. 修正によるバグの修正
対応者: O.S
ApplePayボタンと同様にイベントをtouchstartからclickへ変更
## 5. 反映
対応者: O.S
sandboxで確認後、本番反映を行う
# 教訓
## うまくいった事
バグの認知から速やかに修正を行うことができた
## うまくいかなかった事
Safariのブラウザキャッシュが効きすぎることがあり、問題解決後も数十分間に渡ってErrorが上がっており、混乱が起きた
SDKのエラーがSentryで拾えてなかった
問題発覚までの時間がかかってしまった
## 幸運だった事
ApplePayを確認できる人がいた
Guest課金ストーリー時に同じ現象を踏んでおり原因の特定が早かった
## 再発防止の為にできる事
テストケースの網羅
## タイムライン
20xx/xx/10 15:00
デベロッパー側本番環境にてバグの検知
20xx/xx/10 16:30
デベロッパー側チームからバグ報告を受ける
20xx/xx/10 17:00
原因調査
20xx/xx/10 17:10
修正対応開始
20xx/xx/10 17:40
修正sandbox反映・確認完了
20xx/xx/10 18:00
修正本番反映・確認完了
2018/10/10 18:30
収束
## 参考情報
特になし
解説
このプロジェクトは、Apple Pay 決済を導入している Web 向けのサービスで、決済周りを取り扱うライブラリを SDK と称して個別に開発・運用しており、外部デベロッパー様に導入いただいていますが、ポストモーテムで振り返っているのはその SDK のデプロイによって生じた問題です。
TouchEvent と MouseEvent の混入という、フロントエンド開発プロジェクトなら一度は経験していそうな罠が、本番での不具合に発展してしまったケースです。
幸いにも根深い問題ではなかったため対応は比較的迅速にできましたが、課金処理に近い部分を改修した場合、そのテストは厚めにやりましょうという教訓を再認識しました。
ポスモのポスモ
ポストモーテム関係者が改めてこの記事を読んで、このポストモーテムを振り返りました。
・M.J 済
・M.K 済
・H.Y
みたいになってて「え、済んでないやん」と思いましたw
次いで 2本目です。
ネイティブアプリからログインしてデータ連携するとサービスが利用不能になる
このポストモーテムが書かれたプロジェクトでは、サードパーティのデベロッパー様のコンテンツに対して、Web とネイティブアプリのクロスプラットフォームでのログインやデータ連携を可能にするアカウントサービスを提供しています。
このポストモーテムは、そのデータ連携部分で起こった問題についての振り返りです。
以下、本文です。
20xx-xx-04 20:00
# 障害発生期間
障害発生: 20xx-xx-03 11:40 ※デプロイ日時
対応完了: 20xx-xx-04 13:05
# 作者
開発部
H.T
# レビュー
N.H
# ステータス
対応完了済み
# サマリ
ネイティブアプリ版からログインして Web 版とデータ連携したアカウントのうち、デベロッパーコンテンツの利用登録をしていなかったアカウントは、自社アカウントサービスの API でアカウントの検索対象にならない。
# インパクト
データ連携後、デベロッパーコンテンツに戻るとまずコンテンツへのアカウント登録APIが叩かれるが、そこでエラーが発生してコンテンツ利用不能となる。
64名のユーザーで障害が発生し、9名から問い合せがあった。
# 根本原因
レビューとテストの不足
# 発生原因
実装時のデグレ。
ネイティブアプリ版から自社アカウントサービスにログインしたとき、ログイン先のアカウントが Web版でアカウントを作成していなければ、ネイティブアプリ版のアカウントをWeb版のアカウントへもデータ連携させている。
また、アカウントの検索は複数シャードから行う必要があり、アカウントサービスでは効率性向上のために アカウント ID を添え字としたキャッシュを持っている。
データ連携時に該当キャッシュをクリアするようにしていたが、処理が削除されてしまった。
このコードが取り込まれてしまったのはおそらくマージや rebase のミスが原因と思われる。
KPI 関連の作業ブランチに複数の PR をコミットしていき、それを 開発ブランチにマージするという流れで開発が進められていた。
キャッシュのクリア処理は次の PR のあるコミットで一度削除され、後のコミットで復活している。その PR 全体では削除されていないが、KPI関連のブランチにマージするときに削除するコミットのみが取り込まれてしまったように見える。
削除、復活のコミットを feature/new_kpi_viewer_vol2 ブランチへ
https://github.com/drecom/xxxx-api/pull/2796
(マージコミットで復活されているのがまずいのか? feature/new_kpi_viewer_vol2 ブランチには復活のコミットが入っていない)
feature/new_kpi_viewer_vol2 から開発ブランチへのマージ
https://github.com/drecom/xxxx-api/pull/2874/
# 対応
キャッシュの削除処理を復活させた。
合わせて削除されることのテストを追加した。
# 検出
https://kcw.kddi.ne.jp/#!ridxxxx-xxxxxxxx
20xx-xx-04 10:22
デベロッパー様からチャットワークでの問い合わせで発覚
# アクションアイテム、タイムライン
## No.1
2019-xx-04 10:25
H.T、A.N
https://kcw.kddi.ne.jp/#!ridxxxx-xxxxxxxx
問い合わせをうけ調査開始
## No.2
20xx-xx-04 10:43
H.T、A.N
https://kcw.kddi.ne.jp/#!ridxxxx-xxxxxxxx
アカウントIDを添え字としたキャッシュが壊れていること、
20xx-xx-03 の本番更新によるデグレであることを確認
## No.3
20xx-xx-04 11:11
H.T
https://kcw.kddi.ne.jp/#!ridxxxx-xxxxxxxx
状況と対応方針を連絡
## No.4
20xx-xx-04 11:23
N.H
hotfix 作成
https://github.com/drecom/xxxx-api/pull/2935
## No.5
20xx-xx-04 12:00
A.N
影響を受けたアカウントのオーダーを調査
## No.6
20xx-xx-04 12:35
N.H
sandboxにhotfixをデプロイ、テスト完了
## No.7
20xx-xx-04 13:00
N.H
本番環境にhotfixをデプロイ
## No.8
20xx-xx-04 13:06
H.T
手動で古いキャッシュを削除
各所に連絡
## No.9
20xx-xx-04 14:46
H.T
https://kcw.kddi.ne.jp/#!ridxxxx-xxxxxxxx
補填のために対象ユーザーの抽出依頼を受け作業開始
## No.10
20xx-xx-04 16:31
H.T
抽出完了
## No.11
20xx-xx-04 16:31
K.A
キャッシュ削除のテストを追加
https://github.com/drecom/xxxx-api/pull/2941
# 教訓
## うまくいった事
原因の把握と修正がすばやく実施できた
## うまくいかなかった事
デグレ
## 幸運だった事
データ連携に関するログを残していたため対象ユーザーの特定が可能だった
## 再発防止の為にできる事
大きいブランチを stable にマージするときは必要な approve 数を増やす。
テストを厚く書く。
## 参考情報
解説
ある単一のサービスをネイティブアプリからもWebからも共通のアカウントで利用できる、という仕組みは多く見られますが、このプロジェクトの場合は不特定多数のコンテンツで利用できる共通のアカウントサービスを提供しています。
「Google アカウントでログイン」 や 「Facebook でログイン」 のようなイメージです。
ただしこのアカウントサービスでは、アカウントを作成しなくてもネイティブアプリや Web版のコンテンツを利用できるように暗黙的に仮アカウントを作成できるため、仮アカウントで利用途中のコンテンツの状態を保ったまま、本アカウントの作成とデータ連携を行えるようにする必要がある、という複雑性を持っています。
そのため、プラットフォームを横断したデータ連携やログインのテストケースが複雑になり、そこに普段とは若干異なる開発上のオペレーションも重なったためにデグレが発生していました。
ポスモのポスモ
ポストモーテム関係者が改めてこの記事を読んで、このポストモーテムを振り返りました。
これちゃんと原因特定できてないの恥ずかしいけど
> ドリコムの等⾝⼤のエンジニアリングをお伝えするため
だからいいか
おわりに
本稿では、初めてドリコムのポストモーテムを公開してみましたがいかがでしたでしょうか。
どんな不具合や障害も、振り返ってみると単純なことが原因であることが多い反面、検知や防止については、動作確認を増やしたりテスト範囲を増やすなどの人力に頼ったり、テストコードの追加で機械的に検知したりと、方法は様々です。
ここで紹介した以外にもポストモーテムは多く書かれていますが、「これ、防ぎようあるのかな・・・」という感想を抱いてしまうものも散見されます。
個別のケースに対して最適な解がない場合もありますが、まずは過去に起こった問題を振り返って、読み手なりの感想や対処法を考えるなどするだけでも、ポストモーテムを残している意義があるのではないでしょうか。
本稿が少しでも読者の教訓になれば幸いです。
Tech Inside Drecom の最新の情報は Facebook や Twitter からお届けしています、フォローよろしくおねがいします!
- Twitter: @DRECOM_TECH
- Facebook: tech Inside Drecom