目前我在C#中有一个自定义构建的静态日志记录类,可以使用以下代码调用:
EventLogger.Log(EventLogger.EventType.Application, string.Format("AddData request from {0}", ipAddress));
调用它时,它只会写入配置文件中指定的已定义日志文件。
但是,由于我必须记录许多事件,因此我的代码开始变得难以阅读,因为所有的日志消息都是如此。
是否有一种既定方法可以从C#类中的对象和方法中或多或少地分离日志代码,这样代码就不会变得难以驾驭?
提前感谢大家的帮助,因为这是我最近一直在努力的事情。
答案 0 :(得分:4)
我喜欢PostSharp提供的AOP功能。在我看来,Loggin是任何软件的一个方面。记录不是应用程序应提供的主要值。
所以在我的情况下,PostSharp总是很好。 Spring.NET还有一个可用于实现此目的的AOP模块。
答案 1 :(得分:4)
我见过的最常用的技术是以一种或另一种形式使用AOP。
PostSharp是一种将IL编织作为AOP形式的产品,尽管是not the only way to do AOP in .NET。
答案 2 :(得分:2)
对此的解决方案是使用Aspect-oriented programming来分隔这些问题。这是一个相当复杂/侵入性的变化,所以我不确定它是否适合你的情况。
答案 3 :(得分:2)
要使代码可读,只记录您真正需要的内容(信息/警告/错误)。在开发期间记录调试消息,但在完成后删除最多。对于跟踪日志记录,请使用 AOP记录方法进入/退出等简单的事情(如果你觉得你需要那种粒度)。
示例:
public int SomeMethod(int arg)
{
Log.Trace("SomeClass.SomeMethod({0}), entering",arg); // A
if (arg < 0)
{
arg = -arg;
Log.Warn("Negative arg {0} was corrected", arg); // B
}
Log.Trace("SomeClass.SomeMethod({0}), returning.",arg); // C
return 2*arg;
}
在这个例子中,唯一必要的日志语句是B.日志语句A和C是样板,记录您可以留给PostSharp为您插入。
另外:在您的示例中,您可以看到某种形式的“Y调用的Action X”,这表明您的许多代码实际上可以移动到更高级别(例如命令/过滤器)。
日志记录语句的激增可能会告诉您一些事情:可以使用某种形式的设计模式,这也可以集中大量日志记录。
void DoSomething(Command command, User user)
{
Log.Info("Command {0} invoked by {1}", command, user);
command.Process(user);
}
答案 4 :(得分:2)
我曾经有一个自定义构建的记录器,但最近改为TracerX。这提供了一种简单的方法来检测具有不同严重性级别的代码。可以使用与您正在使用的类等密切相关的名称创建记录器
它有一个单独的Viewer,具有很多过滤功能,包括记录器,严重性等。
答案 5 :(得分:2)
如果您的主要目标是记录功能进入/退出点以及两者之间的偶然信息,我使用一次性日志记录对象获得了良好的结果,其中 构造函数跟踪功能输入 , Dispose()跟踪退出 。这允许调用代码简单地将每个方法的代码包装在单个使用语句中。还为其间的任意日志提供了方法。这是一个完整的C#ETW事件跟踪类以及函数入口/出口包装器:
using System;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace MyExample
{
// This class traces function entry/exit
// Constructor is used to automatically log function entry.
// Dispose is used to automatically log function exit.
// use "using(FnTraceWrap x = new FnTraceWrap()){ function code }" pattern for function entry/exit tracing
public class FnTraceWrap : IDisposable
{
string methodName;
string className;
private bool _disposed = false;
public FnTraceWrap()
{
StackFrame frame;
MethodBase method;
frame = new StackFrame(1);
method = frame.GetMethod();
this.methodName = method.Name;
this.className = method.DeclaringType.Name;
MyEventSourceClass.Log.TraceEnter(this.className, this.methodName);
}
public void TraceMessage(string format, params object[] args)
{
string message = String.Format(format, args);
MyEventSourceClass.Log.TraceMessage(message);
}
public void Dispose()
{
if (!this._disposed)
{
this._disposed = true;
MyEventSourceClass.Log.TraceExit(this.className, this.methodName);
}
}
}
[EventSource(Name = "MyEventSource")]
sealed class MyEventSourceClass : EventSource
{
// Global singleton instance
public static MyEventSourceClass Log = new MyEventSourceClass();
private MyEventSourceClass()
{
}
[Event(1, Opcode = EventOpcode.Info, Level = EventLevel.Informational)]
public void TraceMessage(string message)
{
WriteEvent(1, message);
}
[Event(2, Message = "{0}({1}) - {2}: {3}", Opcode = EventOpcode.Info, Level = EventLevel.Informational)]
public void TraceCodeLine([CallerFilePath] string filePath = "",
[CallerLineNumber] int line = 0,
[CallerMemberName] string memberName = "", string message = "")
{
WriteEvent(2, filePath, line, memberName, message);
}
// Function-level entry and exit tracing
[Event(3, Message = "Entering {0}.{1}", Opcode = EventOpcode.Start, Level = EventLevel.Informational)]
public void TraceEnter(string className, string methodName)
{
WriteEvent(3, className, methodName);
}
[Event(4, Message = "Exiting {0}.{1}", Opcode = EventOpcode.Stop, Level = EventLevel.Informational)]
public void TraceExit(string className, string methodName)
{
WriteEvent(4, className, methodName);
}
}
}
使用它的代码看起来像这样:
public void DoWork(string foo)
{
using (FnTraceWrap fnTrace = new FnTraceWrap())
{
fnTrace.TraceMessage("Doing work on {0}.", foo);
/*
code ...
*/
}
}
答案 6 :(得分:0)
我认为在ASP.NET MVC中实现与过滤器类似的东西是一个很好的选择。这是在属性和反射的帮助下实现的。您标记要以某种方式登录并享受的每种方法。我想可能有更好的方法可以做到,可能是在Observer模式或其他方面的帮助下,但只要我想到它我就无法想到更好的东西。
基本上这些问题被称为跨领域问题,可以在AOP的帮助下解决。
我还认为一些有趣的继承架构可以应用于基础上的日志实体,但我会选择过滤器