我们使用的是Log4net的ThreadContext.Stacks,它大部分工作得很好。如果有多个ThreadContext.Stacks“key”.Push(.),那么我的问题就来了。
使用一个简单的ConversionPattern:
<param name="ConversionPattern value="... topProp=%properties{key} ..."/>我看到日志条目如下:
... topProp=first second third ...我真的希望看到的只是最近推出的价值,而不是所有的价值。我曾希望能在我的附录/布局/转换模式中放置如下内容:
<param name="ConversionPattern value="... topProp=%properties{key}{1} ..."/>但这不管用。我可以假设/要求所有的值都是相同的长度(例如5),然后执行以下操作:
<param name="ConversionPattern value="... topProp=%5.5properties{key} ..."/>但这并不是真正的吸引力。有什么想法吗?
谢谢!
编辑以添加非常简单的示例
using System;
using System.IO;
using log4net;
using log4net.Config;
namespace ThreadLocalExample {
class Program {
private const string PropJobId = "Example:JobId";
static void Main() {
XmlConfigurator.Configure(new FileInfo("log4net.cfg"));
var log = LogManager.GetLogger(typeof(Program));
ThreadContext.Stacks[PropJobId].Push("Old");
log.Debug("Enter using");
using (ThreadContext.Stacks[PropJobId].Push("New")) {
log.Debug("stuff");
}
log.Debug("Out of using");
log.Debug("done.");
Console.ReadKey();
}
}
}使用log4net配置:
<appender name="Console" type="log4net.Appender.ConsoleAppender">
<threshold value="ALL" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="[jobId=%P{Example:JobId}]: %m%n" />
</layout>
</appender>生产:
[jobId=Old]: Enter using
[jobId=Old New]: stuff
[jobId=Old]: Out of using
[jobId=Old]: done.但我想:
[jobId=Old]: Enter using
[jobId=New]: stuff
[jobId=Old]: Out of using
[jobId=Old]: done.发布于 2015-08-28 15:57:27
我也遇到了同样的问题,这不仅仅是关于“格式错误”,因为我使用了需要整数的数据库附录(AdoNetAppender)。因此,在将所有叠加的值连接在一起之后,结果不再是一个整数。考虑一下这样的一个附录:
<appender name="DbAppender" type="log4net.Appender.AdoNetAppender">
...
<commandText value="INSERT INTO Log ([Id]) VALUES (@Id)" />
<parameter>
<parameterName value="@Id" />
<dbType value="Int32" />
<layout type="log4net.Layout.PatternLayout" value="%P{someId}" />
</parameter>
此附录将不接受任何日志消息,其中'someId‘被堆叠两次或更多-在数据库中没有日志.
因此,为了解决这个问题,我放弃了堆栈,转而使用平面属性。我编码了一些简短的分机:
public static class Log4NetExt {
public static IDisposable ThreadContextPush(string key, object value) {
object oldVal = ThreadContext.Properties[key];
ThreadContext.Properties[key] = value;
var topMostCleaner = new DispCleaner();
topMostCleaner.EvDispose += () => {
// Pop = restore old value
ThreadContext.Properties[key] = oldVal;
};
return topMostCleaner;
}
private class DispCleaner : IDisposable {
public event Action EvDispose;
public void Dispose() {
if (EvDispose != null) EvDispose();
}
}
}现在,而不是:
using (ThreadContext.Stacks[PropJobId].Push("New")) {写:
using (Log4NetExt.ThreadContextPush(PropJobId, "New")) {它工作正常;)
(这个简短的代码并不遵循构建一次性对象、删除事件处理程序和所有这些东西的所有最佳实践,但它很短,我认为在这个简单的情况下它是安全的)。
发布于 2017-11-24 14:46:37
我是通过菲利浦解决方案进行修改的
public static class Log4NetExt
{
public static IDisposable ThreadContextSet(string key, object value)
{
//object oldVal = ThreadContext.Properties[key];
ThreadContext.Properties[key] = value;
var topMostCleaner = new DispCleaner();
topMostCleaner.EvDispose += () => {
// Pop = restore old value
//ThreadContext.Properties[key] = oldVal;
ThreadContext.Properties[key] = null;
};
return topMostCleaner;
}
private class DispCleaner : IDisposable
{
public event Action EvDispose;
public void Dispose()
{
if (EvDispose != null)
{
EvDispose();
}
}
}
}并把它当作
使用(Log4NetExt.ThreadContextSet("ContextId","Feed"))使用(Log4NetExt.ThreadContextPush("ContextValue",objFeed.FeedId)) {
}
https://stackoverflow.com/questions/31256955
复制相似问题