平均 80ms なのに照会画面は 3 秒ずつ止まった
目標
あいまいな顧客の文を、測定できる基準表に移し、基準表を読んでリクエストを送り、証拠と判定を残す受け入れテストの実行ツールを作ります。正常なビルドだけを受け入れ、欠陥のあるビルドは、該当する基準で不合格にしなければなりません。
なぜ重要なのか
「速く」は、平均でもp95でも測れ、p95も、計算方法によって値が変わります。何をどう測るのかまで合意しないと、納品のあとで、同じ数字を前にして違うことを言うことになります。 基準値をコードに書くと、基準が変わった日に、実行ツールが静かに間違います。判定だけで証拠がない報告書は、顧客が検証できません。 採点ツールは、ダミーの見積もりサーバーを自分のポートで立ち上げ、テールが遅い・ときどき止まったり500を返したりする・金額が1ウォン間違っている・再照会が揺らぐビルドを作り、基準値・ケース表・変わるフィールド名を毎回変えて、あなたの実行ツールを動かしたあと、証拠から指標を計算し直して、報告書と照合します。
想定所要時間は60分です。デフォルトのセッションが終わる前に、+時間で延長してください(最大180分)。セッションが終わると、/rootのファイルは消えるので、コードは別に保管してください。
ステップ
- 顧客のメールと議事録を読み、合意した基準を記録します(ファイル: /root/accept/criteria.json)。購買チームのリーダーの最初の希望の数字ではなく、会議で合意した数字と測定条件を書きます。
- accept.pyが、基準表のpassesの回数だけケース表を照会してsamples.jsonlを残し、p95_ms(nearest-rank)の基準を判定して、report.jsonと終了コード0・1を出すようにします(ファイル: /root/accept/accept.py)。
- accept.pyに、error_rateを入れます。200ではない応答と、timeout_ms以内に届かなかった応答を、エラーと数え、証拠のstatusに「timeout」を残します。
- accept.pyに、mismatchesを入れます。1回目で200を受け取ったケースだけを、expected_totalと比べ、間違ったケースのidをmismatched_casesとして残します。
- accept.pyに、rerun_diffsを入れます。1・2回目がどちらも200のケースを、基準表のignore_fieldsを除いた本文で比べ、rerun_diff_casesを残します。
- 4つの基準をあわせて使う基準表で、op(<, <=, ==)にそのまま従い、報告書のobserved・pass・metricsが、証拠から計算し直した値と同じになるようにします。
- 新しく変わった基準表で、候補5つ(正常・遅いテール・ときどき500・間違った金額・揺らぐ再照会)を動かして、正常なものだけが受け入れられるかを確認します。
- 顧客の候補rc2を
python3 /opt/lab/p1a-criteria/quote_server.py --port 8095 --build rc2で起動し、criteria.jsonと提供されたケース表で実行して、report.jsonとsamples.jsonlを残します(保存先: /root/accept/rc2/)。
参考
- 用意するもの: 顧客の要望 /opt/lab/p1a-criteria/customer-request.md、実行契約 /opt/lab/p1a-criteria/CONTRACT.md、ケース表 /opt/lab/p1a-criteria/cases.csv、ダミーのサーバー /opt/lab/p1a-criteria/quote_server.py
- 練習用のサーバー: python3 /opt/lab/p1a-criteria/quote_server.py --port 18095 --build rc1 &(正常な候補)。終わったら、そのPIDだけを選んで停止します。
- 直接の実行: python3 /root/accept/accept.py --criteria /root/accept/criteria.json --cases /opt/lab/p1a-criteria/cases.csv --base-url http://127.0.0.1:18095 --out /tmp/run1; echo $?
- よくある間違い: 平均やstatistics.quantilesのデフォルトでp95を計算する、ウォームアップ・再試行のリクエストを混ぜる、エラー応答を、間違った金額としても数える、変わるフィールド名をコードに書く、基準値をコードに書く。
- このサーバーのアドレスは、採点ツールは使いません。採点ツールは、毎回自分のサーバーを新しく立ち上げます。
形容詞4つを数字4つにする
顧客の文4つごとに、metric・op・threshold・sourceを決めて、timeout_ms・passes・ignore_fieldsとあわせて記録してください(ファイル: /root/accept/criteria.json)。
議事録には、最初に出た希望の数字と、最終的な合意が混ざっています。パーセントは比率(小数)で、時間はmsの整数で書きます。sourceには、その基準が出てきた顧客の文を書きます。
平均ではなくp95で、遅いテールを捕まえる
ケース表をpasses回照会してsamples.jsonlを残し、p95_msの基準を判定するようにしてください(ファイル: /root/accept/accept.py)。
リクエストごとに、time.perf_counterで測ったmsを残し、すべてのリクエストのmsを並べ替えて、ceil(0.95 × n)番目の値を選びます。statistics.quantilesのデフォルトは補間なので、別の値が出ます。リクエスト数は、正確にpasses × ケース数です。
届かなかった応答もエラーと数える
error_rateを入れて、200ではない応答とtimeout_msの超過を、エラーと数えるようにしてください(ファイル: /root/accept/accept.py)。
urlopenのtimeout引数に、基準表のtimeout_msを、秒の単位で渡します。HTTPErrorは、状態コードがある応答で、タイムアウトは、TimeoutError・URLErrorで来ます。証拠のstatusには、timeoutを文字列で残します。
1ウォン間違った金額を見つける
mismatchesを入れて、1回目の200の応答のtotalをexpected_totalと比べ、mismatched_casesを残すようにしてください(ファイル: /root/accept/accept.py)。
CSVのexpected_totalは文字列なので、整数に変えて比べます。エラー応答は、すでにエラー率で数えたので、金額の比較からは除きます。1つの問題を2つの基準で二重に数えると、どの基準が原因なのかがあいまいになります。
2回照会して、揺らぐケースを見つける
rerun_diffsを入れて、基準表のignore_fieldsを除いた1・2回目の本文を比べ、rerun_diff_casesを残すようにしてください(ファイル: /root/accept/accept.py)。
request_idのようなフィールド名をコードに書くと、採点ツールがフィールド名を変えた瞬間に、正常なビルドが不合格になります。辞書から、基準表のフィールドだけを除いて比べてください。
報告書が証拠と同じか、自分で合わせる
4つの基準を、基準表のopのまま判定し、report.jsonのobserved・pass・metricsが、samples.jsonlから計算し直した値と同じになるようにしてください(ファイル: /root/accept/accept.py)。
opは、文字列を演算に変える表で処理します。エラー率が基準値とちょうど同じとき、<は不合格、<=は合格です。thresholdは基準表の値をそのまま移し、証拠は、リクエストの直後に1行ずつ書きます。
変わった基準表で、候補5つを分ける
新しい基準値・新しいケース表・新しい変わるフィールド名でも、正常な候補だけを受け入れ、欠陥のある候補は、該当する基準1つだけで不合格にするかを確認してください(ファイル: /root/accept/accept.py)。
1つの欠陥が複数の基準を同時に不合格にすると、原因を切り分けられません。基準値・フィールド名・ケースをコードに書いた場所が残っていないかを探してみてください。
顧客の候補rc2の受け入れを判定する
rc2サーバーをポート8095で起動し、criteria.json・提供されたケース表で実行して、報告書と証拠を残してください(ファイル: /root/accept/rc2/report.json、/root/accept/rc2/samples.jsonl)。
基準表を、結果に合わせて直さないでください。採点ツールは、criteria.jsonがステップ1の合意と同じか、報告書が証拠と同じか、証拠が実際のrc2の応答かを見ます。サーバーは、使い終わったら、そのPIDだけを選んで停止します。