限制 Elmah 发送的电子邮件数量

发布于 2024-08-16 22:41:24 字数 388 浏览 7 评论 0原文

有谁知道有什么好方法可以像健康监控一样限制 Elmah 在一段时间内发送的电子邮件数量?

我希望能够将每个页面中每个错误的电子邮件限制为针对该特定错误和页面每小时左右发送一次电子邮件。

查看 elmah 文档,它看起来像

void ErrorMail_Filtering(object sender, ExceptionFilterEventArgs e)
{
    // perform filtering here   
}

在 global.ascx 文件中使用:可能是一个选项。我可以为每个应用程序设置一个静态对象,其中包含一些错误详细信息和记录的时间并检查它并在需要时取消电子邮件通知?

有谁有更好的解决方案或他们现在正在使用的示例?

Does anyone know of a good way to limit the number of emails sent by Elmah during a time period like you can with Health Monitoring?

I want to be able to limit the emails for each error from each page to only an email once an hour or so for that particular error and page.

Looking at the elmah documentation it looks like using:

void ErrorMail_Filtering(object sender, ExceptionFilterEventArgs e)
{
    // perform filtering here   
}

in the global.ascx file might be an option. I could setup a static object per application that contains some the error details and the time logged and check it and cancel the email notification if need be?

Do anyone have a better solution or an example of what they are using now?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夜巴黎 2024-08-23 22:41:24

我用与你问题中相同的方法写了这篇文章。看起来效果很好。

public static DateTime  RoundUp(this DateTime dt, TimeSpan d)
{
    return new DateTime(((dt.Ticks + d.Ticks - 1) / d.Ticks) * d.Ticks);
}
static ConcurrentDictionary<int, KeyValuePair<DateTime, string>> _concurrent = new ConcurrentDictionary<int, KeyValuePair<DateTime, string>>();

/// <summary>
/// This is an Elmah event used by the elmah engine when sending out emails. It provides an opportunity to weed out 
/// irrelavent emails.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void ErrorMail_Filtering(object sender, ExceptionFilterEventArgs e)
{
    preventSpammingDigestEmail(e);
}

/// <summary>
/// Prevents spamming by throttling emails to 5 minute intervals.
/// </summary>
/// <param name="e"></param>
private static void preventSpammingDigestEmail(ExceptionFilterEventArgs e)
{
    DateTime roundedTimeStamp = DateTime.Now.RoundUp(TimeSpan.FromMinutes(5));
    string serialisedException = Util.SerializeException(e.Exception);

    var lastRaisedException = new KeyValuePair<DateTime, string>
        (roundedTimeStamp, serialisedException);

    int key = lastRaisedException.GetHashCode();

    bool errorHasAlreadyBeenRaised = _concurrent.ContainsKey(key);

    // If event has already been raised in the last five minutes dont raise again
    if (errorHasAlreadyBeenRaised)
    {
        e.Dismiss();
        return;
    }

    // Record that it has been raised
    _concurrent.TryAdd(key, lastRaisedException);

    // Clean up existing entries
    Task.Factory.StartNew(() =>
        {
            var toRemove =
                _concurrent.Where(pair => pair.Value.Key < DateTime.Now.Date).Select(pair => pair.Key).ToArray();

            foreach (var i in toRemove)
            {
                KeyValuePair<DateTime, string> keyValuePair;
                _concurrent.TryRemove(i, out keyValuePair);
            }
        });
}

private static string SerializeException(Exception e, string exceptionMessage = "")
{
    if (e == null)
        return String.Empty; 
    exceptionMessage = String.Format("{0}{1}{2}\n{3}", exceptionMessage, (exceptionMessage == String.Empty) 
        ? String.Empty 
        : "\n\n", e.Message, e.StackTrace);
    if (e.InnerException != null) 
        exceptionMessage = SerializeException(e.InnerException, exceptionMessage); 
    return exceptionMessage;
}

I wrote this using the same method as in your question. Seems to work nicely.

public static DateTime  RoundUp(this DateTime dt, TimeSpan d)
{
    return new DateTime(((dt.Ticks + d.Ticks - 1) / d.Ticks) * d.Ticks);
}
static ConcurrentDictionary<int, KeyValuePair<DateTime, string>> _concurrent = new ConcurrentDictionary<int, KeyValuePair<DateTime, string>>();

/// <summary>
/// This is an Elmah event used by the elmah engine when sending out emails. It provides an opportunity to weed out 
/// irrelavent emails.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void ErrorMail_Filtering(object sender, ExceptionFilterEventArgs e)
{
    preventSpammingDigestEmail(e);
}

