gpt4 book ai didi

c# - 关于以AOP方式记录方法的每次调用

转载 作者:行者123 更新时间:2023-11-30 23:00:12 26 4
gpt4 key购买 nike

我想为我的项目创建一个日志系统。我希望它以 AOP 方式进行。需要用参数和返回值记录每个执行的方法。我的理解是,它可以通过拦截器来实现。我为它创建了一个宠物项目。它几乎可以工作。我遇到的问题是如何从日志中了解在一个请求期间执行了什么以及在另一个请求期间执行了什么?F.e.我有 asp.net 应用程序。用户来到应用程序。我记录一切。但是我不明白某个具体用户做了什么。我只是在日志中看到执行了一个方法,然后执行了另一个方法,依此类推。但是如何定义属于具体请求的所有执行的方法呢?

更新:我知道 ASP.Net 中的过滤器。我将它用于 Controller 。但我也想记录服务和数据访问层。

另一个更新: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

最佳答案

你对你实际做了的事情非常模糊,所以这个答案对你需要做的事情也有点模糊:

每个日志条目都必须包含一个标识符,这样您就可以按标识符对日志条目进行分组,基本上每次调用 Controller 都会得到一组日志( Controller 日志、服务层日志、存储库都按他们的初始条目)。

您已经有一个实例来保存每次调用的数据,这是您的依赖项注入(inject)容器,每次调用都有一个作用域。您需要在那里有一个类来保存您的范围特定数据(例如每个范围只有一个 Guid.NewGuid() )并且您的记录器必须通过依赖注入(inject)访问该类框架。然后您的记录器可以将该标识符附加到您的日志中,您稍后可以按它分组。

关于c# - 关于以AOP方式记录方法的每次调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51740353/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com