审计跟踪(也称为审核日志)是一个安全相关的时间顺序记录,记录这些记录的目的是为已经影响在任何时候的详细操作,提供程序运行的证明文件记录、源或事件

MVC

自定义一个过滤器

public class AuditFilter : IActionFilter
{
/// <summary>
/// 在执行操作方法后调用。
/// </summary>
/// <param name="filterContext"></param>
public void OnActionExecuted(ActionExecutedContext filterContext)
{
var auditData = AbpAuditFilterData.GetOrNull(filterContext.HttpContext);
if (auditData == null)
return;
auditData.Stopwatch.Stop();
var path = AppDomain.CurrentDomain.BaseDirectory + "log.txt";
if (filterContext.Exception != null)
File.AppendAllText(path,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "异常:" + filterContext.Exception + "\r\n");
else
File.AppendAllText(path,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "耗时:" +
Convert.ToInt32(auditData.Stopwatch.Elapsed.TotalMilliseconds) + "\r\n");
}
/// <summary>
/// 在执行操作方法之前调用。
/// </summary>
/// <param name="filterContext"></param>
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var actionStopwatch = Stopwatch.StartNew();
AbpAuditFilterData.Set(
filterContext.HttpContext,
new AbpAuditFilterData(actionStopwatch)
);
}
}

定义一个数据存储

public class AbpAuditFilterData
{
private const string AbpAuditFilterDataHttpContextKey = "__AbpAuditFilterData"; public AbpAuditFilterData(
Stopwatch stopwatch)
{
Stopwatch = stopwatch;
} public Stopwatch Stopwatch { get; } public static void Set(HttpContextBase httpContext, AbpAuditFilterData auditFilterData)
{
GetAuditDataStack(httpContext).Push(auditFilterData);
} public static AbpAuditFilterData GetOrNull(HttpContextBase httpContext)
{
var stack = GetAuditDataStack(httpContext);
return stack.Count <= 0
? null
: stack.Pop();
} /// <summary>
/// 获取一个可变大小的后进先出 (LIFO) 集合
/// </summary>
/// <param name="httpContext"></param>
/// <returns></returns>
private static Stack<AbpAuditFilterData> GetAuditDataStack(HttpContextBase httpContext)
{
if (httpContext.Items[AbpAuditFilterDataHttpContextKey] is Stack<AbpAuditFilterData> stack)
return stack;
stack = new Stack<AbpAuditFilterData>();
httpContext.Items[AbpAuditFilterDataHttpContextKey] = stack;
return stack;
}
}

HomeController 如下

public class HomeController : Controller
{
public ActionResult Index()
{
var a = 0;
for (var i = 0; i < 10000; i++)
for (var j = 0; j < 10000; j++)
a = i - j;
ViewBag.A = a;
return View();
} public ActionResult About()
{
var a = Convert.ToInt32("a");
ViewBag.Message = "Your application description page."; return View();
}
}

访问home/index 日志记录如下:

2018-01-22 19:11:09耗时:342

访问home/about 日志记录如下:

Web Api

自定义过滤器

public class AuditFilter : IActionFilter
{
//
// 摘要:
// 获取或设置一个值,该值指示是否可以为单个程序元素指定多个已指示特性的实例。
//
// 返回结果:
// 如果可以指定多个实例,则为 true;否则为 false。默认值为 false。
public bool AllowMultiple => false; /// <summary>
/// 异步执行筛选器操作
/// </summary>
/// <param name="actionContext"></param>
/// <param name="cancellationToken"></param>
/// <param name="continuation"></param>
/// <returns></returns>
public async Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
var method = actionContext.ActionDescriptor is ReflectedHttpActionDescriptor descriptor ? descriptor.MethodInfo : null;
var str = $"{actionContext.ActionDescriptor.ControllerDescriptor.ControllerType.Name}/{method?.Name}/{JsonConvert.SerializeObject(actionContext.ActionArguments)}"; var stopwatch = Stopwatch.StartNew();
var path = AppDomain.CurrentDomain.BaseDirectory + "log.txt";
try
{
return await continuation();
}
catch (Exception ex)
{
File.AppendAllText(path,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + str + "异常:" + ex + "\r\n");
throw;
}
finally
{
stopwatch.Stop();
File.AppendAllText(path,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " " + str + "耗时:" +
Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds) + "\r\n");
}
}
}

