15

最近、Windows サービスの展開中に問題が発生しました。4 台のコンピューターでは問題は発生しませんでしたが、5 台目のコンピューターではサービスを開始しようとしても例外が原因で失敗しました。例外スタック トレースはイベント ログに書き込まれるため、原因を簡単に特定できるはずですが、

protected override void OnStart(string[] args)
{
    EventLog.WriteEntry("Starting service", EventLogEntryType.Information);

    try
    {
        //...
        base.OnStart(args);
    }
    catch (Exception ex)
    {
        EventLog.WriteEntry("Service can not start. Stack trace:" + ex.StackTrace, EventLogEntryType.Error);
        Stop();
        return;
    }

    EventLog.WriteEntry("Service started", EventLogEntryType.Information);           
}

しかし残念ながら、ログに情報が書き込まれることはありませんでした。最後に、最初に書き込まれたログエントリまでたどりました。アプリケーション イベント ログが最近のエントリでいっぱいで、7 日より古いエントリのみを上書きするように構成されていたため、例外がスローされました。

アプリケーション イベント ログの構成を変更できないことを考えると、イベント ログへの書き込みに関するベスト プラクティスは何ですか?

常にEventLog.WriteEntrytry ブロックを入れる必要がありますか、はいの場合、例外をどのように処理する必要がありますか (イベント ログに書き込むのはおそらく悪い考えです)、メソッドでイベント ログの状態を確認する必要OnStartがありますか、それとも他に良い方法がありますか?提案?

4

6 に答える 6

11

log4net を使用する

log4net を使用する利点は、ログをチェックして、コード内で説明するよりもはるかに柔軟にログを制御できることです。

イベント ログにログを記録していて、問題が発生し、イベント ログ エントリがない場合は、いつでもファイル アペンダ ログに切り替えて、それが機能していることを確認できたはずです。イベントログ。

log4net も防御的です。ログ エントリの書き込みに失敗しても、プログラムがクラッシュすることはありません。したがって、これが発生することはありませんでした (つまり、ログ ファイルはありませんが、プログラムは実行されており、ログ ファイルを取得するために 2 番目のログ記録方法を指定できたはずです)。

log4net ドキュメントの重要な部分は次のとおりです。

[log4net] は、ベスト エフォート型のフェイル ストップ ロギング システムです。

フェイル ストップとは、log4net が実行時に予期しない例外をスローしないことを意味し、アプリケーションがクラッシュする可能性があります。何らかの理由で、log4net がキャッチされない例外をスローした場合 (スローされる可能性がある ArgumentException および ArgumentNullException を除く)、log4net-user@logging.apache.org メーリング リストに電子メールを送信してください。キャッチされない例外は、すぐに対処する必要がある重大なバグとして処理されます。

さらに、log4net は、指定された出力ストリームが開かれていない場合、書き込み可能でない場合、またはいっぱいになった場合、System.Console.Out または System.Console.Error に戻りません。これにより、ロギングが失敗したためにユーザーの端末がフラッディングされて、他の方法では動作しているプログラムが破損するのを回避できます。ただし、log4net は、ロギングを実行できないことを示す単一のメッセージを System.Console.Error および System.Diagnostics.Trace に出力します。

(私の強調)

ほとんどの場合、あなたよりも優れたライブラリがあります。log4net は .Net へのログインを解決し、あなたの生活を楽にしてくれます。

于 2008-11-24T10:46:50.700 に答える
4
System.Diagnostics.EventLog log = 
    new System.Diagnostics.EventLog("YourLogNameHere");
log.ModifyOverflowPolicy(
    System.Diagnostics.OverflowAction.OverwriteAsNeeded, 0);

これにより、オーバーフローの問題が修正されます。通常、イベント ログは、正しく構成されていれば、非常に信頼性が高くなります。イベント ログを使用するときは、テキスト ファイルに書き込むだけの簡単な緊急バックアップ ロガーを追加していました (書き込みには約 5 分かかります)。呼び出されることはありませんでした。

于 2008-11-24T13:25:04.187 に答える
3

ServiceBase クラスが既に提供しているデフォルトのイベント ログ メカニズムをそのまま使用することはできませんか? サービスが開始されない場合は、そのことを示すエントリがイベント ログに自動的に書き込まれます (stacktrace を使用)。

それとは別に、log4net(またはlogging-systemのような他のベストエフォート)に関するコメントに関しては、達成しようとしていることに本当に依存していると思います。

あなたの例では、log4net (または ServiceBase のイベントロギングの組み込みサポート) を使用しても問題ない可能性があります。

しかし、エラーが発生し、その事実がどこかに記録されていないことさえ問題になる場合があります。たとえば、認証または承認システムを想定します。たとえば、資格情報が間違っているためにパスワード認証が失敗したことを正常かつ確実にログに記録できない場合は、続行できない可能性があります (パスワード認証が成功した場合も同様です)。

そのため、ロギングの試行がいつ失敗したかを知り、それを単独で処理する必要がある場合があります。もちろん、これには限界があり (ニワトリ - 卵 - 問題)、行うことは特定のアプリケーションまたはシナリオに非常に固有のものです。

于 2008-11-25T07:12:30.303 に答える
2

例外をログに記録することは、例外を飲み込んだ方がよいまれなケースの 1 つだと思います。ほとんどの場合、これでアプリが失敗することは望ましくありません。

しかし、なぜログ記録コードを自分で書いているのでしょうか? NLog や Log4Net などのフレームワークを使用してください。これらも先ほど言ったように例外を飲み込みますが、構成を変更するだけでログ出力を別の場所 (ファイル、メッセージボックスなど) にリダイレクトできます。これにより、このような問題の解決がはるかに簡単になります。

于 2008-11-24T10:49:17.153 に答える
2

Logging App Blockの利用を検討してください。

Enterprise Library Logging Application Block は、一般的なログ機能の実装を簡素化します。開発者は Logging Block を使用して、さまざまな場所に情報を書き込むことができます。

  • イベントログ
  • 電子メール メッセージ
  • データベース
  • メッセージ待ち行列
  • テキストファイル
  • WMI イベント
  • アプリケーション ブロックの拡張ポイントを使用したカスタムの場所
于 2008-11-24T10:49:46.840 に答える
0

ここで一歩戻りましょう:

システム イベント ログは、システムに問題が発生したことをシステム管理者に警告するために存在します。サービスの開始が失敗するのを許可する必要があります。これは、「サービス コントロール マネージャー」の報告されたソースと共にシステム エラー ログに表示されます。これは、システム管理者が障害について知ることを意味します。

次に、トラブルシューティングが必要な場合は、プログラムの最上位にあるディスク上のファイルに例外を記録する必要があります。サービスの開始が失敗するように、それらを再スローする必要もあります。

その後、システム イベント ログで問題を特定し、障害の発生時刻をアプリケーション ログと相互参照できます。

于 2009-06-04T12:17:09.173 に答える