さくらコードSakura Code
小説/第18話

Novel

第18話 私のコード

第18話 私のコードのイメージイラスト

Script

Cold Open

シーン1 週明けの翔太

 二月六日。月曜日。

 立春を過ぎたばかりの空は、だいぶ高くなっていた。オフィスの窓の外、午前の光が、冬の終わりらしく、わずかに、白さを残しながら、ガラスを通って、机に届いている。

 翔太は、いつもの月曜より、少しだけ、疲れた顔で出社してきた。コーヒーを二杯、続けて淹れてから、ようやく椅子に腰を下ろした。

 先週末、翔太が担当していた別件の障害調査が、金曜の夜まで続いていた。追加の調整ごとも、彼のカレンダーに、二つほど入っていた。

 リリース前夜の会議で「あさってか、しあさってには直せる」と宣言したダッシュボード修正は、まだ、翔太の手もとで、半分ほどで止まっていた。

 朝会で、翔太は、鈴木に、

「#218 の監視修正、ちょっと、今週前半に、片付けられるか、予測つかないです。すみません」

 と、珍しく、弱音に近い言い方をした。

 鈴木は、穏やかにうなずいた。

「いそがなくていい。順番、整理しよう」

 その隣で、桜子は、少しだけ、息を吸い込んでから、手をあげた。


Part A

シーン2 桜子の挙手

「あの、#218 の監視修正のほうって、わたしが、調査と提案を、やってみていいですか」

 翔太と、鈴木と、遥が、同時に、桜子を見た。

「……もちろん、実装は、翔太くんがいいって言うなら、翔太くんにお願いしたいです。でも、調査と、一次の修正案、書き切るところまでは、わたしでも、いけるかなって」

 鈴木が、うなずきかけた。ただ、翔太が、半拍、沈黙してから、

「望月さん、実装まで、やっていいよ。僕、レビューに回る」

 と、言った。

 声は、やや低かった。けれど、その沈黙の半拍が、本気の決断の時間なのだと、桜子には分かった。翔太は、「僕の領地を取らないで」を選ばないで、「領地の中で走ってほしい」を選んだ。

「……ありがとう、中村くん。お願いします」

「うん。レビュー、雑にしないよ」

「はい」

 朝会が解散したあと、遥が、桜子の横に来て、

「桜子さん、手、あげたね」

 と、短く言った。

「はい」

「言い方、落ち着いてた。調査と、提案、じゃなくて、調査と、一次の修正案、まで入れたところ、いいね」

 桜子は、ほんの少しだけ、うなずいた。自分の耳のあたりが、熱かった。


シーン3 集計窓の悲しみ

 桜子は、ステージング環境に、自分の検証用のブランチを作って、集計の境界で起きているズレを、まず、自分の目で、再現することから始めた。

 アプリ側は、1分窓でメトリクスを記録している。

fallback_inquiries_detail_total: 
  - 14:00:00〜14:00:59 -> 2 回
  - 14:01:00〜14:01:59 -> 3 回
  - 14:02:00〜14:02:59 -> 0 回
  - ...

 ダッシュボード側は、これを5分窓で集計し、折れ線として描画している。ただ、境界のちょうどのタイミングで発火したイベントは、1分窓の縁で浮き上がり、5分窓の境界のアラインの仕方によって、手前の窓にも、次の窓にも、完全には含まれない瞬間があった。

 桜子は、擬似負荷で、境界付近のタイミングに発火を集めた。アプリ側のカウンタは正しい。ダッシュボードの折れ線が、ほんのわずかに、低い位置で描画される。数字にして、2〜4%の過小。

 (ここが、わたしの、きょうの、境界)

 頭の中で、五月の初めてのバグの日の「境界条件」という言葉が、もう一度、流れた。

 それから、六月のリファクタリングの parametrize。境界値を並べて、仕様の角を、明文化する考え方。

 桜子は、ダッシュボード側の集計コードを開いて、画面を上から下まで、ゆっくり読み直した。


Part B

シーン4 桜子案と翔太案

 昼の休憩、翔太が、桜子のデスクの横に立った。

「望月さん、僕が考えてた案、ちょっと、聞いてもらっていい?」

「はい、ぜひ」

 翔太は、ノートに、二本の線を引いた。

