简体   繁体   中英

Is it possible to configure what information gets stored in the Windows event log in the event of an application crash?

Occasionally, a bug will trigger one of those unrecoverable exceptions (eg a StackOverflowException ) that causes our entire ASP.NET MVC application to crash. When this happens, the Windows event log typically contains some information about the error, although it is minimal. Currently, for example, we have what we believe is a StackOverflowException being thrown inside a reflection invocation. In such cases, the event log contains some basic information about the outer TargetInvocationException and nothing that will let us pinpoint the problem. My question is, is it possible to configure something in .NET/IIS/Windows to log more information when this happens? If we could get, for example, the first N characters of the full exception (including stack trace and inner exceptions), we could easily debug and fix the issue.

You can't control what another class writes to the log, but you can capture exceptions in the global.asax file and do your own logging. I tend to use a combination of database logging and email notifications.

--global.asax

    void Application_Error(object sender, EventArgs e)
    {
        // Code that runs when an unhandled error occurs
        Exception exSvr = Server.GetLastError();

        if (exSvr == null)
            return;

        if (exSvr.Message == "The client disconnected.")
        {
            // I don't want to be notified everytime someone closes
            //   the browser mid-request.
            return;
        }

        if (exSvr is System.Threading.ThreadAbortException || exSvr.InnerException is System.Threading.ThreadAbortException || exSvr.Message.StartsWith("Thread was being aborted") || (exSvr.InnerException != null && exSvr.InnerException.Message.StartsWith("Thread was being aborted")))
        {
            // So we don't get notified everytime .NET kills a thread.
            // NOTE:  This error is how .NET kills a thread, and will happen every time we call Response.Redirect("", true)
            return;
        }

        ErrorHandler.SendServerErrMsg("Application Error", exSvr, HttpContext.Current);
    }

--ErrorHandler

    public static void SendServerErrMsg(string codeSection, Exception exSvr, HttpContext context, SeverityLevel lvl = SeverityLevel.Warning)
    {
        if (_config == null || !_config.EnableEmailAlerts)
            return;

        if (context != null && context.Request != null && context.Request.Url != null && context.Request.Url.IsLoopback && !_config.SendAlertsInDebugMode)
            return;

        if (context != null && context.IsDebuggingEnabled && !_config.SendAlertsInDebugMode)
            return;

        // Attempt to get the currently logged in user.
        System.Web.Security.MembershipUser curUsr = null;
        try
        { curUsr = System.Web.Security.Membership.GetUser(); }
        catch { } // If it fails, don't worry about it.

        // Set the message's subject line.
        string subject = _config.ApplicationName + " Exception - " + HttpUtility.HtmlEncode(codeSection);

        // Build the page body in a StringBuilder object.
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        if (context != null && context.Request != null)
            sb.AppendLine(string.Format("<h2>{0}</h2>", HttpUtility.HtmlEncode(context.Request.ApplicationPath)));
        sb.AppendLine("<p>The following exception has occurred:</p>");
        sb.AppendLine("<ul>");
        Exception innerEx = exSvr;
        while (innerEx != null)
        {
            sb.AppendLine(string.Format("<li>{0}</li>", HttpUtility.HtmlEncode(innerEx.Message)));
            innerEx = innerEx.InnerException;
        }
        sb.AppendLine("</ul>");
        sb.AppendLine("<p/>");
        if (exSvr.TargetSite != null)
            sb.AppendLine(string.Format("<p>Target Site: {0} {1} (in {2})</p>", exSvr.TargetSite.MemberType, exSvr.TargetSite.Name, exSvr.TargetSite.DeclaringType));
        else
            sb.AppendLine("<p>Target Site: N/A</p>");
        sb.AppendLine("<p/>");
        sb.AppendLine("<hr />");
        if (context != null && context.Request != null)
        {
            HttpRequest req = context.Request;
            sb.AppendLine("<p>");
            sb.AppendLine(string.Format("<div>Request URL: {0}</div>", HttpUtility.HtmlEncode(req.Url.ToString())));
            sb.AppendLine(string.Format("<div>Request Path: {0}</div>", HttpUtility.HtmlEncode(req.FilePath)));
            sb.AppendLine(string.Format("<div>User: {0}</div>", (curUsr != null) ? HttpUtility.HtmlEncode(curUsr.UserName) : "Unknown"));
            sb.AppendLine(string.Format("<div>User Host Address: {0}</div>", HttpUtility.HtmlEncode(req.UserHostAddress)));
            // We're going to try a reverse DNS search on the IP address.  Failover,
            //   just uses the UserHostName value from the HttpContext object.
            string hostName = null;
            try { hostName = System.Net.Dns.GetHostEntry(req.UserHostAddress).HostName; }
            catch { hostName = null; }
            if (hostName == null) hostName = req.UserHostName;
            sb.AppendLine(string.Format("<div>User Host Name: {0}</div>", HttpUtility.HtmlEncode(hostName)));
            sb.AppendLine(string.Format("<div>User Agent: {0}</div>", HttpUtility.HtmlEncode(req.UserAgent)));
            sb.AppendLine(string.Format("<div>Server Name: {0}</div>", (context.Server != null ? HttpUtility.HtmlEncode(context.Server.MachineName) : "Unknown")));
            sb.AppendLine(string.Format("<div>Request Identity: {0}</div>", (req.LogonUserIdentity != null ? HttpUtility.HtmlEncode(req.LogonUserIdentity.Name) : "Unknown")));

            sb.AppendLine("</p>");
            sb.AppendLine("<hr />");
        }
        sb.AppendLine("<p>Stack trace follows:</p>");
        Exception ex = exSvr;
        while (ex != null)
        {
            sb.AppendLine("<p>");
            sb.AppendLine(string.Format("<b>&gt;&gt;&nbsp;{0}:</b> {1} in {2}<br/>", ex.GetType().Name, HttpUtility.HtmlEncode(ex.Message), HttpUtility.HtmlEncode(ex.Source)));
            sb.AppendLine(HttpUtility.HtmlEncode(ex.StackTrace));
            sb.AppendLine("</p>");
            ex = ex.InnerException;
        }
        if (context!=null && context.Trace.IsEnabled)
        {
            sb.AppendLine("<hr />");
            sb.AppendLine("<p>Web Trace:</p>");
            sb.AppendLine(string.Format("<p>{0}</p>", HttpUtility.HtmlEncode(context.Trace.ToString())));
        }

        EmailHelper.SendEmail(GetAlertContacts(), subject.Trim(), sb.ToString().Trim(), true);
    }

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