Limiting the Number of Emails Sent By Elmah

陌路散爱 提交于 2019-12-02 23:39:44

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);
            }
        });
}

I don't know if Elmah has that capability (the docs don't mention it), but ASP.NET's health monitoring does: 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?

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.

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!