コードをインストルメント化するときに開発者が行う愚かなこと

開発者は時々 あまりに 彼らが彼らのシステムを計装するとき、役に立ちます。 たとえば、リクエストの応答時間を報告するメトリックを追加するように求められた場合、それを行うにはいくつかの方法があります。 理にかなっていると思われるXNUMXつの方法は、リクエストの総数で変数を保持することと、処理時間の合計で変数を保持することです。 次に、開発者は、合計処理時間を合計リクエストで割った変数と、それを公開する方法(JMX経由でレポートするMBean、またはHTTP経由のステータスページなど)を作成するだけです。 これは、すべてユーザーが事前に計算した応答時間をミリ秒単位で報告する、すてきなオブジェクトになります。

これの問題は? 実際、平均応答時間を報告しますが、サーバーが起動してからのすべての応答時間の平均になります。 つまり、サーバーが平均応答時間1ミリ秒で実行されていて、1000時間稼働している場合、サーバーは要求ごとに100ミリ秒の応答時間を示し始めます。この遅い動作が1.01時間続くと、事前に計算されます。平均応答時間はXNUMXミリ秒になります(要求の速度が一定であると仮定)。 グラフで目で認識できるほどの変化はありませんが、 システムは現在100倍遅くなっていますが。 この実装を数回正確に確認しました(最近では、独自のプロセスの一部をインストルメント化した独自の開発者のXNUMX人だけでなく、ZooKeeperや他のサーバーでも)。これにより、応答時間のメトリックが監視やアラートの目的で役に立たなくなります。 (そして、なぜ彼らはそこにいるのですか?)

別の選択肢? 事前定義された期間(たとえば、過去2分間に受信したすべての要求の平均応答時間)にわたってメトリック(応答時間、CPU負荷など)を事前に計算します。 これはサーバーが起動してから平均化するよりも良い選択ですが、それでも最も役立つわけではありません。 別の周波数でサンプリングしたい場合はどうなりますか? 5分間隔でサンプリングする場合、サンプリングするたびに最後の2分間の移動平均が得られるため、監視はシステムの変更に期待したほど応答しません。 3分間隔でサンプリングすると、過去3分間の情報しか取得できません。 そのXNUMX分前の情報はないので、そのXNUMX分以内に応答時間が大幅に急増した場合、私にはわかりません。

では、開発者がインストルメンテーションを追加するための好ましい方法は何ですか? 開発者はより少ない作業を行う必要があります。 サーバーは、応答時間などの計算に必要なメトリックを公開する必要がありますが、事前計算は行わないでください。それは監視システムに任せてください。 結局のところ、それは彼らがするように設計されたものです。

したがって、応答時間を報告するには、サーバーの起動以降、すべての要求の処理に費やされた合計時間を示すカウンターを公開します。 処理されたリクエストの総数を示す別のカウンターを表示します。 それでおしまい。 (TomcatのMbeansはまさにこれを行います。)

次に、監視システムは、必要な間隔の応答時間を把握できます。 監視システムは、時間T1で、次に時間T2で再び合計処理時間の値を取得します。 同様に、時間T1とT2で合計リクエストを取得します。 次に、T1とT2の間隔に関係なく、その期間の平均応答時間は次のようになります。

(時間T2での合計処理時間–時間T1での合計処理時間)/(時間T2での合計要求–時間T1での合計要求)。

この方法は、5分ごとなどの低頻度でサンプリングすることを選択し、サンプルの最初の3分間に大きなスパイクがある場合、これは5分間の平均で表示されることを意味します。 何度でもサンプリングして、対象期間を正確に表すデータを取得できます。

この方法は、値を事前に計算するほど便利ではないように思われるかもしれませんが、はるかに一般的なユーティリティを提供します。 だから開発者–そんなに助けようとするのをやめなさい。 あなたの監視システムはあなたに感謝します!