/// <summary>
/// Prevents spamming by throttling emails to 5 minute intervals.
/// </summary>
/// <param name="e"></param>
private static void preventSpammingDigestEmail(ExceptionFilterEventArgs e)
{
    DateTime roundedTimeStamp = DateTime.Now.RoundUp(TimeSpan.FromMinutes(5));
    string serialisedException = Util.SerializeException(e.Exception);

    var lastRaisedException = new KeyValuePair<DateTime, string>
        (roundedTimeStamp, serialisedException);

    int key = lastRaisedException.GetHashCode();

    bool errorHasAlreadyBeenRaised = _concurrent.ContainsKey(key);

    // If event has already been raised in the last five minutes dont raise again
    if (errorHasAlreadyBeenRaised)
    {
        e.Dismiss();
        return;
    }

    // Record that it has been raised
    _concurrent.TryAdd(key, lastRaisedException);

    // Clean up existing entries
    Task.Factory.StartNew(() =>
        {
            var toRemove =
                _concurrent.Where(pair => pair.Value.Key < DateTime.Now.Date).Select(pair => pair.Key).ToArray();

            foreach (var i in toRemove)
            {
                KeyValuePair<DateTime, string> keyValuePair;
                _concurrent.TryRemove(i, out keyValuePair);
            }
        });
}

private static string SerializeException(Exception e, string exceptionMessage = "")
{
    if (e == null)
        return String.Empty; 
    exceptionMessage = String.Format("{0}{1}{2}\n{3}", exceptionMessage, (exceptionMessage == String.Empty) 
        ? String.Empty 
        : "\n\n", e.Message, e.StackTrace);
    if (e.InnerException != null) 
        exceptionMessage = SerializeException(e.InnerException, exceptionMessage); 
    return exceptionMessage;
}
鯉魚旗 2024-08-23 22:41:24

我不知道 Elmah 是否具有该功能(文档没有提及),但 ASP.NET 的运行状况监控具有: https://web.archive.org/web/20210513222150/http://aspnet.4guysfromrolla.com/articles/032107- 1.aspx

我最终为我的 CMS 编写了自己的事件日志记录、通知和汇总系统...我散列每个异常的堆栈跟踪,并使用它来“汇总”类似事件(一个 Web 应用程序)如果出现问题,可能会在不到一秒的时间内出现数千个异常)。

我将通知期限配置为 1 天 - 每天我只收到第一个错误实例的通知。最新的错误实例始终会被保存,但较旧的实例会被“清理”到最后 20 个左右,具体取决于频率等......

它与身份验证系统集成,因此管理员/开发人员会获得一个“收件箱”他们订阅的事件的数量,并且可以实时查看调试信息,同时防止未经身份验证的用户看到任何调试信息。

真的很好...而且由于它是通用的,它也适用于非错误事件,例如出版物、用户更改通知等。

我很好奇是否有人会对作为库公开的这种系统感兴趣?

I don't know if Elmah has that capability (the docs don't mention it), but ASP.NET's health monitoring does: https://web.archive.org/web/20210513222150/http://aspnet.4guysfromrolla.com/articles/032107-1.aspx

I ended up writing my own event logging, notification, and rollup system for my CMS... I hash the stack trace of each exception and use it to 'roll-up' similar events (a web app may get thousands of exceptions in less than a second if something goes wrong).

I configured my notification period to 1 day - I only get notified of the first instance of an error each day. The latest instance of an error is always saved, but older instances are 'cleaned up' to the last 20 or so, depending upon frequency, etc....

It integrates with the authentication system, so administrators/developers get an 'inbox' of events they have subscribed to, and can look at debug info in real time, while preventing unathenticated users from seeing any debugging info at all.

Really nice... And since it's generic, it works for non-error events also, like publications, user change notifications, etc.

I'm curious if anyone would be interested in that kind of system exposed as a library?

墨落成白 2024-08-23 22:41:24

我遇到了类似的问题,并选择对 ELMAH 使用 log-to-SQL 方法。我在 Web 服务器上使用 SQLExpress 2008(免费版),然后设置 SQL 报告以每天早上发送摘要电子邮件。

此方法不需要编码,只需设置 SQL 服务器和报告服务。它的好处是让您可以对数月的错误日志运行报告,而不仅仅是每天查看它们。此外,您还可以根据需要频繁地安排报告。

ELMAH wiki 页面提供了有关如何设置 web.config 以指向 SQL 的信息服务器。一旦数据存储在 SQL 中,就有许多选项可用于获取数据,但我发现 SQL Express 报告服务非常适合我的需求。

I had a similar problem and opted to use the log-to-SQL method for ELMAH. I used SQLExpress 2008 (free-version) on my Web server and then setup SQL Reporting to send digest emails every morning.

This method required no coding, just setup of the SQL server and reporting services. It has the benefit of letting you run reports on months of error logs rather than just seeing them daily. In addition, though, you can schedule reports as frequently as you like.

The ELMAH wiki page has information on how to setup the web.config to point to a SQL server. There are many options for getting the data out, once the data is in SQL but I find the SQL Express reporting services were perfect for my needs.

太阳哥哥 2024-08-23 22:41:24

这个 codeplex 项目 ASP.NET Exception Reporting 是 Elmah 的包装器,看起来很有前途。 http://aspexceptionreporter.codeplex.com/

This codeplex project ASP.NET Exception Reporting which is a wrapper for Elmah looks promising. http://aspexceptionreporter.codeplex.com/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文