限制 Elmah 发送的电子邮件数量
Posted
技术标签:
【中文标题】限制 Elmah 发送的电子邮件数量【英文标题】:Limiting the Number of Emails Sent By Elmah 【发布时间】:2011-01-01 07:28:57 【问题描述】:有人知道像使用 Health Monitoring 那样限制 Elmah 在一段时间内发送的电子邮件数量的好方法吗?
我希望能够将每个页面中每个错误的电子邮件限制为仅每小时一次针对该特定错误和页面发送一封电子邮件。
查看 elmah 文档,它看起来像使用:
void ErrorMail_Filtering(object sender, ExceptionFilterEventArgs e)
// perform filtering here
在 global.ascx 文件中可能是一个选项。我可以为每个应用程序设置一个静态对象,其中包含一些错误详细信息和记录的时间,并检查它并在需要时取消电子邮件通知?
有没有人有更好的解决方案或他们现在正在使用的示例?
【问题讨论】:
【参考方案1】:我使用与您的问题相同的方法编写了此内容。看起来效果不错。
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("012\n3", exceptionMessage, (exceptionMessage == String.Empty)
? String.Empty
: "\n\n", e.Message, e.StackTrace);
if (e.InnerException != null)
exceptionMessage = SerializeException(e.InnerException, exceptionMessage);
return exceptionMessage;
【讨论】:
我真的不想污染答案,但这里是代码。 public class Util private static string SerializeException(Exception e, string exceptionMessage = string.Empty) if (e == null) return String.Empty; exceptionMessage = String.Format("012\n3", exceptionMessage, (exceptionMessage == String.Empty) ? String.Empty : "\n\n", e.Message, e 。堆栈跟踪); if (e.InnerException != null) exceptionMessage = SerializeException(e.InnerException, exceptionMessage);返回异常消息; 【参考方案2】:这个作为 Elmah 包装器的 codeplex 项目 ASP.NET 异常报告看起来很有前景。 http://aspexceptionreporter.codeplex.com/
【讨论】:
【参考方案3】:我不知道 Elmah 是否有这种能力(文档没有提到),但是 ASP.NET 的健康监控有:http://aspnet.4guysfromrolla.com/articles/032107-1.aspx
我最终为我的 CMS 编写了自己的事件记录、通知和汇总系统...我对每个异常的堆栈跟踪进行哈希处理,并使用它来“汇总”类似的事件(一个网络应用程序可能会获得数千个如果出现问题,会在不到一秒的时间内出现异常)。
我将通知期限配置为 1 天 - 我每天只会收到第一个错误实例的通知。总是保存最新的错误实例,但较旧的实例被“清理”到最后 20 个左右,具体取决于频率等......
它与身份验证系统集成,因此管理员/开发人员可以获得他们订阅的事件的“收件箱”,并可以实时查看调试信息,同时防止未经身份验证的用户看到任何调试信息。
真的很好...而且由于它是通用的,它也适用于非错误事件,如发布、用户更改通知等。
我很好奇是否有人会对这种作为库公开的系统感兴趣?
【讨论】:
我认为人们会感兴趣,或者至少我会。【参考方案4】:我遇到了类似的问题,并选择对 ELMAH 使用 log-to-SQL 方法。我在我的 Web 服务器上使用 SQLExpress 2008(免费版),然后设置 SQL Reporting 以每天早上发送摘要电子邮件。
此方法无需编码,只需设置 SQL 服务器和报告服务。它的好处是让您可以在几个月的错误日志上运行报告,而不仅仅是每天查看它们。此外,您可以根据需要随时安排报告。
ELMAH wiki page 包含有关如何设置 web.config 以指向 SQL 服务器的信息。一旦数据在 SQL 中,就有很多方法可以获取数据,但我发现 SQL Express 报告服务非常适合我的需求。
【讨论】:
这似乎是合理的。在这种特殊情况下,我只是没有那种访问权限,但对于我自己的项目,我可能会走这条路。以上是关于限制 Elmah 发送的电子邮件数量的主要内容,如果未能解决你的问题,请参考以下文章