首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >只记录最顶层的ThreadContext堆栈项。

只记录最顶层的ThreadContext堆栈项。
EN

Stack Overflow用户
提问于 2015-07-06 22:45:26
回答 2查看 1.2K关注 0票数 3

我们使用的是Log4net的ThreadContext.Stacks,它大部分工作得很好。如果有多个ThreadContext.Stacks“key”.Push(.),那么我的问题就来了。

使用一个简单的ConversionPattern:

代码语言:javascript
复制
<param name="ConversionPattern value="... topProp=%properties{key} ..."/>

我看到日志条目如下:

代码语言:javascript
复制
... topProp=first second third ...

我真的希望看到的只是最近推出的价值,而不是所有的价值。我曾希望能在我的附录/布局/转换模式中放置如下内容:

代码语言:javascript
复制
<param name="ConversionPattern value="... topProp=%properties{key}{1} ..."/>

但这不管用。我可以假设/要求所有的值都是相同的长度(例如5),然后执行以下操作:

代码语言:javascript
复制
<param name="ConversionPattern value="... topProp=%5.5properties{key} ..."/>

但这并不是真正的吸引力。有什么想法吗?

谢谢!

编辑以添加非常简单的示例

代码语言:javascript
复制
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配置:

代码语言:javascript
复制
<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>

生产:

代码语言:javascript
复制
[jobId=Old]: Enter using
[jobId=Old New]: stuff
[jobId=Old]: Out of using
[jobId=Old]: done.

但我想:

代码语言:javascript
复制
[jobId=Old]: Enter using
[jobId=New]: stuff
[jobId=Old]: Out of using
[jobId=Old]: done.
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-28 15:57:27

我也遇到了同样的问题,这不仅仅是关于“格式错误”,因为我使用了需要整数的数据库附录(AdoNetAppender)。因此,在将所有叠加的值连接在一起之后,结果不再是一个整数。考虑一下这样的一个附录:

代码语言:javascript
复制
<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‘被堆叠两次或更多-在数据库中没有日志.

因此,为了解决这个问题,我放弃了堆栈,转而使用平面属性。我编码了一些简短的分机:

代码语言:javascript
复制
    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();
            }
        }
    }

现在,而不是:

代码语言:javascript
复制
using (ThreadContext.Stacks[PropJobId].Push("New")) {

写:

代码语言:javascript
复制
using (Log4NetExt.ThreadContextPush(PropJobId, "New")) {

它工作正常;)

(这个简短的代码并不遵循构建一次性对象、删除事件处理程序和所有这些东西的所有最佳实践,但它很短,我认为在这个简单的情况下它是安全的)。

票数 1
EN

Stack Overflow用户

发布于 2017-11-24 14:46:37

我是通过菲利浦解决方案进行修改的

代码语言:javascript
复制
 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)) {

}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31256955

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档