[英]Programmatic Custom Json Layout Log4j2
I have Java<\/code> desktop client application that utilizes
Log4j2 framework.<\/code>
我有使用
Log4j2 framework.<\/code>的
Java<\/code>桌面客户端应用程序。
JSON structure is used when logging the exceptions or infos with custom parameters.
使用自定义参数记录异常或信息时使用 JSON 结构。 I am trying to configure the Log4j2 programmatically for this reason.
出于这个原因,我正在尝试以编程方式配置 Log4j2。 I am aware that the file based configuration is recommended but it seems like it'd be better to programmatically initialize the framework for my case.
我知道建议使用基于文件的配置,但似乎最好为我的案例以编程方式初始化框架。
This is the structure I am trying to build.这是我正在尝试构建的结构。
Custom Json Layout自定义 Json 布局<\/li>
![](/img/trans.png)
HttpAppender<\/code> that will send the logs over HTTP
HttpAppender<\/code>将通过 HTTP 发送日志
<\/li>
![](/img/trans.png)
If HttpAppender fails, it will use JdbcAppender<\/code> to write to the database
如果 HttpAppender 失败,它将使用JdbcAppender<\/code>写入数据库
<\/li>
If JdbcAppender fails, it will use FileAppender<\/code> to write to a log file
如果 JdbcAppender 失败,它将使用FileAppender<\/code>写入日志文件
<\/li><\/ul>I am able to generate JsonLayout<\/code> but I cannot add custom fields and remove existing ones from the default structure.
我能够生成JsonLayout<\/code>但我无法添加自定义字段并从默认结构中删除现有字段。
I've probably checked over 50 articles\/questions but none of them worked for me.
我可能已经检查了 50 多篇文章\/问题,但没有一个对我有用。 This is the current code I have.
这是我拥有的当前代码。
![](/img/trans.png)
public static void initializeLogger() { ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder(); builder.setStatusLevel(Level.DEBUG); builder.setConfigurationName("DefaultLogger"); \/\/Creating console appender just to see logging is there. AppenderComponentBuilder appenderBuilder = builder.newAppender("Console", "CONSOLE") .addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT); appenderBuilder.add(builder.newLayout("PatternLayout") .addAttribute("pattern", pattern) .addAttribute("AdditionalField.key", "asd") .addAttribute("AdditionalField.value", "qwe")); RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.DEBUG); rootLogger.add(builder.newAppenderRef("Console")); builder.add(appenderBuilder); \/\/Creating the file appender LayoutComponentBuilder layoutBuilder = builder.newLayout("JsonLayout") .addAttribute("compact", "false") .addAttribute("AdditionalField", builder.newKeyValuePair("asd", "qwe")); ComponentBuilder triggeringPolicy = builder.newComponent("Policies") .addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", "1KB")); appenderBuilder = builder.newAppender("LogToRollingFile", "RollingFile") .addAttribute("fileName", fileName) .addAttribute("filePattern", "applog-%d{MM-dd-yy-HH-mm-ss}.log.") .add(layoutBuilder) .addComponent(triggeringPolicy); builder.add(appenderBuilder); rootLogger.add(builder.newAppenderRef("LogToRollingFile")); builder.add(rootLogger); Configurator.reconfigure(builder.build()); }<\/code><\/pre> This code prints to the console and writes Json formatted logging to a file.此代码打印到控制台并将 Json 格式的日志记录写入文件。 The custom values are not added to the Json.
自定义值不会添加到 Json。 I tried to create JsonLayout via its builder<\/code> but I cannot add it to the builder itself.
我尝试通过其builder<\/code>创建 JsonLayout,但我无法将其添加到构建器本身。
![](/img/trans.png)
\/\/Probably creating a new layout instance with additional fields \/\/might be helpful but I cannot use this in the builder above. JsonLayout layout = JsonLayout.newBuilder() .setAdditionalFields(new KeyValuePair [] { new KeyValuePair("asd", "qwe"), new KeyValuePair("zxc", "rty"), }).build();<\/code><\/pre> The parameters that I need to add to the Json is dynamic and I do not know the keys and values of the custom nodes.我需要添加到 Json 的参数是动态的,我不知道自定义节点的键和值。 At this stage, I am trying to create a custom Json Layout at write it to the file.
在这个阶段,我试图在将其写入文件时创建一个自定义 Json 布局。
I might be doing this completely wrong so please advice!我可能做错了,所以请指教! I'm open to suggestions.
我愿意接受建议。 Thanks.
谢谢。
"
A custom value as a key-value pair can be added as a component by calling the addComponent
method of LayoutComponentBuilder
.通过调用
LayoutComponentBuilder
的addComponent
方法,可以将自定义值作为键值对添加为组件。 The following code snippet shows an example:以下代码片段显示了一个示例:
ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
AppenderComponentBuilder console =
builder.newAppender("stdout", "Console")
.addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
LayoutComponentBuilder jsonLayout
= builder.newLayout("JsonLayout")
.addAttribute("complete", false)
.addAttribute("compact", false)
.addComponent(builder.newKeyValuePair("key1", "value1"))
.addComponent(builder.newKeyValuePair("key2", "value2"));
console.add(jsonLayout);
builder.add(console);
RootLoggerComponentBuilder rootLogger
= builder.newRootLogger(Level.INFO);
rootLogger.add(builder.newAppenderRef("stdout"));
builder.add(rootLogger);
builder.writeXmlConfiguration(System.out);
return builder;
Here is the corresponding xml ouput:这是相应的 xml 输出:
<?xml version='1.0' encoding='UTF-8'?>
<Configuration>
<Appenders>
<Console name="stdout" target="SYSTEM_OUT">
<JsonLayout complete="false" compact="false">
<KeyValuePair key="key1" value="value1"/>
<KeyValuePair key="key2" value="value2"/>
</JsonLayout>
</Console>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="stdout"/>
</Root>
</Loggers>
</Configuration>
Tested with log4j 2.17.1使用 log4j 2.17.1 测试
You can use the following class to subtract any of the attributes you want in the class from the log.您可以使用以下类从日志中减去您想要的类中的任何属性。
import com.fanap.midhco.applicationUtil.JsonUtil;
import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Node;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.impl.Log4jLogEvent;
import org.apache.logging.log4j.core.jackson.JsonConstants;
import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
import org.apache.logging.log4j.core.layout.AbstractStringLayout;
import org.apache.logging.log4j.core.util.StringBuilderWriter;
import org.apache.logging.log4j.util.Strings;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Set;
@Plugin(name = "MineCustLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public class MineCustLayout extends AbstractStringLayout {
private final ObjectWriter objectWriter;
@PluginFactory
public static MineCustLayout createLayout(
@PluginAttribute(value = "locationInfo", defaultBoolean = false) final boolean locationInfo, @PluginAttribute(value = "eventEol", defaultBoolean = true) final boolean eventEol
) {
final SimpleFilterProvider filters = new SimpleFilterProvider();
final Set<String> except = new HashSet<>();
if (!locationInfo) {
except.add(JsonConstants.ELT_SOURCE);
}
except.add("loggerFqcn");
except.add("level");
except.add("timeMillis");
except.add("instant");
except.add("thread");
except.add("loggerName");
except.add("threadId");
except.add("threadPriority");
except.add("contextMap");
except.add("endOfBatch");
except.add(JsonConstants.ELT_NANO_TIME);
filters.addFilter(Log4jLogEvent.class.getName(), SimpleBeanPropertyFilter.serializeAllExcept(except));
final ObjectWriter writer = new Log4jJsonObjectMapper().writer(new MinimalPrettyPrinter());
return new MineCustLayout(writer.with(filters));
}
public MineCustLayout(ObjectWriter objectWriter) {
super(StandardCharsets.UTF_8, null, null);
this.objectWriter = objectWriter;
}
@Override
public String toSerializable(LogEvent event) {
final StringBuilderWriter writer = new StringBuilderWriter();
try {
objectWriter.writeValue(writer, event);
// writer.write('\n');
return JsonUtil.getJsonObject(writer.toString()).get("message").toString() + '\n';
} catch (final IOException e) {
LOGGER.error(e);
return Strings.EMPTY;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.