NLog 限制在设定时间内记录相同错误的次数

问题描述 投票:0回答:3

每当发生“严重”错误时,我们都会使用 NLog 发送电子邮件。在某些情况下,这种情况可能会经常发生,生成太多消息。

有没有办法让 NLog 限制在设定的时间内针对某个特定错误或任何错误发送的消息数量?

log4net 或任何其他流行的日志库中是否有类似的机制?

email logging log4net nlog
3个回答
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;
    }
}

3
投票

您可以在这里看到我对类似 log4net 问题的回答:

log4net - 是否有仅记录第 N 条消息的过滤器?

在该答案中,我提出了一个自定义 log4net 过滤器实现,允许限制可配置时间段内的重复消息。

对于 NLog,最简单的方法可能是编写自定义 Wrapper target。 自定义 Wrapper 目标实现将检查传入的日志消息,如果当前消息与最新消息不同(或者可能已经过了一定时间),则转发。 然后,您可以使用此自定义包装器包装任何现有目标。

请注意,我实际上尚未编写 Wrapper 目标,否则我会尝试提供更多信息。


0
投票

根据您的 NLog 版本,您可以使用内置的 LimitingWrapper 目标(自 4.4 起可用),它具有限制和间隔属性。

我们在一个长期存在且经常活跃的流程中使用它,将所有错误记录在日志文件中,但按小时限制电子邮件。

<target xsi:type="LimitingWrapper"
              name="EmailLimitingWrapper"
              messageLimit="10"
              interval="01:00">

                <target xsi:type="Mail" subject="${EmailSubject}" to="[email protected]"
                   useSystemNetMailSettings="true"
                   body="${EmailBody}"/>

</target>

在这里您可以查看文档:

https://github.com/NLog/NLog/wiki/LimitingWrapper-target

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.