9

私が持っている log4net.config ファイルで smtp アペンダーを構成しようとしています。問題は、インターネット全体を調べたところ、info、debug、error、fatal などの他のすべてのログ情報が含まれているエラーが発生したときに電子メールを送信する方法が見つからないことです。アプリケーションが終了したときのみ (エラーが発生するたびではありません)。

したがって、このメールを受け取るのは次の場合のみです: アプリケーションが終了したとき + すべてのログ情報 (DEBUG、INFO、ERROR、FATAL) があるとき + エラーが発生した場合のみ。

もう少し詳しく説明すると、これは、c シャープで例外を処理する方法によるもので、いたるところに複数レベルの処理があるため、エラーが発生した場合でも、何度でもメールを 1 つだけ受信したいと考えています。また、複数のログを使用するのではなく、ルートに 1 つだけ使用したいと考えています。

ありがとう。

4

3 に答える 3

6

SmtpAppender自力でこれを達成することはできません。だから私がしたことは、タイプのアペンダーに別のアペンダーを作成することでしたMemoryAppender。このロガーにしきい値を設定してSmtpAppender、たとえばError. これを使用して、より多くのレベルが記録された電子メールを送信するかどうかを後で決定します。

のメッセージは実際には気にしませんMemoryAppender-- 最後にメッセージが含まれていることだけを気にします。メールで受け取るメッセージは、実際にはSmtpAppender.

プログラムの最後で、メモリ アペンダーをチェックして、その GetEvents() にイベントが含まれているかどうかを確認します。もしそうなら、私は の正常な実行を停止しませんSmtpAppender

両方のアペンダーの Log4Net 構成:

<appender name="ErrorHolder" type="log4net.Appender.MemoryAppender" >
    <onlyFixPartialEventData value="true" />
    <!-- if *any* message is logged with this level, the email appender will 
         be used with its own level -->
    <threshold value="ERROR" />
</appender>

<appender name="Email" type="log4net.Appender.SmtpAppender">    
    <!-- the level you want to see in the email IF ErrorHolder finds anything -->
    <threshold value="INFO"/> 
    <bufferSize value="512" />
    <lossy value="false" /> <!-- important! -->   
    <to value="name@domain.com" />
    <from value="name@domain.com" />
    <subject value="ERROR: subject" />
    <smtpHost value="smtpserver" />    
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%newline%date [%thread] %-5level %logger [%property{NDC}] - %message%newline%newline%newline" />
    </layout>    
</appender>

<root>
  <level value="ALL" />
  <appender-ref ref="ErrorHolder" />
  <appender-ref ref="Email" />
</root>

アプリの最後にこれを実行して、アペンダーが空のSmtpAppender場合は無効にします。ErrorHolder

// trigger loggers if errors occurred:
var memoryAppender = ((Hierarchy)LogManager.GetRepository())
    .Root.Appenders.OfType<MemoryAppender>().FirstOrDefault();

if (memoryAppender != null && memoryAppender.GetEvents().Length == 0)
{
    // there was no error so don't email anything
    var smtpAppender = ((Hierarchy)LogManager.GetRepository())
        .Root.Appenders.OfType<SmtpAppender>().FirstOrDefault();

    if (smtpAppender != null)
    {
        smtpAppender.Threshold = Level.Off;
        smtpAppender.ActivateOptions();
    }
}
于 2011-05-06T04:42:23.007 に答える
2

これは、log4net構成の問題ではなく、アプリケーション構成の問題のように聞こえます。アプリケーションの最後に、内部にエラーがあることを検出した場合にログファイルを電子メールで送信するメソッドを配置することをお勧めします。エラーをログに記録するすべての場所でグローバル変数をfalseからtrueに切り替えることでこのエラーを検出するか、アプリケーションが終了するまで待ってからログファイルを読み取ってエラーが含まれているかどうかを確認できます。最初の方法はシャットダウン時に高速になりますが、複数の場所でコードを変更することを意味します。後者では、メソッドを1つ追加するだけで済みますが、大きなファイルでは時間がかかる場合があります。

3番目のオプションは、log4netを使用してエラーを2番目のログファイルに送信することです(2つの場所に移動します)。次に、アプリケーションが閉じていて、ログを電子メールで送信する必要があるかどうかを確認しているときに、エラーのみのファイルが存在するかどうかを確認します。存在する場合は、削除して(次回は存在しないように)、ログ全体を電子メールで送信します。

于 2011-05-05T14:42:58.583 に答える