5

「重大な」エラーが発生するたびに、NLog を使用して電子メール メッセージを送信しています。場合によっては、非常に多くのメッセージが生成されることが非常に頻繁に発生する可能性があります。

設定された期間内に特定のエラーまたはエラーで送信されるメッセージの数を NLog に制限させる方法はありますか?

log4net またはその他の一般的なロギング ライブラリに類似のメカニズムはありますか?

4

2 に答える 2

5

構成ファイルの変更:

 <target name="SystemErrorLog" xsi:type="TokenTimeThrottler" EntryExpirationPeriodSec="300">
    <target xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
      <target xsi:type="Mail" ... />
    </target>   </target>

対象クラス:

[Target("TokenTimeThrottler", IsCompound = true)]
public class ThrottlingLogTarget : CompoundTargetBase
{
    private ITokenTimeThrottler _tokenTimeThrottler;

    public ThrottlingLogTarget()
        : this(new Target[0])
    {
    }

    public ThrottlingLogTarget(params Target[] targets)
        : base(targets)
    {
    }

    [Required]
    public int EntryExpirationPeriodSec { get; set; }

    protected override void InitializeTarget()
    {
        base.InitializeTarget();

        _tokenTimeThrottler = new TokenTimeThrottler(EntryExpirationPeriodSec > 0 ? EntryExpirationPeriodSec : 0);
    }

    protected override void Write(AsyncLogEventInfo logEvent)
    {
        if (this.Targets.Count == 0)
        {
            logEvent.Continuation(null);
            return;
        }

        var token = string.Format("{0},{1},{2}", logEvent.LogEvent.LoggerName, logEvent.LogEvent.Level, logEvent.LogEvent.FormattedMessage);

        if (_tokenTimeThrottler.CheckAllow(token))
        {
            foreach (var target in Targets)
            {
                target.WriteAsyncLogEvent(logEvent);
            }
        }
    }
}


public class TokenTimeThrottler : ITokenTimeThrottler
{
    private readonly ConcurrentDictionary<string, DateTime> _entriesLastTimes;
    private readonly int _expirationPeriodSec;

    public TokenTimeThrottler(int entryExpirationPeriodSec)
    {
        _entriesLastTimes = new ConcurrentDictionary<string, DateTime>();

        _expirationPeriodSec = entryExpirationPeriodSec;
    }

    public bool CheckAllow(string token)
    {
        DateTime lastLoggedTime;

        if (_entriesLastTimes.TryGetValue(token, out lastLoggedTime))
        {
            DateTime? updatedTime = null;

            if (lastLoggedTime.AddSeconds(_expirationPeriodSec) < DateTime.Now)
            {
                updatedTime = DateTime.Now;
            }

            _entriesLastTimes.AddOrUpdate(token, k => updatedTime ?? lastLoggedTime,
                                            (k, v) => updatedTime ?? v);

            return updatedTime.HasValue;
        }

        _entriesLastTimes.AddOrUpdate(token, k => DateTime.Now, (k, v) => v);

        return true;
    }
}
于 2014-11-05T09:09:25.603 に答える
3

同様のlog4netの質問に対する私の回答は、次のとおりです。

log4net - N 番目のメッセージのみをログに記録するためのフィルターはありますか?

その回答で、構成可能な期間内に繰り返されるメッセージを調整できるようにするカスタム log4net フィルター実装を提案しました。

NLog の場合、最も簡単な方法は、カスタムの Wrapperターゲットを記述することです。カスタム Wrapper ターゲットの実装は、着信ログ メッセージを調べ、現在のメッセージが最新のメッセージと異なる場合 (または一定の時間が経過した場合) に転送します。その後、このカスタム ラッパーで既存のターゲットをラップできます。

私は実際に Wrapper ターゲットを作成していないことに注意してください。または、より多くの情報を提供しようとします。

于 2013-03-07T15:50:49.577 に答える