是否可以通过指定记录器名称在log4j2
中添加记录器可编程性?
我厌倦了在网上搜索它,我发现有些事情说log4j2
不允许这种功能。这是链接:
How to add Log4J2 appenders at runtime programmatically?
有办法做到这一点吗?
答案 0 :(得分:0)
我想分享一下我是如何使用log4j2实现它的。 您可以添加新的记录器并删除现有记录器。 并且也可以更改日志级别。
src/
main/
java/
com/foo/bar/
LogLevelPM
LogLevelWin -- Swing UI
resources/
log4j2.xml
log4j2的配置
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.foo.bar.myLogger" level="debug" additivity="false">
<appender-ref ref="Console"/>
</Logger>
<Root level="trace">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
LogLevelPM执行实际操作,而LogLevelWin只是一个使用它的示例。
package com.foo.bar;
import java.util.Collection;
import java.util.Map;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
public class LogLevelPM {
public Object[][] retrieveLoggers() {
Object[][] result = null;
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
Collection<LoggerConfig> loggerConfigs = config.getLoggers().values();
result = new Object[loggerConfigs.size()][];
LoggerConfig rootLoggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
result[0] = new Object[] {"ROOT", rootLoggerConfig.getLevel().toString(), getAppenderNames(rootLoggerConfig.getAppenders())};
int i = 1;
for (LoggerConfig loggerConfig : loggerConfigs) {
if (!loggerConfig.getName().isEmpty()) {
result[i++] = new Object[]{loggerConfig.getName(), loggerConfig.getLevel().toString(), getAppenderNames(loggerConfig.getAppenders())};
}
}
return result;
}
public String[] getAllAppenders() {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
Map<String, Appender> appenders = config.getAppenders();
String[] appenderNames = (String[]) appenders.keySet().toArray(new String[appenders.size()]);
return appenderNames;
}
private String getAppenderNames(Map<String, Appender> appenders) {
Collection<Appender> existingAppenders = appenders.values();
String result = "";
for (Appender appender : existingAppenders) {
if (!result.isEmpty()) {
result += ",";
}
result += appender.getName();
}
return result;
}
public void changeLogLevel(String loggerName, Level level) {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = null;
if (loggerName.equals("ROOT")) {
loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
} else {
loggerConfig = config.getLoggerConfig(loggerName);
}
if (loggerConfig != null) {
loggerConfig.setLevel(level);
ctx.updateLoggers();
}
}
public void changeAppender(String loggerName, Level level, String appenderName) {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
Map<String, Appender> allAppenders = config.getAppenders();
Appender newAppender = allAppenders.get(appenderName);
if (newAppender != null) {
LoggerConfig loggerConfig = null;
org.apache.logging.log4j.core.Logger coreLogger = null;
if (loggerName.equals("ROOT")) {
loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
} else {
loggerConfig = config.getLoggerConfig(loggerName);
}
Map<String, Appender> appenders = loggerConfig.getAppenders();
Collection<Appender> existingAppenders = appenders.values();
for (Appender appender : existingAppenders) {
loggerConfig.removeAppender(appender.getName());
}
loggerConfig.addAppender(newAppender, level, null);
ctx.updateLoggers();
}
}
public void addLogger(String loggerName, Level level, String appenderName) {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = new LoggerConfig(loggerName, level, false);
Map<String, Appender> allAppenders = config.getAppenders();
Appender appender = allAppenders.get(appenderName);
loggerConfig.addAppender(appender, level, null);
config.addLogger(loggerName, loggerConfig);
ctx.updateLoggers();
}
public void deleteLogger(String loggerName) {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
config.removeLogger(loggerName);
ctx.updateLoggers();
}
}
LogLevelWin是使用基于Swing的上述方法的示例。 这是一个位日志代码,因此您可以跳过此步骤。
package com.foo.bar;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import net.miginfocom.swing.MigLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.ListSelectionModel;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Collection;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.JPanel;
public class LoglevelWin extends JFrame {
private static final long serialVersionUID = 1L;
private Component parent;
private JScrollPane scrollPane_1;
private JTable tblLoggers;
private JButton btnRefresh;
private JPanel panel;
private JButton btnNewButton;
private JButton btnDelete;
private boolean dirty;
private LogLevelPM logLevelPM = new LogLevelPM();
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
LoglevelWin frame = new LoglevelWin(null);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public LoglevelWin(Component parent) {
setMinimumSize(new Dimension(800, 400));
if (parent != null) {
this.parent = parent;
parent.setEnabled(false);
}
initUI();
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
close();
}
});
setLocationRelativeTo(null);
retrieveLoggers();
setVisible(true);
}
// logger from server
private void retrieveLoggers() {
// table model
Object[][] loggerModels = logLevelPM.retrieveLoggers();
if (loggerModels != null) {
String[] columnNames = new String[] {
"Logger Name", "Level", "Appender"
};
tblLoggers.setModel(new DefaultTableModel(loggerModels, columnNames) {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public java.lang.Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return String.class;
case 1:
return String.class;
case 2:
return String.class;
default:
return Object.class;
}
};
@Override
public boolean isCellEditable(int row, int col)
{
if (dirty) {
if ((row+1) == this.getRowCount()) {
return true;
}
}
return (col==0)?false:true;
}
});
setUpLevelColumn(tblLoggers.getColumnModel().getColumn(1));
String[] appenderNames = logLevelPM.getAllAppenders();
setUpAppenderColumn(appenderNames, tblLoggers.getColumnModel().getColumn(2));
tblLoggers.getColumnModel().getColumn(0).setPreferredWidth(300);
tblLoggers.getColumnModel().getColumn(2).setPreferredWidth(200);
tblLoggers.getTableHeader().setReorderingAllowed(false);
tblLoggers.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
int type = e.getType();
if (type != TableModelEvent.DELETE && type != TableModelEvent.INSERT) {
int row = e.getFirstRow();
int column = e.getColumn();
TableModel model = (TableModel)e.getSource();
String loggerName = (String) (model.getValueAt(row, 0));
String levelName = (String) (model.getValueAt(row, 1));
String appenderName = (String) model.getValueAt(row, 2);
if (dirty && (row+1) == model.getRowCount()) {
// add
if (loggerName != null
&& !loggerName.isEmpty()
&& levelName != null
&& !levelName.isEmpty()
&& appenderName != null
&& !appenderName.isEmpty()
) {
logLevelPM.addLogger(loggerName, Level.getLevel(levelName), appenderName);
dirty = false;
}
} else {
// update
if (column == 1) {
logLevelPM.changeLogLevel(loggerName, Level.getLevel(levelName));
}
if (column == 2) {
logLevelPM.changeAppender(loggerName, Level.getLevel(levelName), appenderName);
}
}
}
}
});
this.dirty = false;
}
}
private void setUpAppenderColumn(String[] appenderNames, TableColumn column) {
//Set up the editor for the sport cells.
JComboBox<String> comboBox = new JComboBox<String>();
for (int i = 0; i < appenderNames.length; i++) {
comboBox.addItem(appenderNames[i]);
}
column.setCellEditor(new DefaultCellEditor(comboBox));
//Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer =
new DefaultTableCellRenderer();
renderer.setToolTipText("Click for appender change");
column.setCellRenderer(renderer);
}
private void setUpLevelColumn(TableColumn column) {
//Set up the editor for the sport cells.
JComboBox<String> comboBox = new JComboBox<String>();
// for (Level level : Level.values()) {
// comboBox.addItem(level.toString());
// }
comboBox.addItem(Level.ALL.name());
comboBox.addItem(Level.TRACE.name());
comboBox.addItem(Level.DEBUG.name());
comboBox.addItem(Level.INFO.name());
comboBox.addItem(Level.WARN.name());
comboBox.addItem(Level.ERROR.name());
comboBox.addItem(Level.FATAL.name());
comboBox.addItem(Level.OFF.name());
column.setCellEditor(new DefaultCellEditor(comboBox));
//Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer =
new DefaultTableCellRenderer();
renderer.setToolTipText("Click for level change");
column.setCellRenderer(renderer);
}
private Object[][] retrieveLoggersLocal() {
Object[][] result = null;
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
Collection<LoggerConfig> loggerConfigs = config.getLoggers().values();
result = new Object[loggerConfigs.size()][];
result[0] = new Object[] {"ROOT", config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME).getLevel()};
int i = 1;
for (LoggerConfig loggerConfig : loggerConfigs) {
if (!loggerConfig.getName().isEmpty()) {
result[i++] = new Object[]{loggerConfig.getName(), loggerConfig.getLevel()};
}
}
return result;
}
private void close() {
if (parent != null) {
parent.setEnabled(true);
((JFrame)parent).toFront();
((JFrame)parent).repaint();
}
dispose();
}
private void initUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new MigLayout("", "[grow][][]", "[][grow][grow]"));
scrollPane_1 = new JScrollPane();
getContentPane().add(scrollPane_1, "cell 0 2,grow");
tblLoggers = new JTable();
tblLoggers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
tblLoggers.setModel(new DefaultTableModel(
new Object[][] {
},
new String[] {
"Logger Name", "Level", "Appender"
}
) {
private static final long serialVersionUID = 1L;
});
tblLoggers.getColumnModel().getColumn(0).setPreferredWidth(300);
tblLoggers.getColumnModel().getColumn(2).setPreferredWidth(200);
scrollPane_1.setViewportView(tblLoggers);
panel = new JPanel();
getContentPane().add(panel, "flowx,cell 1 2,grow");
panel.setLayout(new MigLayout("", "[73px]", "[23px][][]"));
btnRefresh = new JButton("Refresh");
panel.add(btnRefresh, "cell 0 0,growx");
btnNewButton = new JButton("Add");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
addLogger();
}
});
panel.add(btnNewButton, "cell 0 1,growx");
btnDelete = new JButton("Delete");
btnDelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
deleteLogger();
}
});
panel.add(btnDelete, "cell 0 2,growx");
btnRefresh.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
retrieveLoggers();
}
});
}
protected void deleteLogger() {
int row = tblLoggers.getSelectedRow();
if (row > 0) {
DefaultTableModel model = ((DefaultTableModel)tblLoggers.getModel());
String loggerName = (String) (model.getValueAt(row, 0));
logLevelPM.deleteLogger(loggerName);
model.removeRow(row);
tblLoggers.setRowSelectionInterval(row-1, row-1);
}
}
protected void addLogger() {
if (!dirty) {
DefaultTableModel model = ((DefaultTableModel)tblLoggers.getModel());
this.dirty = true;
model.addRow(new Object[]{"","",""});
}
}
protected void changeLogLevel(String loggerName, String level) {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = null;
if (loggerName.equals("ROOT")) {
loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
} else {
loggerConfig = config.getLoggerConfig(loggerName);
}
if (loggerConfig != null) {
loggerConfig.setLevel(Level.getLevel(level));
ctx.updateLoggers();
}
}
}
答案 1 :(得分:0)
我最近有机会以编程方式实现我想分享的log4j2记录器。
以下是使用ConfigurationBuider API在log4j2环境中创建/添加记录器的代码段:
package com.simple.log4j2.demo.demo;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
public class Log4j2Logger {
int counter = 0;
LoggerContext ctx;
Configuration config;
Logger logger;
String loggerName = "testLogger";
String appenderName = "myAppender";
static String testMessage = "This is a Test Message";
public void log() {
final ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
config = builder.build();
ctx = Configurator.initialize(config);
config = ctx.getConfiguration();
ctx.start(config);
ctx.updateLoggers(config);
// To create/add the logger of the configuration specified above we can use the
// getLogger(..) method
logger = ctx.getLogger(loggerName);
// Now we need to attach an appender to the logger so that our messages could be
// logged
logger.addAppender(addConsoleAppender(ctx.getConfiguration(), appenderName));
while (counter < 10) {
logger.error(testMessage + counter);
counter++;
}
// We can remove the logger in the context also after use.
removeLogger();
}
private Appender addConsoleAppender(Configuration config, String appenderName) {
Appender consoleAppender = ConsoleAppender.newBuilder().setConfiguration(config).setName(appenderName)
.withImmediateFlush(true).build();
consoleAppender.start();
return consoleAppender;
}
public void removeLogger() {
config.getLoggerConfig(loggerName).getAppenders().get(appenderName).stop();
config.getLoggerConfig(loggerName).removeAppender(appenderName);
config.removeLogger(loggerName);
ctx.updateLoggers(config);
}
}
对于测试,您可以在任何测试类中包含以下内容:
Log4j2Logger testLogger = new Log4j2Logger();
testLogger.log();
此API可帮助您以强大的方式处理日志。
您可以:
PS:我使用过log2.12版本2.12.1。