多线程模式下的Log4j2自定义ContextDataInjector

时间:2017-03-16 16:14:28

标签: java multithreading logging configuration log4j2

我有一个实例化多个线程的应用程序。每个服务都具有相同的log4j2配置,可写入日志和套接字appender。 我需要在所有日志和套接字输出中获取主机信息,但使用

InetAddress addr = InetAddress.getLocalHost();
ThreadContext.put("Host", addr.getHostName());

我只在" main"中收到该信息。线程。

所以,在这里解释https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/ContextDataInjector.html

  

在某些异步模型中,可以将工作委托给多个线程,而从概念上讲,这项工作共享相同的上下文。在这样的模型中,将上下文数据存储在ThreadLocal变量中是不方便或不可取的。用户可以配置ContextDataInjectorFactory以提供自定义ContextDataInjector对象,以便使用来自任意上下文的上下文数据初始化日志事件。

我应该创建一个自定义ContextDataInjector,但我无法对其进行编码。 我编码了这个

List<Property> propertiesTest = new ArrayList<>();
propertiesTest.add(Property.createProperty("Host", "test"));
StringMap reusabletest = null;

ContextDataInjector prueba = ContextDataInjectorFactory.createInjector();
prueba.injectContextData(propertiesTest, reusabletest);

但它不起作用......

另一种方法是以这种方式实现ContextDataInjector:

 public class Log4j2Manager implements ContextDataInjector
{
private static Log4j2Configuration config;
private static final String PROPERTIES_PATH = "/etc//Log4j2Manager/Log4j2Manager.properties";
private final static Logger LOG = LogManager.getLogger(Log4j2Manager.class);

private static Log4j2slave[] workers = null;

public Log4j2Manager(String configPath) throws Exception
{
    List<Property> propertiesTest = new ArrayList<>();
    propertiesTest.add(Property.createProperty("Host", "test"));
    StringMap reusableTest = null;

    injectContextData(propertiesTest, reusableTest);
    workers = new Log4j2slave[config.NumWorkers];
    for (int i = 0; i < workers.length; i++) 
    {
        workers[i] = new Log4j2slave(i);
        Thread.sleep(1000);
    }
    .... 
 } 
    ....
 @Override
 public StringMap injectContextData(List<Property> properties, StringMap reusable) 
 {
    if (properties == null || properties.isEmpty()) 
    {
        // assume context data is stored in a copy-on-write data structure
        // that is safe to pass to another thread
        return (StringMap) rawContextData();
    }
    // first copy configuration properties into the result
    ThreadContextDataInjector.copyProperties(properties, reusable);

    // then copy context data key-value pairs (may overwrite configuration
    // properties)
    reusable.putAll(rawContextData());
    return reusable;
}

@Override
public ReadOnlyStringMap rawContextData() {
    // TODO Auto-generated method stub
    return null;
}

但它返回零点异常。 有什么建议吗?

最好的问候

2 个答案:

答案 0 :(得分:1)

您没有提供堆栈跟踪,但我怀疑nullpointer异常是由return s.join(encdic.get(c,c) for c in plaintext) 的实现引起的。它不能返回rawContextData()

请参阅null界面的Log4j2 built-in implementations,了解从此方法返回的内容。

要安装自定义上下文数据注入器,您需要在系统属性ContextDataInjector中指定实现的完全限定类。请参阅ContextDataInjectorFactory

答案 1 :(得分:0)

最后我直接打电话给我,我做了一个测试。 使用

ThreadContext.put("Host", addr.getHostName())

我可以得到&#34;主持人&#34;只有主要的,而如果我避免这种结构,我没有任何价值,也没有进入主要 我不明白错误在哪里。

        InetAddress addr = InetAddress.getLocalHost();
        ThreadContext.put("Host", addr.getHostName());

        List<Property> properties = new ArrayList<>();
        properties.add(Property.createProperty("Host", "test"));
        StringMap reusable = null;

        ContextDataInjector prueba = new  ForGarbageFreeThreadContextMap();
        prueba.injectContextData(properties, reusable);

        Log4j2Manager Log4j2Man = new Log4j2Manager(propertiesPath);
        Log4j2Man.Start();