0

Code below is used in Global.asax to log error is ASP.NET MVC3 application.

Some errors are realated to timeouts reading data from PostgreSql server.

How to add request duration logging to this ? Is there some propaerty which provides request start time in MVC3 ?

I looked into samples in

http://www.codeproject.com/Articles/550510/Exception-Handling-and-NET

http://msdn.microsoft.com/en-us/library/24395wz3(v=vs.100).aspx

Global.asax - Application_Error - How can I get Page data?

http://www.velocityreviews.com/forums/t99686-global-asax-application_error-how-to-get-informations-about-the-exception.html

but havent found such sample.

    void Application_Error(object sender, EventArgs e)
    {
        var sb = new StringBuilder();
        var url = HttpContext.Current.Request.Url;
        sb.AppendLine("Url " + url.ToString());
        foreach (var d in Request.Form.AllKeys)
                sb.AppendLine(d.ToString() + ":" + Request.Form[d].ToString());
        sb.AppendLine();
        foreach (var d in Request.Headers.AllKeys)
                sb.AppendLine(d.ToString() + "\t" + Request.Headers[d].ToString());
        Exception exception = Server.GetLastError();
        MyLogger.WriteException(exception, "Application_Error", sb.ToString());
    }
Community
  • 1
  • 1
Andrus
  • 26,339
  • 60
  • 204
  • 378
  • What type of errors do you want to catch the duration of? If you want to time those that actually maps against a route you could use a global filter for it. – Tomas Jansson Sep 23 '13 at 08:36

3 Answers3

1

You can add request duration for the paths like this in config file

<location path="your path here">
<system.web>
    <httpRuntime executionTimeout="600" />
</system.web>

or you can set it into your controller also

HttpContext.Server.ScriptTimeout = timeout value here;
1

If by request, you are reffering to HTTP request, you can use Application_BeginRequest and Application_EndRequest in combination with ThreadStatic Stopwatch like this:

public class MvcApplication : System.Web.HttpApplication
{
    [ThreadStatic]
    private static Stopwatch stopwatch;

    protected void Application_Start()
    {
        //...
    }

    protected void Application_BeginRequest()
    {
        stopwatch = new Stopwatch();
        stopwatch.Start();
    }

    protected void Application_EndRequest()
    {
        stopwatch.Stop();
        var elapsedTime = stopwatch.ElapsedMilliseconds;
        //log time...
        stopwatch.Reset();
    }
}

And in your case, instead of Application_EndRequest, you can use

protected void Application_Error(object sender, EventArgs e)
{
    //...
    stopwatch.Stop();
    var time = stopwatch.ElapsedMilliseconds;
    stopwatch.Reset();
    //...
}

You should be aware of some problems when ThreadStatic : look here . If you don't want to use ThreadStatic, you can use HttpContext.Current.Items like this:

protected void Application_BeginRequest()
{
    var stopwatch = new Stopwatch();
    stopwatch = new Stopwatch();
    stopwatch.Start();
    HttpContext.Current.Items.Add("RequestStopwatch", stopwatch);
}

protected void Application_Error(object sender, EventArgs e)
{
    //...
    if (HttpContext.Current.Items["RequestStopwatch"] != null)
    {
        var stopwatch = (Stopwatch)HttpContext.Current.Items["RequestStopwatch"];
        stopwatch.Stop();
        var time = stopwatch.ElapsedMilliseconds;
        //log time...
        HttpContext.Current.Items.Remove("RequestStopwatch");
    }
    //...
}
Bojan Kaurin
  • 262
  • 1
  • 4
  • why `if (HttpContext.Current.Items["RequestStopwatch"] != null)` check is used ? It shuld be not null always – Andrus Sep 24 '13 at 20:14
  • Yes, you are correct, it shouldn't be null, so this if condition could be removed if you are sure that it will not be removed somewhere inside request. I've put this here just in case that someone somewhere inside request (for example: Action method inside controller) removes "RequestStopwatch" item. – Bojan Kaurin Oct 07 '13 at 12:24
0

You time it yourself. In a BeginRequest handler start a stopwatch then save it to HttpContext.Items. Then in the error handler, get it back and stop it. Same approach for timeing the whole request, only you do the stopping part in EndRequest.

Take a look at this example , it's a http module which times the request then adds it to repsonse.

MikeSW
  • 16,140
  • 3
  • 39
  • 53