Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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>
like image 316
Cyberdrew Avatar asked Aug 28 '15 20:08

Cyberdrew


1 Answers

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 e.g. 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. E.g. 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.

like image 158
Alois Kraus Avatar answered Oct 12 '22 22:10

Alois Kraus