「ダッシュボード側の集計窓、いまは5分。これを、アプリ側と合わせて、1分窓に揃える。集計回数が増えるけど、最近のSaaS監視の粒度からすれば、そんなに重くない」

「なるほど」

「利点:境界ズレの現象そのものが、物理的に、ほぼ消える。欠点:監視コストが、若干、上がる。既存の他指標も、1分か5分か、統一が必要」

 桜子は、自分のノートに、もうひとつ、線を引いた。

「わたしの案は、こうです。集計窓は、5分のまま、据え置く」

「据え置く」

「はい。代わりに、ダッシュボード側の集計ロジックを、境界またぎのイベントを、手前と次の窓に、時間割合で、薄く帰属させる。いわゆる、プロレート集計」

「ああ、プロレート」

「利点:ダッシュボードの5分窓は動かさないので、他指標の運用を変えない。欠点:集計コードは、少し、複雑になる」

 二人は、お互いの線を、見比べた。

「どっちも、アリだね」

「はい。どっちも、アリです」

 桜子は、翔太の顔を、見た。翔太は、少しだけ、頬に、笑いのあとのような、影を浮かべて、

「望月さん、書いてみてよ。僕のほうが、良い理由と、望月さんのほうが、良い理由、両方」

「……はい、書きます」


シーン5 設計意図を、書き切る

 午後、桜子は、PR #258 を切った。タイトルは、

