System.Diagnostics.Trace是否有任何性能降级?

时间:2015-08-28 20:14:52

标签: c# asp.net-mvc-5 trace system.diagnostics

我正在寻找一个简单的原生.NET错误记录解决方案。我对使用log4net,Elmah或任何其他日志记录库不感兴趣。以下是我计划使用的内容。我的问题是我网站上的性能是最重要的,这个流程是否会引入任何性能问题?

Global.asax中

protected void Application_Start(object sender, EventArgs e)
        {
            GlobalFilters.Filters.Add(new HandleExceptionsAttribute());
        }

处理异常属性:

public sealed class HandleExceptionsAttribute : HandleErrorAttribute
    {
        private void TraceError(Exception _this)
        {
            Trace.TraceError("{0} Exception {1}", DateTime.Now.ToString("M/d/yyyy h:mmtt"), _this);
        }

        public override void OnException(ExceptionContext filterContext)
        {
            var ex = filterContext.Exception;
            TraceError(ex);
            Task.Run(() =>
            {
                using (var msg = new MailMessage(ConfigurationManager.AppSettings["SendErrorsFrom"], ConfigurationManager.AppSettings["SendErrorsTo"]))
                {
                    msg.Subject = ex.Message;
                    msg.Body = ex.StackTrace;
                    using (var smtp = new SmtpClient())
                        smtp.Send(msg);
                }
            });
        }
    }

的web.config:

  <system.diagnostics>
    <trace autoflush="true" indentsize="4">
      <listeners>
        <add name="textWriterListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="logs\log.txt"/>
        <add name="eventLogListener" type="System.Diagnostics.EventLogTraceListener" initializeData="Base Test" />
        <remove name="Default"/>
      </listeners>
    </trace>
  </system.diagnostics>

3 个答案:

答案 0 :(得分:4)

这取决于。

TraceError使用条件编译器属性,这意味着如果编译时TRACE标志已关闭 off (如在RELEASE模式下),则所有对TraceError的调用都将从您的删除编译代码。表面上这会消除对实时代码的大多数性能问题,因为性能是如此至关重要,你肯定会在RELEASE模式下编译。

但是,在TraceError调用中实际找不到的任何补充代码仍会运行。因此,在您的情况下,对HandleExceptionsAttribute.TraceError()的调用仍将执行 - 它将立即返回而不执行任何操作。

// This code sticks around, and could still have performance implications.
var additionalInfo = GoGetMoreInformation(); 
// This code disappears when compiled
Trace.TraceError("Something went wrong: {0}", additionalInfo); 

当然,另一个缺点是你不会在现场环境中从你的踪迹中获取任何信息,在这些环境中它们可能被证明是非常有用的。在您的情况下,这意味着您的实时系统中抛出的任何异常对您来说都是完全不可见的。如果用户不抱怨结果,你就没有迹象表明出现了任何问题。

校正

显然我上面所说的Debug是正确的,但默认情况下,Visual Studio会在发布模式构建期间保持TRACE标志处于活动状态。

答案 1 :(得分:4)

为每个例外获取电子邮件?祝你好运。祝你好运。

代码本身不会很好用。它不是关于Trace.TraceError本身,而是你想做什么。我有时会看到错误循环,它会在几分钟内产生数百万个异常。您正在努力实现自我拒绝服务攻击。让我们做一些数学。每分钟100万个例外,文本blob为ca.网络上的1500字节导致1,5GB / min的邮件数据。这会吃大约25 MBit的网络带宽。这是一个保守的估计。但如果发生这种情况,你将很快耗尽内存。异步任务方法将对任务进行排队。由于您发送的电子邮件速度比生成异常的速度慢,您很快就会收到OutOfMemoryException,您也会尝试通过邮件发送....至少在拒绝服务情况持续之前,您将很快获得免费重启。

更好的方法是编写一个自定义MailTraceListener,它将聚合异常并限制每个邮件发送的异常的速率,例如:最多1分钟。然后,您可以添加RollingFileTraceListener(不是.NET的一部分。存在外部日志库存在的原因),它将记录到平面文件,您可以通过邮件发送聚合摘要。 通过异常消息检测重复异常以仅记录摘要也是有意义的。例如。始终记录第一个,然后再次检查最后一个异常是否与新异常相同。如果是,则递增计数器并继续这样做,直到出现另一个计数器。然后你可以写一个很好的总结,只发生了100亿个例外,除了第一个例外,你没有记录它们。

例外本身很慢。如果你追踪他们或不扮演角色。您可以优化Trace调用,但这是您最不关心的问题。堆栈展开是异常处理中最昂贵的部分。跟踪的主要性能来自您配置的输出设备。如果您对其进行分析,您会很快发现它。

正如我上面所概述的那样,一个好的错误处理策略并不容易实现,因为你正在处理几乎任何事情都可能发生的异常情况。包括您对异常的处理成为问题的一部分。你需要对它进行彻底测试,否则你会发现如果没有错误发生它会完美运行但是由于某些奇怪的原因它会在发生一些极端情况异常时崩溃。

答案 2 :(得分:0)

对于Web应用程序,没有理由自己动手 - 框架能够通过使用ASP.NET运行状况监视单独通过配置通知您任何无法处理的异常。请参阅https://msdn.microsoft.com/en-us/library/Bb398933.aspx以获得良好的开端。

还要记住你得到的代码会变得很难看。当电子邮件服务器配置错误,在异常处理程序中抛出异常时会发生什么。在事情崩溃而不影响性能的情况下记录错误是一个非常重要的问题,建议使用经过良好测试的库而不是尝试在此处推出自己的解决方案。