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

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 处理异常的方法

审计日志中的AOP的更多相关文章

  1. Springboot中使用AOP统一处理Web请求日志

    title: Springboot中使用AOP统一处理Web请求日志 date: 2017-04-26 16:30:48 tags: ['Spring Boot','AOP'] categories: ...

  2. Spring Boot中使用AOP统一处理Web请求日志

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...

  3. (转)Spring Boot中使用AOP统一处理Web请求日志

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...

  4. 在Delphi中应用AOP实现日志功能

    AOP现在很火,网上有这许多支持AOP的框架,对于Delphi来说同样也有MeAOP.不过觉得这些框架太复杂了. 现在有一个系统,基本上都快结束了,整体上当然是没有采用什么AOP的框架.对于这样的系统 ...

  5. Spring Boot中使用AOP记录请求日志

    这周看别人写的springboot后端代码中有使用AOP记录请求日志,以前没接触过,因此学习下. 一.AOP简介 AOP为Aspect Oriented Programming的缩写,意为:面向切面编 ...

  6. 46. Spring Boot中使用AOP统一处理Web请求日志

    在之前一系列的文章中都是提供了全部的代码,在之后的文章中就提供核心的代码进行讲解.有什么问题大家可以给我留言或者加我QQ,进行咨询. AOP为Aspect Oriented Programming的缩 ...

  7. 转:Spring Boot中使用AOP统一处理Web请求日志

    在spring boot中,简单几步,使用spring AOP实现一个拦截器: 1.引入依赖: <dependency> <groupId>org.springframewor ...

  8. Spring MVC 中使用AOP 进行统一日志管理--注解实现

    1.AOP简介 AOP称为面向切面编程 AOP的基本概念 (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知 (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的 ...

  9. SpringBoot中使用AOP打印接口日志的方法(转载)

    前言 AOP 是 Aspect Oriented Program (面向切面)的编程的缩写.他是和面向对象编程相对的一个概念.在面向对象的编程中,我们倾向于采用封装.继承.多态等概念,将一个个的功能在 ...

随机推荐

  1. CGO 类型(CGO Types) 一

    CGO Types C作为一种混合编程语言已经很久了,无论那些广泛使用的包是用何种语言实现的,都导出了和C兼容的API.Go程序调用C程序,可以借助两种工具实现,一种是cgo,另一种是SWIG工具.C ...

  2. touch事件应用

    js的touch事件,一般用于移动端的触屏滑动: $(function(){ document.addEventListener("touchmove", _touch, fals ...

  3. linux系统下phpstudy里的mysql使用方法

    linux作为一个优秀的服务器端管理系统,其实linux的桌面系统也用起来十分的nice.好吧,如何你在做开发的时候在linux下安装了lmap或者phpstudy,那么在第一次使用其自带的mysql ...

  4. windows c++ 程序移植到Linux的一些要点

    这段时间得到一份源码,是Windows下的,调试了一把,可以正常运行,可是没有Linux版本,而实际的应用场景是要在Linux服务器上面运行 所以涉及到Windows下c++程序的移植,有同事竭力推荐 ...

  5. SSM框架开发web项目系列(五) Spring集成MyBatis

    前言 在前面的MyBatis部分内容中,我们已经可以独立的基于MyBatis构建一个数据库访问层应用,但是在实际的项目开发中,我们的程序不会这么简单,层次也更加复杂,除了这里说到的持久层,还有业务逻辑 ...

  6. TurnipBit:和孩子一起动手DIY“滚动”的生日礼物

    当孩子的生日来临之时,做父母的总是会为该为孩子准备什么礼物而烦恼.下面就教家长朋友们利用TurnipBit开发板DIY一份"特殊"的生日礼物,不仅能增加与孩子的互动性还能提升孩子在 ...

  7. 页面刷新vuex数据消失问题解决方案 之 vuex中间件

    之前我写了一篇用ES6 Proxy方案解决数据同步的文章 页面刷新vuex数据消失问题解决方案. 今天和同事沟通这个vuex数据还原问题,我说我的方法很奇异.聊着聊着,同事咋不用  store.sub ...

  8. [Spark内核] 第28课:Spark天堂之门解密

    本課主題 什么是 Spark 的天堂之门 Spark 天堂之门到底在那里 Spark 天堂之门源码鉴赏 引言 我说的 Spark 天堂之门就是SparkContext,这篇文章会从 SparkCont ...

  9. SLAM入门之视觉里程计(5):单应矩阵

    在之前的博文OpenCV,计算两幅图像的单应矩阵,介绍调用OpenCV中的函数,通过4对对应的点的坐标计算两个图像之间单应矩阵\(H\),然后调用射影变换函数,将一幅图像变换到另一幅图像的视角中.当时 ...

  10. C# Main函数详解

    2018-01-15 22:10:59  一.Main()方法的简介 1.唯一性.一般情况下,一个C#可执行程序只有一个Main函数,作为程序入口.但是在某些情况(如单元测试中),程序拥有多个Main ...