検索/コンテナのログとメトリクスをリアルタイムで流すWebアプリを開発する

コンテナのログとメトリクスをリアルタイムで流すWebアプリを開発する

バックエンドとシングルページのフロントエンドでできた、コンテナのログとメトリクスを流すアプリを直す時に使う。層の分け方、ストリームの上限、ログイン方式とデプロイモードを崩さずに、機能を全部の層へ足し、決まったテストを回し、短いレビューを書く。

このAIルールを使うには
## レビューは短く、バグと作業を止める問題だけを書く 変更リクエストのレビューと保守担当者としての返信には、極めて簡潔な形式を使う。報告するのはバグ、セキュリティ問題、作業を妨げる問題だけにする。短い箇条書きを使い、必要に応じて`file:line`参照を付け、「長所」や「要約」といったセクションは省き、返信全体をおよそ10〜15行に収める。 人間の保守担当者として書く。emダッシュやenダッシュ、「XではなくY」のような修辞的対比、前置きだけの称賛、末尾の再要約、太字のインラインラベル、中身のない曖昧表現は使わない。くだけた小文字表記や短縮形は許容する。判断を示し、理由を1つ述べたら終える。 ## 直した変更リクエストのビルドを、報告者に試してもらう 報告された問題が未完了の変更リクエストで修正されている場合、そのリクエスト用に継続的インテグレーションが構築した成果物を報告者に試してもらう。`{registry}/{image}:change-{number}`のような汎用パターンを使い、ビルド済みイメージまたはパッケージの正確な参照先を伝える。 これにより、報告者は次のリリースを待たずに修正を検証できる。この方法を勧める前に、オートメーションが変更リクエストごとにタグ付き成果物を実際に1つ発行していることを確認する。 ## 直す前に、バックエンドとフロントエンドの層の分け方をつかむ システムを、コンパイルされるHTTPバックエンドと、型を持つシングルページのフロントエンドの組み合わせとして扱う。バックエンドはルーティング、認証、コンテナまたはワークロードのクライアント、ログとメトリクスのライブストリーム、操作、通知、リモートエージェントとの通信を担う。フロントエンドはファイルベースのビュー、再利用可能なコンポーネント、リアクティブストア、ストリーム用コンポーザブル、ルーティング、ローカライズ、利用者設定を担う。 単独または複数ホストのサービス、クラスタ化されたオーケストレーション、リモートエージェント運用など、文書化された各デプロイモードを明示的にサポートする。あるクライアント実装で動く変更が、すべてのバックエンドでも動くと仮定してはならない。 主要な依存方向を明確に保つ。`HTTP handlers -> host service -> per-host service -> domain client -> runtime implementation` ## 決まったターゲットでビルドとテストを回す 依存関係をインストールし、証明書、スキーマ、プロトコルコードの生成ターゲットを実行してプロジェクトを準備する。バックエンドとフロントエンドを連動してホットリロードする場合は開発タスク全体を使い、問題を切り分ける場合は2つの監視処理を個別に実行する。 フロントエンドの成果物を、完全なバックエンドビルドへ埋め込む前にビルドする。フロントエンド配布物、アプリケーション全体、デプロイ可能なイメージには、それぞれ別のターゲットを用意する。プレビューターゲットを使い、実運用に近いビルドをローカルで確認する。 文書化されたターゲットを通して、バックエンドテスト、フロントエンドの単体テスト、型チェック、ブラウザ統合テストを実行する。時刻に影響されるフロントエンドテストでは`TZ=UTC`を使い、監視モードはローカルで反復作業を行う間だけ使う。 ## バックエンドの層を分けたまま、共通のインターフェースで実装する HTTPルーティングとストリーミングハンドラーを、ホストサービスおよびクライアントサービスより上位に置く。ランタイム固有の操作を共有ドメインクライアントインターフェースの背後に置き、サポート対象のコンテナ、クラスタ、リモートエージェントの各バックエンドでそのインターフェースを実装する。 認証プロバイダー、ドメインモデル、イベント解析、通知の評価、通知の配信をトランスポートハンドラーから分離する。コマンドライン解析と複数ホストのオーケストレーションはハンドラー内で重複させず、支援レイヤーに置く。 新しいワークロード操作を追加する場合、ドメインクライアントインターフェース、適用対象となるすべてのランタイム実装、ホスト単位のサービスラッパー、ルートを含むHTTPハンドラーを更新する。1つのデプロイモードだけを通すためにレイヤーを迂回してはならない。 ## フロントエンドのストアとログの型を、決まった役割のまま保つ ルートビュー、自動インポートされるコンポーネント、リアクティブストア、ストリーム用コンポーザブル、アプリケーションプラグインを、それぞれ定められた役割に保つ。バックエンドが描画したHTMLから注入される設定は不変として扱う。永続化する設定は、リアクティブなストレージ抽象化の背後に置く。 単一行のテキスト、構造化オブジェクト、グループ化された複数行メッセージを、別々のログエントリ型として表現する。共用体型を繰り返し書かず、共有メッセージエイリアスを使う。各イベントから正しい型を選ぶファクトリーを通してエントリを生成する。 ルートやワークロードの変更をまたいで再利用されるコンポーネントは、派生状態をすべて更新しなければならない。チャートが最後の棒だけを書き換えて更新を最適化する場合は、完全な再計算メソッドを外部へ公開し、データ系列全体が置き換わった時に呼び出す。 ## ログとメトリクスのストリームで、決まった上限を守る ログ、ライフサイクルイベント、メトリクスのストリームにはサーバー送信イベントを使い、対話的なアタッチまたは実行セッションにはWebSocket接続を使う。状態を変更するワークロード操作は、読み取り専用ストリームではなく明示的なHTTPリクエストで送る。 受信したフロントエンドイベントを250ミリ秒バッファリングするが、遅くとも1,000ミリ秒後にはフラッシュする。リアクティブ更新をまとめ、表示メッセージが400件を超えたら、ビューアー規約に従って最も古いエントリを置換するか、対象として印を付ける。 メトリクス履歴は最大300項目のローリングウィンドウで追跡する。アルファ0.2の指数移動平均でメトリクスを平滑化し、CPU値は許可されたコア数またはホストのコア数で正規化する。メモリの割合値と絶対値は区別して保つ。 チャートは利用可能な表示幅に合わせてダウンサンプリングする。通常の更新では最後の棒だけを更新する場合でも、ワークロードの切り替えなどでデータ系列全体を置換した時は、完全な再計算を必ず実行する。 ## ログイン方式とデプロイモードを、1つずつ分けて扱う 認証なし、ローカルファイル、フォワードプロキシの認証を別々の方式としてサポートする。ローカル認証には有効期限付きの署名済み資格情報を使い、設定された利用者ファイルを検証し、ロールベースの認可をIDプロバイダーから独立させる。 単独モードでは、再試行に対応したマネージャーでローカルクライアントとリモートクライアントをまとめる。クラスタモードではオーケストレーションAPIを通してノードを検出し、各ノードのエージェントへ接続する。クラスタネイティブモードでは、そのプラットフォームのAPIを通して同じドメインクライアントインターフェースを実装する。リモートエージェントモードでは、証明書で認証されたトランスポートを必須にする。 モード選択はアプリケーションのエントリーポイントに置く。適用対象となるすべてのモードについて動作を定義するか、非対応モードでは明示的に拒否するまで、その機能は未完成とする。 ## 新しい機能を、関係する全部の層に通して足す 新しいHTTPルートでは、ルートを登録し、ハンドラーを実装し、ホストサービスを通して対象を解決し、構造化データを返すか、目的のストリームを確立する。新しいログビューでは、ルートビューを追加し、ストリーム用コンポーザブルを作成し、フィルター付きAPI URLを組み立て、バッファリングを管理し、リアクティブなメッセージと制御手段を返し、既存のビューアーを再利用する。 新しいメトリクスでは、バックエンドの統計型を拡張し、値を抽出・計算し、プロトコルスキーマを更新し、プロトコルコードを再生成する。インターフェースから必要な場合は、フロントエンドモデルでそのフィールドを利用可能にする。既存のイベントストリームで更新を運び、並行する別トランスポートを設けない。 新しい通知チャネルでは、ディスパッチャーインターフェースを実装し、ディスパッチャーファクトリーへ登録し、設定フォームを追加し、永続化されたルールとアラート状態の動作を維持する。 ## リモートツールの同時実行を絞り、一時的な失敗だけ再試行する リモートディスパッチャーが設定されるまで接続してはならない。ツールの検出と呼び出しには双方向ストリームを使い、1つのレジストリを通して呼び出しを振り分け、重み付きセマフォで同時実行数を5件に制限する。 一時的な障害が起きたら、ジッターを加えた1〜30秒の指数バックオフで再接続する。資格情報が無効、または利用可能なプランがないことを示す権限拒否応答では、再試行を恒久的に停止する。不変のツール定義は一度だけキャッシュし、リモート操作を無効にした時のオーバーヘッドを無視できる程度に抑える。 ツールを追加するには、名前、説明、パラメータスキーマを定義し、その応答型をプロトコル結果の共用体へ追加し、プロトコルコードを再生成し、振り分け用の分岐を登録し、ホストサービスインターフェースの背後で実装し、対象を絞ったテストを追加する。 ## ログを種類ごとに分けて、ため込まずにライブで流す 多重化されたランタイムストリームのヘッダーとペイロードを読み取り、各生イベントを構造化データ、グループ化された複数行イベント、単一行イベントのいずれかに分類する。明示的なパターンで重大度を抽出し、ドメインイベントをシリアライズしてライブストリームで配信する。 リモートエージェントでは、ドメインクライアント呼び出しをプロトコルリクエストへ変換し、ローカルのランタイムクライアントへ処理を委譲し、応答をドメインモデルへ戻す。上限のない結果をメモリに集めず、ログ、メトリクス、ライフサイクルイベントのストリーミング動作を維持する。 レベル、クエリ、正規表現によるフィルタリングには、明確な結果上限を維持しなければならない。ワークロード操作は、明示的な有効化ゲートの背後に置いたままにする。 ## 毎回同じ結果になるテストをし、ライブの接続を見てデバッグする バックエンドテストは競合検出器を有効にして実行する。プロジェクトのアサーションライブラリを一貫して使い、フロントエンドテストはUTCで実行し、ブラウザ統合テストは必要なサービス構成とともに実行する。ビルド失敗をコードの不具合と判断する前に、必要な証明書とプロトコル成果物を再生成する。 アセットを埋め込まない開発では、ファイルシステムからの配信と連動したホットリロードを有効にする。バックエンドの変更時はバックエンド監視処理を再起動し、フロントエンドの変更時は全体を再起動せずモジュール置換を使う。 デバッグでは、バックエンドのデバッグログを有効にし、ブラウザ開発ツールでフロントエンドの状態を確認し、ネットワークパネルでサーバー送信イベントとWebSocket接続を調べる。生成ファイルや自動編集が無関係な変更を隠していないか、最終差分をレビューする。