简体   繁体   English

如果应用程序崩溃,是否可以配置将哪些信息存储在Windows事件日志中?

[英]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. 有时,错误会触发那些不可恢复的异常之一(例如StackOverflowException ),导致我们整个ASP.NET MVC应用程序崩溃。 When this happens, the Windows event log typically contains some information about the error, although it is minimal. 发生这种情况时,Windows事件日志通常包含一些有关该错误的信息,尽管该信息很少。 Currently, for example, we have what we believe is a StackOverflowException being thrown inside a reflection invocation. 例如,当前,我们认为反射调用中引发了StackOverflowException In such cases, the event log contains some basic information about the outer TargetInvocationException and nothing that will let us pinpoint the problem. 在这种情况下,事件日志包含有关外部TargetInvocationException一些基本信息,而没有任何内容可以让我们查明问题所在。 My question is, is it possible to configure something in .NET/IIS/Windows to log more information when this happens? 我的问题是,是否可能在.NET / IIS / Windows中配置某些内容以在发生这种情况时记录更多信息? 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. 例如,如果我们可以获得完整异常的前N个字符(包括堆栈跟踪和内部异常),则我们可以轻松调试并解决该问题。

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. 您无法控制其他类写入日志的内容,但是可以捕获global.asax文件中的异常并进行自己的日志记录。 I tend to use a combination of database logging and email notifications. 我倾向于结合使用数据库日志记录和电子邮件通知。

--global.asax --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 --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);
    }

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

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