昨天线上日志有错误提示。内容大概是返回到页面提示的异常信息后,日志又标记了和业务不相关的Exception。初步诊断程序没有出现异常,异常信息外包了一层try..catch,catch捕捉到的exception的一些代码错误位置等信息。这让我们当时很迷茫。
try
{
if (sfbz)
{
throw new FailedException("操作异常,已收费处方不允许变更");
}
}
catch (Exception e)
{
LogCore.Error("SaveMedicalRecord error", e);
throw;
}
经过研究发现,主要是框架底层两个方面的问题
1.FailedException派生自基类Exception,根据业务需求重新定义了对象,却没有继承基类的message虚拟字段。导致Exception无法捕捉派生类的Message详情,抛出基类的异常信息。
//...FailedException
using System;
/// <summary>
/// 业务处理失败的可预测异常
/// </summary>
public class FailedException : Exception
{
/// <summary>
/// 错误代码
/// </summary>
public string Code
{
get;
set;
}
/// <summary>
/// 错误描述
/// </summary>
public string Msg
{
get;
set;
}
/// <summary>
/// 是否记入日志,默认false,不记入日志
/// </summary>
public bool Log
{
get;
set;
}
/// <summary>
/// 构造函数
/// </summary>
public FailedException()
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="msg">错误描述</param>
public FailedException(string msg)
{
Msg = msg;
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="code">错误代码</param>
/// <param name="msg">错误描述</param>
public FailedException(string code, string msg)
{
Code = code;
Msg = msg;
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="code">错误代码</param>
/// <param name="msg">错误描述</param>
/// <param name="log">是否记入日志</param>
public FailedException(string code, string msg, bool log)
{
Code = code;
Msg = msg;
Log = log;
}
}
2.日志问题。系统如何判断异常是系统用户的提示还是代码bug呢?先展示代码
/// <summary>
/// 过滤器 全局异常捕获,防止返回500
/// </summary>
public class HandlerErrorAttribute : HandleErrorAttribute
{
/// <summary>
/// (重写)Called when an exception occurs.
/// </summary>
/// <param name="context"></param>
public override void OnException(ExceptionContext context)
{
FailedException ex2;
if (!(context.Exception is FailedException))
{
ILogger logger = AppLogger.Instance;
if (logger != null)
{
Exception ex = context.Exception;
while (ex.InnerException != null)
{
ex = ex.InnerException;
}
logger.Error(ex.Message, ex);
}
}
else
if (context.RequestContext.HttpContext.Request.IsAjaxRequest())
{
context.ExceptionHandled = true;
context.HttpContext.Response.StatusCode = 200;
Exception innerEx = context.Exception;
if (!(innerEx is FailedException))
{
while (innerEx.InnerException != null)
{
innerEx = innerEx.InnerException;
}
}
context.Result = new ContentResult
{
Content = new AjaxResult
{
state = ResultType.error.ToString(),
code = ((context.Exception is FailedException) ? (((FailedException)context.Exception).Code ?? "").ToUpper() : "SYSTEM_ERROR"),
message = ((context.Exception is FailedException) ? ((FailedException)context.Exception).Msg : innerEx.Message),
exStackTrace = ((context.Exception is FailedException) ? null : innerEx.StackTrace),
InnerException = ((innerEx is FailedException) ? null : innerEx.InnerException)
}.ToJson()
};
}
else
{
base.OnException(context);
}
}
}
代码显示,只要捕捉到异常,就进HandlerErrorAttribute.OnException().主要是两个判断。第一个if非Failedception时为true。意思是Exception进入到该断代码。以下是记录日志详情的地方
logger.Error(ex.Message, ex);
很明显抛出"SaveMedicalRecord error" 异常日志是这段代码记录的。
第二个判断是ajax请求。主要是把当前返回结果设置为成功,整合当前错误信息为json串,用result接收后返回到页面给用户提示。诠释了下面代码,为什么初步诊断它没有记录下来
throw new FailedException("操作异常,已收费处方不允许变更");
以上是昨天遇到的问题整理,刚开始自己写博客,表达和逻辑方面有些欠缺,小白请多指教。谢谢~