简体   繁体   English

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

[英]Does System.Diagnostics.Trace have any performance degredation?

I am looking for a simple native .NET error logging solution. 我正在寻找一个简单的本机.NET错误日志记录解决方案。 I am not interested in using log4net, Elmah or any other logging library. 我对使用log4net,Elmah或任何其他日志记录库不感兴趣。 Below is what I am planning on using. 以下是我计划使用的内容。 My question is performance on my site is paramount and does this flow introduce any performance concerns? 我的问题是我的网站上的性能是至关重要的,这个流程是否会引入任何性能问题?

Global.asax Global.asax中

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

Handle Exceptions Attribute: 处理异常属性:

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: 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>

Getting an EMail for every exception? 为每个例外获取电子邮件? I wish you good luck with that. 祝你好运。祝你好运。

The code as it is will not work well. 代码本身不会很好。 It is not about Trace.TraceError itself but what you want to do. 它不是关于Trace.TraceError本身,而是你想做什么。 I have seen sometimes error loops which produce millions of exceptions within minutes. 我有时会看到错误循环,它会在几分钟内产生数百万个异常。 You are working towards a self inflicted denial of service attack. 您正在努力实现自我拒绝服务攻击。 Lets do some math. 让我们做一些数学。 1 million exceptions per minute with a text blob of ca. 每分钟100万个例外,文本blob为ca. 1500 bytes over the network leads to 1,5GB/min of mail data. 网络上的1500字节导致1,5GB / min的邮件数据。 This will eat ca. 这会吃大约 25 MBit of your network bandwidth. 25 MBit的网络带宽。 And this is a conservative estimate. 这是一个保守的估计。 But if that happens you will run out of memory very quickly. 但如果发生这种情况,你将很快耗尽内存。 The async task approach will queue the tasks. 异步任务方法将对任务进行排队。 Since you will send emails slower than you can produce exceptions you will quite soon get an OutOfMemoryException which you will also try to send via mail .... At least you will get a free restart quite quickly before the denial of service situation will persist. 由于您发送的电子邮件速度比生成异常的速度慢,您很快就会收到OutOfMemoryException,您也会尝试通过邮件发送....至少在拒绝服务情况持续之前,您将很快获得免费重启。

A better way would be to write a custom MailTraceListener which will aggregate the exceptions and throttle the rate of sent exceptions per mail eg to at most 1/minute. 更好的方法是编写一个自定义MailTraceListener,它将聚合异常并限制每个邮件发送的异常的速率,例如最多1分钟。 Then you can add a RollingFileTraceListener (not part of .NET. There is a reason why external logging libraries exist) which will log to a flat file and you can send an aggregated summary via mail. 然后,您可以添加RollingFileTraceListener(不是.NET的一部分。存在外部日志库存在的原因),它将记录到平面文件,您可以通过邮件发送聚合摘要。 It also makes sense to detect duplicate exceptions by their exception message to log only a summary. 通过异常消息检测重复异常以仅记录摘要也是有意义的。 Eg the first one is logged always and then you check againts the last exception is identical with the new one. 例如,始终记录第一个,然后再次检查最后一个异常是否与新异常相同。 If yes increment a counter and keep doing that until a different one shows up. 如果是,则递增计数器并继续这样做,直到出现另一个计数器。 Then you can write a nice summary that 10 billion exceptions did just occur and you did log none of them except the first one. 然后你可以写一个很好的总结,只发生了100亿个例外,除了第一个例外,你没有记录它们。

Exceptions in itself are slow. 例外本身很慢。 If you trace them or not plays no role. 如果你追踪他们或不扮演角色。 You can optimize away the Trace call but this is your least concern. 您可以优化Trace调用,但这是您最不关心的问题。 Stack unwinding is the most expensive part of exception handling. 堆栈展开是异常处理中最昂贵的部分。 The main performance hit of tracing comes your configured output device. 跟踪的主要性能来自您配置的输出设备。 You will find that out quite quickly if you profile it. 如果您对它进行分析,您会很快发现它。

As I have outlined above a good error handling strategy is not easy to implement since you are dealing with exceptional cases where pretty much anything can happen. 正如我上面概述的那样,一个好的错误处理策略并不容易实现,因为你正在处理几乎任何事情都可能发生的异常情况。 Including that your handling of exceptions becomes part of the problem. 包括您对异常的处理成为问题的一部分。 You need to test that thoroughly or you will find that it works perfectly if no error happens but for some strange reason it crashes when some corner case exception occurs. 你需要对它进行彻底测试,否则你会发现如果没有错误发生它会完美运行但是由于某些奇怪的原因它会在发生一些极端情况异常时崩溃。

It depends. 这取决于。

TraceError uses a conditional compiler attribute, which means that if you compile with the TRACE flag turned off (as in RELEASE mode), then all calls to TraceError will be removed from your compiled code. TraceError使用条件编译器属性,这意味着如果在关闭 TRACE标志的情况下进行编译(如在RELEASE模式下),则将从编译的代码中删除对TraceError的所有调用。 Ostensibly this would remove most performance concerns for live code, because with performance being so paramount, you are certainly going to compile in RELEASE mode. 表面上这会消除对实时代码的大多数性能问题,因为性能是如此至关重要,你肯定会在RELEASE模式下编译。

However, any supplemental code that's not actually found inside the call to TraceError will still run. 但是,在TraceError调用中实际找不到的任何补充代码仍将运行。 So in your case, the call to HandleExceptionsAttribute.TraceError() will still be executed--it will just return immediately without doing anything. 因此,在您的情况下,仍将执行对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); 

And, of course, the other down-side is that you're not going to get any information from your traces in live environments, where they may prove to be pretty useful. 而且,当然,另一个缺点是你不会从现场环境中的痕迹中获取任何信息,在这些环境中它们可能被证明是非常有用的。 In your case, that means that any exceptions thrown in your live system will be completely invisible to you. 在您的情况下,这意味着您的实时系统中抛出的任何异常对您来说都是完全不可见的。 You'll have no indication that anything is wrong if users don't complain about the results. 如果用户不抱怨结果,您将没有任何迹象表明存在任何问题。

Correction 更正

Apparently what I said above is true about Debug , but Visual Studio will leave the TRACE flag active during Release mode builds by default. 显然我上面说的是关于Debug ,但默认情况下Visual Studio会在Release模式构建期间保持TRACE标志处于活动状态。

For web apps there is no reason to roll your own -- the framework has the ability to notify you of any unhanded exception through configuration alone using ASP.NET health monitoring. 对于Web应用程序,没有理由自己动手 - 框架能够通过使用ASP.NET运行状况监视单独通过配置通知您任何无法处理的异常。 See https://msdn.microsoft.com/en-us/library/Bb398933.aspx for a good start. 请参阅https://msdn.microsoft.com/en-us/library/Bb398933.aspx以获得良好的开端。

Also keep in mind the code you've got is going to be ugly. 还要记住,你得到的代码将是丑陋的。 What happens when the email server is misconfigured throwing exceptions inside your exception handlers. 当电子邮件服务器配置错误,在异常处理程序中抛出异常时会发生什么。 Logging errors when things are crashing without effecting performance is a non-trivial problem, it is highly advisable to use a well tested library rather than trying to roll your own solution here. 在事情崩溃而不影响性能的情况下记录错误是一个非常重要的问题,建议使用经过良好测试的库而不是尝试在此处推出自己的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM