Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将动态值传递给log4j2xml配置_Java_Logging_Log4j_Log4j2 - Fatal编程技术网

Java 将动态值传递给log4j2xml配置

Java 将动态值传递给log4j2xml配置,java,logging,log4j,log4j2,Java,Logging,Log4j,Log4j2,我正在尝试使用log4j2编写日志模块,该模块需要以json的形式将日志写入控制台STDOUT 为此,我尝试使用JSON格式的PatternLayout,如下所示 在编写日志时,我很难将代码中的值动态地传递到log4j2.xml配置文件,以便在运行时替换它们 我尝试使用StructuredDataMessage和MapMessages替换中提到的Map中的值 我也尝试了StrLookup和ContextMaplookup,但到目前为止没有成功 Below is my xml config

我正在尝试使用log4j2编写日志模块,该模块需要以json的形式将日志写入控制台STDOUT

为此,我尝试使用JSON格式的PatternLayout,如下所示

在编写日志时,我很难将代码中的值动态地传递到log4j2.xml配置文件,以便在运行时替换它们

我尝试使用StructuredDataMessage和MapMessages替换中提到的Map中的值

我也尝试了StrLookup和ContextMaplookup,但到目前为止没有成功

Below is my xml config

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="WARN" name="App" packages="com.test.common.logging">
        <Properties>
            <Property name="filename">target/rolling1/rollingtest.log</Property>
            <Property name="maptype">$${map:type}</Property>

        </Properties>

        <ThresholdFilter level="debug"/>

        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
              <PatternLayout pattern="%highlight{{'logged time': '%d{dd MMM yyyy HH:mm:ss}', 
            'LEVEL' : '%level',
            'CLASS' : '%c{-1}',
            'Module' : '[%t]',
            'message' : '%m',
            'error' : '%exception',
            'class' : '%C',
            'threadid' : '%tid',
            'threadname' : '%thread',
            'whatisthis' : '${filename}',
            'processid' : '%pid', 
            'logdir' : '$${sd:type}'
            'location' : '${log4j:configLocation}'
            'systemproperty' : '$${ctx:key-}'
            }}%n"/>
            </Console>
        </Appenders>

        <Loggers>
            <Root level="trace">
                <AppenderRef ref="Console"/>
            </Root>
        </Loggers>

    </Configuration>

如果您看到lastvalue systemproperty没有通过从代码值中替换而得到预期的反映。

我认为您对log4j2有一些基本的误解。我认为最好的办法是提供一些示例代码并解释输出,而不是列出我在代码中看到的所有问题。我想当你看到一些工作代码时,你就会明白你哪里出错了

出于本例的目的,我简化了log4j2配置文件,方法是删除似乎正常工作的元素,并将重点放在不正常的元素上。我将
模式布局更改为以下内容:

<PatternLayout pattern="{'LEVEL' : '%level', 'typeFromStructMsg' : '${sd:type}', 'contextValue' : '${ctx:myContextKey}', 'nameFromMapMsg' : '${map:name}', 'mySysProperty' : '${sys:mySysProperty}'}%n" />
运行
App
类时,将生成以下控制台输出:

{'LEVEL' : 'INFO', 'typeFromStructMsg' : '${sd:type}', 'contextValue' : 'myContextValue', 'nameFromMapMsg' : 'arun', 'mySysProperty' : 'sys prop value'}
{'LEVEL' : 'WARN', 'typeFromStructMsg' : 'string', 'contextValue' : 'myContextValue', 'nameFromMapMsg' : '${map:name}', 'mySysProperty' : 'sys prop value'}
{'LEVEL' : 'ERROR', 'typeFromStructMsg' : '${sd:type}', 'contextValue' : 'myContextValue', 'nameFromMapMsg' : '${map:name}', 'mySysProperty' : 'sys prop value'}
注意,在输出的第一行中我们看到:
'nameFromMapMsg':'arun'
,而在其他行中我们看到:
'nameFromMapMsg':'${map:name}'

第一行输出由这行代码生成:
logger.info(mapMsg)
将名为
mapMsg
MapMessage
的实例传递给
info
方法。由于消息是
MapMessage
的一个实例,并且它包含一个名为
name
的键,因此映射查找将用它为消息中的
name
键找到的值替换
${map:name}
。这就是为什么只有输出的第一行显示“nameFromMapMsg”:“arun”
——其他输出行是从不是
MapMessage
实例的消息生成的

类似地,请注意,在输出的第二行中,我们看到了
'typeFromStructMsg':'string'
。这是因为日志是从一个
structuredataMessage
生成的,该消息是用“字符串”类型定义的:

structuredatamessage structMsg=newstructuredatamessage(“1”、“名称”、“字符串”)

在输出的其他行中,我们没有传递
StructuredDataMessage
,因此在这些行中,我们看到
'typeFromStructMsg':'${sd:type}'
,因为log4j2找不到该类型的值

最后,请注意,在所有输出行中,我们都可以看到这样的内容:
'mySysProperty':'syspropvalue'
。这是因为系统属性查找不依赖于传递给记录器的消息类型。此查找始终能够找到系统属性
mySysProperty
的值,因为我们定义了它:

System.setProperty("mySysProperty", "sys prop value");
而且,正如我前面所说,系统属性独立于消息(它们不存储在消息中)

对于
'contextValue':'myContextValue'
ThreadContext
与消息无关,因为我们为该键定义了一个值:

ThreadContext.put("myContextKey", "myContextValue");
无论发送给记录器的消息类型如何,查找始终能够找到值


我希望这个示例代码有助于说明如何使用一些查找,以及如何设计log4j2的体系结构。祝你好运

在xml文件本身中编辑PatternLayout是不可行的,如果值是静态的,并且保持不变,那么它就可以工作,否则您需要通过扩展内置方法实现自定义模式,然后相应地格式化消息。 下面的链接将让您知道同样的情况


谢谢你的详细解释,这对我很有帮助。所以基本上,由于StructuredDataMessage和StringMapMessage依赖于日志消息,我也需要将它们传递给我的记录器,对吗?如果我还需要传递日志消息,那么除了映射之外,我可以将它们作为其他参数单独传递吗?或者只需要作为映射键传递?如果使用结构化数据查找,则必须将
structuredataMessage
的实例传递给记录器,以便查找可以在该消息中找到值。类似地,如果使用映射查找,则必须传递
MapMessage
的实例(我在上面的示例中使用了
StringMapMessage
)。我引用的实例是消息,因此您要记录的所有数据都需要包含在该实例中。请参阅,您是否可以添加更多关于此的详细信息?
{'LEVEL' : 'INFO', 'typeFromStructMsg' : '${sd:type}', 'contextValue' : 'myContextValue', 'nameFromMapMsg' : 'arun', 'mySysProperty' : 'sys prop value'}
{'LEVEL' : 'WARN', 'typeFromStructMsg' : 'string', 'contextValue' : 'myContextValue', 'nameFromMapMsg' : '${map:name}', 'mySysProperty' : 'sys prop value'}
{'LEVEL' : 'ERROR', 'typeFromStructMsg' : '${sd:type}', 'contextValue' : 'myContextValue', 'nameFromMapMsg' : '${map:name}', 'mySysProperty' : 'sys prop value'}
System.setProperty("mySysProperty", "sys prop value");
ThreadContext.put("myContextKey", "myContextValue");