22

Jeff Atwood が尋ねたように、「あなたのログの哲学は何ですか? すべてのコードに散らばって.logthis()呼び出し.logthat()を行う必要がありますか? それとも、何らかの形で事後にログを挿入しますか?」

4

12 に答える 12

21

私のロギング哲学は、次の 4 つの部分に簡単に要約できます。

監査、またはビジネス ロジックのログ記録

ログに記録する必要があるものをログに記録します。これはアプリケーション要件に由来し、データベースに加えられたすべての変更をログに記録すること (多くの金融アプリケーションのように) や、データへのアクセスをログに記録すること (業界の規制を満たすために医療業界で必要とされる場合があります) が含まれる場合があります。

これはプログラム要件の一部であるため、ロギングの一般的な説明に含めない人が多いですが、これらの領域には重複があり、アプリケーションによっては、すべてのロギング アクティビティを一緒に検討することが有用です。

プログラムのロギング

開発者がアプリケーションをテストおよびデバッグし、データ フローとプログラム ロジックをより簡単に追跡して、実装、統合、およびその他のエラーが存在する可能性がある場所を理解するのに役立つメッセージ。

通常、このロギングは、デバッグ セッションの必要に応じてオンまたはオフにされます。

パフォーマンス ロギング

必要に応じて後でログを追加して、パフォーマンスのボトルネックやその他のプログラムの問題を見つけて解決します。これらの問題は、プログラムの失敗の原因ではありませんが、操作の改善につながります。メモリ リークや重大ではないエラーが発生した場合は、プログラム ログと重複します。

セキュリティ ログ

セキュリティが懸念される外部システムとのユーザー アクションと対話をログに記録します。攻撃後に攻撃者がシステムをどのように破壊したかを判断するのに役立ちますが、侵入検知システムに結び付けて、新しい攻撃または進行中の攻撃を検出することもできます。

于 2008-09-04T19:29:37.147 に答える
4

メッセージや完全なスタック トレースなど、例外が発生した場合は、常に、常に、常にログを追加すると思います。それを超えて、ログを頻繁に使用するかどうかはかなり主観的だと思います...

私はしばしば、私がログに記録していることがめったにヒットしない重要な場所にのみログを追加しようとします。そうしないと、彼が言及したようにログが大きくなりすぎるという問題が発生します...これが、エラーケースをログに記録することが常に理想的な理由ですログに記録します (これらのエラー ケースが実際にいつ発生したかを確認できるので、問題をさらに調査できます)。

ログに記録する他の良いことは、アサーションがあり、アサーションが失敗した場合にログに記録することです...たとえば、このクエリは10件未満の結果である必要があります。これよりも大きい場合は問題がある可能性があるため、ログに記録します。もちろん、ログ ステートメントがログをいっぱいにしてしまう場合は、おそらく、何らかの「デバッグ」レベルにするか、ログ ステートメントを調整または削除するためのヒントです。ログが大きくなりすぎると、多くの場合、それらを無視することになります。

于 2008-09-04T19:32:53.423 に答える
1

私は伝統的なアプローチと考えるものを採用しています。条件定義に囲まれたいくつかのロギング。本番ビルドでは、定義をオフにします。

于 2008-09-04T19:29:50.263 に答える
1

これは、ログ データが意味を持つことを意味するためです。

  • ロギング フレームワークに応じて、レベル/重大度/カテゴリ情報を追加して、ログ データをフィルタリングできます。
  • 多すぎず少なすぎず、適切なレベルの情報が存在することを確認できます
  • コードを書くときに最も重要なものが何であるかを知っているので、それらがログに記録されることを確認できます

なんらかの形式のコード インジェクション、プロファイリング、またはトレース ツールを使用してログを生成すると、詳細であまり役に立たないログが生成される可能性が高く、掘り下げるのが難しくなります。ただし、これらはデバッグ支援として役立つ場合があります。

于 2008-09-04T19:31:22.727 に答える
1