ValuesController代码如下

public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
Thread.Sleep(new Random().Next(500, 1000));
return new[] { "Get" };
} // GET api/values/5
public string Get(int id)
{
Thread.Sleep(new Random().Next(500, 1000));
return id + "";
} [Route("api/values/GetError")]
public void GetError()
{
var a = Convert.ToInt32("a");
}
}

访问api/values 日志记录如下

2018-01-22 19:23:27 ValuesController/Get/{}耗时:978

访问api/values/1 日志记录如下

2018-01-22 19:24:21 ValuesController/Get/{"id":1}耗时:727

访问api/values/GetError 日志记录如下

Unity

自定义一个拦截器

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Interface)]
public class UnityAopAttribute : HandlerAttribute, ICallHandler
{
public override ICallHandler CreateHandler(IUnityContainer container)
{
return this;
} public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
var s = new Stopwatch();
s.Start();
var result = getNext()(input, getNext);
if (result.Exception != null)
{
WriteLog(result.Exception.ToString());
//表示处理异常 Unity就不会抛出
result.Exception = null;
}
s.Stop();
WriteLog("方法:{0},参数:{1},耗时:{2}",
input.MethodBase.Name, JsonConvert.SerializeObject(input.Arguments), s.Elapsed.TotalMilliseconds);
return result;
} private void WriteLog(string format, params object[] arg)
{
var path = AppDomain.CurrentDomain.BaseDirectory + "log.txt";
File.AppendAllText(path, string.Format(format, arg) + "\r\n");
} public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
} public bool WillExecute => false;
}

接口定义如下

public interface IOrderService
{
string GetOrder(); string GetOrderDetail();
}

实现如下

加上UnityAop标记

[UnityAop]
public class OrderService : IOrderService
{
public string GetOrder()
{
Thread.Sleep(new Random().Next(500, 1000));
return "GetOrder";
} public string GetOrderDetail()
{
var i = Convert.ToInt32("a");
return i + "GetOrder";
}
}

注入及调用如下

示例代码:https://github.com/sunven/Abp1

Reference

Unity AOP 处理异常的方法

最新文章

  1. IoC组件Unity再续~根据类型字符串动态生产对象
  2. centos设置编码
  3. with(nolock)的用法
  4. FormsAuthentication与Session超时时间不一的解决方法
  5. Mysql 的存储过程和存储函数
  6. 关于Windows 7的64位系统不兼容某些控件的问题
  7. js页面之间函数调用
  8. 声明式编程思想和EEPlat
  9. SSH(Spring4+Struts2+Hibernate4)框架整合
  10. .net MVC使用Aspose.Words 获取文本域获取文档
  11. eolinker——添加项目成员
  12. Vue 系列之 样式相关
  13. Apache虚拟主机
  14. VIM空格和TAB转换
  15. Spring的PropertyPlaceholderConfigurer
  16. 学JS的心路历程-物件与原型(三)
  17. 执行程序---system
  18. 海思平台交叉编译curl支持SSL功能
  19. [Functional Programming] Monad
  20. sublime text C++

热门文章

  1. KVM(一):KVM安装
  2. 安装supervisord
  3. 4、树莓派的中文:安装ftp,安装gcc,安装qt,编译qt程序,运行qt界面程序
  4. gitlab 本地 定时备份
  5. 本机向windows服务器传输文件的三种方法
  6. [编织消息框架][消息服务]rmi
  7. Fiddler中设置断点修改Request和Response
  8. 【官方文档】Nginx模块Nginx-Rtmp-Module学习笔记(三)流式播放Live HLS视频
  9. node.js 之 Hello,World in Node !
  10. js的onscroll、scrollTop、scrollHeight及window.scroll等方法