feat(monitoring): prorate fallback metrics across boundary (#218 follow-up)

 PR本文には、十二月の小リリース束のIssueテンプレと、リリース前夜のチェックリストの両方を参考にした、長めの設計セクションを置いた。

## 背景
#218 (フォールバック常時ON) のダッシュボードが、集計窓の境界で
イベントを過小カウントしうる問題への対処。

## 二案の比較

### 案A (桜子案): ダッシュボード側を 5分窓のまま、境界プロレート集計にする
- メリット:
  - 既存の他メトリクスの 5分窓運用と整合
  - アプリ側の 1分カウンタは変えない
  - 既存ダッシュボードのレイアウト変更なし
- デメリット:
  - 集計コードが少し複雑 (境界イベントを時間比で分配)
  - プロレート処理の単体テストが必要

### 案B (翔太案): 集計窓自体を 1分に揃える
- メリット:
  - 境界ズレの現象そのものが物理的に消える
  - 短時間のスパイクを早く検知できる
- デメリット:
  - 他メトリクスとの窓粒度の差が生まれる
  - 監視インフラ側のコスト・運用負荷の見直しが必要
  - ダッシュボードの折れ線の見え方が、チーム全員にとって、一度、変わる

## 本PRでの選択
案A を採用する。理由は、現在のサクラサポートの監視は 5分窓を基準に構築されており、
本件のためだけに窓粒度を変えると、他指標の運用負荷まで波及するため。

案B が価値を持つのは「スパイク検知を短周期で見たい」という将来の要件が立った時点。
この方向の提案は別Issue #261 として切り出し、担当は翔太さん希望とする。

## Acceptance Criteria
- [ ] 境界イベントの過小カウントが、ステージングで 0.5% 未満
- [ ] プロレート処理の単体テスト (境界/中央/深夜切り替え) 緑
- [ ] ダッシュボードから Runbook (#219) に 1クリック到達が維持

## ロールバック
- feature_flags.yaml: `prorate_boundary_metrics: true` をデフォルトON
- 問題発生時は false に切り替えるだけで、従来の 5分窓素朴集計に戻る

 実装は、画面を三度、行き来して、テストから先に書いた。境界時刻ちょうど、境界+1秒、境界-1秒、日付変更、サーバのローカルタイム跨ぎ。parametrize で、八ケースを並べた。

 一度、赤が出た。期待値のほうが、桜子の勘違いだった。テストを直して、また緑にする。

 夕方、PR本文とコードを、ひと通り、見直した。

 送信ボタンを押した。


Part C

シーン6 鈴木の選択と、翔太の一言

 翌朝。

 レビューは、遥、翔太、鈴木の順に付いた。

 遥は、

@yamashita-haruka: 二案併記、いいね。
本PRでの選択の理由が、桜子さんの言葉で書いてある

 翔太は、

@nakamura-shota: LGTM。#261 は、僕が、将来、スパイク検知を
入れたくなった時に、自分で起票して動きます。
プロレート処理、parametrize のケース、抜けなさそう

 鈴木は、レビュワーを代表して、

@suzuki-kenichi: Approved。顧客向け障害時の挙動が、
既存の5分窓の運用と揃ったままで、いい。
ふつうのリリース判断で進めよう

 昼、桜子は、鈴木に呼ばれて、短いミーティングをした。

「桜子さん、#258、本番、明日の夕方でいい?」

「はい、手順どおりで、お願いします」

「あと、お伝えしておくね。#261 は、翔太くんが将来、着手する形で、ボードに残す。桜子さんの案が、翔太くんの案を“潰した”わけじゃない。二つとも、いい案で、今回の現場が寄ってるのは、桜子さんのほう、だった」

「……ありがとうございます」

 ミーティングのあと、トイレに行こうと廊下を歩いていたら、翔太と、すれ違った。

 翔太は、半歩だけ、足を止めて、

「#261、僕がやるから」

 と、言った。

 桜子は、ひと呼吸だけ、置いてから、

「はい、お願いします」

 と、返した。

 その声色は、夏の計測タスクのころ、廊下で聞いた「countunread、僕、コード読んでなかった」のときより、少しだけ、落ち着いていた。


Ending

シーン7 冷たい雨のあとの道

夕方のオフィスで、桜子がモニタに映る監視ダッシュボードの折れ線を、じっと見つめている

 翌日の夕方、十七時半。

 #258 が、本番へ、デプロイされた。リリースのボタンは、鈴木が押した。桜子は、自分の机で、ダッシュボードの折れ線を、じっと、見ていた。集計値が、これまでより、ほんのわずかに、正しい位置に、描画されていく。

 十八時すぎ、桜子は、退勤した。

 駅までの道で、冷たい雨が、ほんの十分ほど、降った。桜子は、ビルの軒先で、雨を見送った。

 アスファルトが、濡れている。街路樹の下では、まだ葉のない枝が、夕雨のあとの街灯の光を、線で受けている。風は、立春の名にしては、まだ冷たかった。

 桜子は、近くのカフェに入って、メモ帳を開いた。

2023/02/07 新人日記

- #258、本番、今日の17:30デプロイ
- 調査・設計・実装・テスト・PR本文・レビュー対応、全部、自分の手で
- 翔太案と二案併記。選ばれたのは、わたしの案
- 鈴木さん: 「桜子さんの案が、翔太くんの案を“潰した”わけじゃない」
- 翔太くん: 「#261、僕がやるから」

 ペンを置いて、桜子は、カップを、両手で包んだ。

 (わたしの、コード)

 入社式の日の print("Hello, Sakurako Mochizuki.") の一行。

 五月の、>= 18 の一文字の修正。

 六月の、リファクタリングと parametrize。

 夏の計測タスクの、計測表と、二段の改善案。

 雨のレビューの日の、Runbook とフラグ。

 十月の障害の夜の、タイムラインの数行。

 千葉の現場から持ち帰った、黄色い付箋。

 十二月の、Issue テンプレとホワイトボードの矢印。

 リリース前夜の、三択の評価軸。

 全部、頭の中で、並べてみる。どれも、自分の名前のコミットハッシュが、いまの本番に、残っている。

 でも、いま、初めて、桜子は、

 (きょうのは、わたしが、決めた形で、入った)

 と、思った。

 提案書を鈴木に渡して、決裁を頼んだ。実装は、自分で書いた。二案の比較も、自分で書いた。テストの parametrize のケースも、自分で並べた。翔太の別案は、別Issue として、ちゃんと、残した。

 桜子は、メモの最後に、こう書いた。

- きょう、わたしの書いたコードが、サクラサポートで、動いた
- わたしは、きょうから、「書ける人」、じゃなくて、「決めた形で書ける人」
  にいたる階段の、二段目にいる

 ペンを置くと、カフェの窓の外、雨上がりの街路に、街灯が灯り始めていた。

 桜子の一年目も、もう、残りわずかだ。

 明日は、きっと、また、別の新しいコードが、誰かの机の上で、書かれる。