删除 PostSharp 日志消息中的前缀
Delete prefix in PostSharp log message
我使用 PostSharp LogAttribute 和 log4net 为调用的所有方法生成跟踪。
输出很好,但我想去掉每行的重复标签 Entering:
:
17:48:34,694 [Main ] Entering: LoginPopUp.LoginClick()
17:48:34,695 [Main ] Entering: UserRepository.GetUser()
17:48:34,695 [Main ] Entering: UserRepository.IsAdmin()
17:48:34,696 [Main ] Entering: SecurityManager.Encrypt()
从 this answer 可以明显看出 PostSharp 团队不会添加消息格式自定义。
还有一个自定义的例子TraceAttribute derived from OnMethodBoundaryAspect
而且定制起来似乎更灵活。但问题是,在这种情况下,我丢失了显示嵌套级别的缩进(对我来说,这比在每一行都输入 Entering 单词更重要)。
最好的解决方案是扩展 LogAttribute 以自定义前缀,但我不知道是否可行。
那么如何删除 Entering:
前缀?
基于 Peter 答案的工作代码
static readonly Dictionary<Thread, int> DepthDictionary = new Dictionary<Thread, int>();
// Invoked at runtime before that target method is invoked.
public override void OnEntry(MethodExecutionArgs args)
{
int depth;
DepthDictionary.TryGetValue(Thread.CurrentThread, out depth);
Trace.WriteLine(getIndent(depth) + this.enteringMessage, this.category);
DepthDictionary[Thread.CurrentThread] = depth+1;
}
// Invoked at runtime after the target method is invoked (in a finally block).
public override void OnExit(MethodExecutionArgs args)
{
var depth = --DepthDictionary[Thread.CurrentThread];
Trace.WriteLine(getIndent(depth) + this.exitingMessage, this.category);
}
private string getIndent(int depth)
{
string result = "";
for (int i = 0; i < depth; i++) result += " ";
return result;
}
可以在 log4net 自定义 PatternLayoutConverter 中使用 string.Replace 删除它,但这似乎不是最佳解决方案。
如果能有一个基于自定义 TraceAttribute 的解决方案就好了。
如果您的解决方案不是多线程的,您可以自己添加缩进:
// Invoked only once at runtime from the static constructor of type declaring the target method.
public override void RuntimeInitialize(MethodBase method)
{
string methodName = method.DeclaringType.FullName + method.Name;
this.enteringMessage = methodName;
this.exitingMessage = methodName;
}
static int depth = 0;
// Invoked at runtime before that target method is invoked.
public override void OnEntry(MethodExecutionArgs args)
{
Trace.WriteLine(getIndent()+this.enteringMessage, this.category);
depth++;
}
// Invoked at runtime after the target method is invoked (in a finally block).
public override void OnExit(MethodExecutionArgs args)
{
depth--;
Trace.WriteLine(getIndent()+this.exitingMessage, this.category);
}
private string getIndent(){
string result = "";
for (int i = 0; i < depth;i++) result += " ";
return result;
}
我使用 PostSharp LogAttribute 和 log4net 为调用的所有方法生成跟踪。
输出很好,但我想去掉每行的重复标签 Entering:
:
17:48:34,694 [Main ] Entering: LoginPopUp.LoginClick()
17:48:34,695 [Main ] Entering: UserRepository.GetUser()
17:48:34,695 [Main ] Entering: UserRepository.IsAdmin()
17:48:34,696 [Main ] Entering: SecurityManager.Encrypt()
从 this answer 可以明显看出 PostSharp 团队不会添加消息格式自定义。
还有一个自定义的例子TraceAttribute derived from OnMethodBoundaryAspect 而且定制起来似乎更灵活。但问题是,在这种情况下,我丢失了显示嵌套级别的缩进(对我来说,这比在每一行都输入 Entering 单词更重要)。
最好的解决方案是扩展 LogAttribute 以自定义前缀,但我不知道是否可行。
那么如何删除 Entering:
前缀?
基于 Peter 答案的工作代码
static readonly Dictionary<Thread, int> DepthDictionary = new Dictionary<Thread, int>();
// Invoked at runtime before that target method is invoked.
public override void OnEntry(MethodExecutionArgs args)
{
int depth;
DepthDictionary.TryGetValue(Thread.CurrentThread, out depth);
Trace.WriteLine(getIndent(depth) + this.enteringMessage, this.category);
DepthDictionary[Thread.CurrentThread] = depth+1;
}
// Invoked at runtime after the target method is invoked (in a finally block).
public override void OnExit(MethodExecutionArgs args)
{
var depth = --DepthDictionary[Thread.CurrentThread];
Trace.WriteLine(getIndent(depth) + this.exitingMessage, this.category);
}
private string getIndent(int depth)
{
string result = "";
for (int i = 0; i < depth; i++) result += " ";
return result;
}
可以在 log4net 自定义 PatternLayoutConverter 中使用 string.Replace 删除它,但这似乎不是最佳解决方案。
如果能有一个基于自定义 TraceAttribute 的解决方案就好了。
如果您的解决方案不是多线程的,您可以自己添加缩进:
// Invoked only once at runtime from the static constructor of type declaring the target method.
public override void RuntimeInitialize(MethodBase method)
{
string methodName = method.DeclaringType.FullName + method.Name;
this.enteringMessage = methodName;
this.exitingMessage = methodName;
}
static int depth = 0;
// Invoked at runtime before that target method is invoked.
public override void OnEntry(MethodExecutionArgs args)
{
Trace.WriteLine(getIndent()+this.enteringMessage, this.category);
depth++;
}
// Invoked at runtime after the target method is invoked (in a finally block).
public override void OnExit(MethodExecutionArgs args)
{
depth--;
Trace.WriteLine(getIndent()+this.exitingMessage, this.category);
}
private string getIndent(){
string result = "";
for (int i = 0; i < depth;i++) result += " ";
return result;
}