有时,错误会触发导致整个ASP.NET MVC应用程序崩溃的不可恢复的异常之一(例如StackOverflowException
)。发生这种情况时,Windows事件日志通常包含有关错误的一些信息,尽管它很小。例如,目前,我们认为在反射调用中抛出了StackOverflowException
。在这种情况下,事件日志包含有关外部TargetInvocationException
的一些基本信息,并且没有任何内容可以让我们查明问题。我的问题是,是否可以在.NET / IIS / Windows中配置某些内容以在发生这种情况时记录更多信息?例如,如果我们可以获得完整异常的前N个字符(包括堆栈跟踪和内部异常),我们可以轻松地调试并解决问题。
答案 0 :(得分:0)
您无法控制其他类写入日志的内容,但您可以捕获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
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>>> {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);
}