【发布时间】:2018-08-09 04:55:41
【问题描述】:
我想为我的项目创建一个日志系统。我希望它以 AOP 方式进行。需要使用参数和返回值记录每个执行的方法。我怎么理解,它可以通过拦截器来实现。我为它创建了一个宠物项目。它几乎可以工作。我遇到的问题是如何从日志中了解在一个请求期间执行了什么以及在另一个请求期间执行了什么? F.e.我有 asp.net 应用程序。用户来到应用程序。我记录一切。但我不明白一位具体用户做了什么。我只是在日志中看到执行了一个方法,然后执行了另一个方法,依此类推。但是如何定义所有属于具体请求的执行方法呢?
更新: 我知道 ASP.Net 中的过滤器。我将它用于控制器。但我也想记录服务和数据访问层。
另一个更新: nvoigt 的回答有效。非常感谢 nvoigt!
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var builder = new ContainerBuilder();
var config = GlobalConfiguration.Configuration;
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<ItemService>().As<IItemService>().EnableInterfaceInterceptors().InterceptedBy(typeof(CallLogger)).InstancePerRequest();
builder.RegisterType<ItemRepository>().As<IItemRepository>().EnableInterfaceInterceptors().InterceptedBy(typeof(CallLogger)).InstancePerRequest();
builder.RegisterType<CallLogger>().AsSelf().InstancePerRequest();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
如您所见,CallLoger 具有每个请求的生命周期。我已将 Guid scopeId 属性添加到 CallLogger
public class CallLogger : IInterceptor
{
private readonly string _path = @"D:\1.txt";
private readonly Guid _scopeId;
public CallLogger()
{
_scopeId = Guid.NewGuid();
}
public void Intercept(IInvocation invocation)
{
string message = String.Format("{0}: {1} - Calling method {2} with parameters {3}... ",
_scopeId,
invocation.TargetType.FullName, invocation.Method.Name,
string.Join(", ", invocation.Arguments.Select(a => a)));
string[] m1 = { message };
File.AppendAllLines(_path, m1);
invocation.Proceed();
List<string> m2 = new List<string>();
if (invocation.ReturnValue is IEnumerable)
{
m2.Add(String.Format($"{_scopeId}: Done {invocation.TargetType.FullName} - {invocation.Method.Name}: result was"));
foreach (var rv in (IEnumerable)invocation.ReturnValue)
{
m2.Add(rv.ToString());
}
}
else
{
m2.Add(String.Format($"{_scopeId}: Done {invocation.TargetType.FullName} - {invocation.Method.Name}: result was {invocation.ReturnValue}"));
}
File.AppendAllLines(_path, m2);
}
}
现在我的日志带有 scopeId:
fd35e0f3-a162-48f9-9d69-b39c601513a2: Core.ItemService - Calling method Get with parameters 1...
fd35e0f3-a162-48f9-9d69-b39c601513a2: Core.Repositories.ItemRepository - Calling method Get with parameters 1...
fd35e0f3-a162-48f9-9d69-b39c601513a2: Done Core.Repositories.ItemRepository - Get: result was Id is 1, SomeProperty is Property1, AnotherProperty is Another1
fd35e0f3-a162-48f9-9d69-b39c601513a2: Done Core.ItemService - Get: result was Id is 1, SomeProperty is Property1, AnotherProperty is Another1
1ed6bfd7-f786-4397-905e-6ba7027bdd55: Core.ItemService - Calling method Get with parameters 5...
1ed6bfd7-f786-4397-905e-6ba7027bdd55: Core.Repositories.ItemRepository - Calling method Get with parameters 5...
1ed6bfd7-f786-4397-905e-6ba7027bdd55: Done Core.Repositories.ItemRepository - Get: result was Id is 5, SomeProperty is Property5, AnotherProperty is Another5
1ed6bfd7-f786-4397-905e-6ba7027bdd55: Done Core.ItemService - Get: result was Id is 5, SomeProperty is Property5, AnotherProperty is Another5
【问题讨论】:
-
使用像 Postsharp 这样的 AOP 框架,查看日志记录。或 Fody 的方法装饰器。看:doc.postsharp.net/manual-logging