私は自分のコードで多くの条件をアサートすることから始めます (C# では、 を使用System.Diagnostics.Assert)。ただし、デバッグ中またはシステムに負荷をかけているときに、内部で何が起こっているかを追跡する方法が本当に必要であることがわかった場所にのみログを追加します。デバッガーを永続的に接続せずに私のコード。

それ以外の場合は、Visual Studio の機能を使用してトレースをコードに特別なブレークポイントとして配置することを好みます (つまり、ブレークポイントを挿入して右クリックし、[ヒット時...] を選択して、その場合に何を表示するかを指示します)。再コンパイルする必要はなく、オンザフライでトレースを有効/無効にするのは簡単です。

于 2008-09-04T19:31:41.010 に答える
1

多くの人が使用するプログラムを作成している場合は、ログに記録するものと記録しないものを選択する何らかのメカニズムを用意することをお勧めします。.logthis() 関数を支持する 1 つの議論は、(適切に行われた場合) 場合によってはインライン コメントの優れた代替品になる可能性があるということです。

さらに、エラーが発生している場所を正確に絞り込むのに役立ちます。

于 2008-09-04T19:43:05.023 に答える
0

あなたが本当にあなたのシステムにログインする必要があるなら、あなたのテストはくだらないか、少なくとも不完全で、あまり徹底的ではありません。システム内のすべては、可能な限りブラックボックスにする必要があります。Stringのようなコアクラスがロギングを必要としないことに注意してください。主な理由は、それらが非常によくテストされ、詳細に実行されているためです。驚く様な事じゃない。

于 2011-02-09T06:21:00.880 に答える
0

私も Adam の意見に同意しますが、興味のあることや成果として示すことができることをログに記録し、それらが起こっていることの一種の証拠として記録することも検討します。

于 2008-09-04T19:30:43.803 に答える
0

ユーザーが提供した同じ手順を繰り返すことは言うまでもなく、単体テストで再現されない問題を絞り込む方法としてログを使用しています。当社の管理外のドライバーまたはサードパーティのライブラリの不具合が原因です)。

これはすべて私たちのテスト手順でキャッチする必要があるというコメントには同意しますが、これらの要件を満たすために非常に低レベルでパフォーマンスが重要なコードを要求する 100 万以上の LOC コードベースを見つけるのは困難です。私はミッション クリティカルなソフトウェアの仕事はしていませんが、メモリ アロケーターの実装から GPU コードの SIMD への利用まで、あらゆることをしなければならないことが多いグラフィックス業界で働いています。

非常にモジュール化された疎結合または完全に分離されたコードであっても、システムの相互作用は非常に複雑な入力と出力につながる可能性があり、プラットフォーム間で動作が異なり、テストを逃れる不正なエッジ ケースが時折発生します。モジュラー ブラック ボックスは非常に単純な場合もありますが、それらの間の相互作用が非常に複雑になり、時折予期しないエッジ ケースが発生する可能性があります。

ロギングが私のお尻を救った例として、ある時、私はクラッシュしていたプロトタイプの Intel マシンを持っていた奇妙なユーザーを持っていました。SSE 4 をサポートする必要があるマシンの最小要件をリストしましたが、この特定のマシンはそれらの最小要件を満たしており、16 コアのマシンであるにもかかわらず、SSE 3 以降のストリーミング SIMD 拡張をサポートしていませんでした。SSE 4命令が使用された行番号を正確に示す彼のログを見ることで、それをすぐに発見することができました. レポートの検証に参加した他の 1 人のユーザーは言うまでもなく、私たちのチームの誰も問題を再現できませんでした。理想的には、古い SIMD バージョン用のコードを作成するか、少なくともいくつかの分岐とチェックを行って、ハードウェアが最小要件をサポートしていることを確認する必要があります。しかし、シンプルさと経済性を実現するためのハードウェアの最小要件を通じて伝えられる確固たる前提を作りたかったのです。ここで、おそらく、「グリッチ」があったのは最小システム要件であったことは議論の余地があります.

ここでログを使用する方法を考えると、かなり大きなログを取得する傾向があります。ただし、目標は読みやすさではありません。一般的に重要なのは、ユーザーが何らかのクラッシュを経験したときにレポートと共に送信されるログの最後の行です (世界の他のユーザーは言うまでもなく)。再現できます。

それにもかかわらず、過度のログ スパムを回避するために私が定期的に採用している 1 つのトリックは、一度正常に実行されたコード片がその後も正常に実行されると想定することが合理的であることが多いということです (厳密な保証ではありませんが、多くの場合、妥当な仮定です)。log_onceそのため、呼び出されるたびにロギングのコストを支払うというオーバーヘッドを回避するために、粒度の高い関数に一種の関数を使用することがよくあります。

ログ出力をあちこちに散らばることはありません (時間があればそうするかもしれません)。通常、私は最も危険と思われる領域のためにそれらを最も予約します: GLSL シェーダーを呼び出すコード、例えば (ここでは GPU ベンダーは機能やコードのコンパイル方法の点でさえ大きく異なります)、SIMD 組み込み関数を使用するコード、非常に低レベルのコード、コード必然的に、OS 固有の動作、POD の表現に関する仮定を行う低レベル コード (例: 8 ビットから 1 バイトを想定するコード) に依存する必要があります。健全性チェックを行うだけでなく、最も多くの単体テストを作成します。通常はこれで十分です。ログを記録することで、再現不可能な問題に対処し、その問題をやみくもに突き刺す必要があった場合に何度も助けられました。

于 2015-11-18T14:55:58.377 に答える