简体   繁体   中英

Does System.Diagnostics.Trace have any performance degredation?

I am looking for a simple native .NET error logging solution. I am not interested in using log4net, Elmah or any other logging library. 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

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:

  <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. 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. 1500 bytes over the network leads to 1,5GB/min of mail data. This will eat ca. 25 MBit of your network bandwidth. 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.

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

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

However, any supplemental code that's not actually found inside the call to TraceError will still run. So in your case, the call to HandleExceptionsAttribute.TraceError() will still be executed--it will just return immediately without doing anything.

// 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.

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. See https://msdn.microsoft.com/en-us/library/Bb398933.aspx for a good start.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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