I want to share how I implemented it using log4j2.
You can add a new logger and delete an existing one.
And changing log levels is possible too.
src/
main/
java/
com/foo/bar/
LogLevelPM
LogLevelWin -- Swing UI
resources/
log4j2.xml
Configuration for 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 does actual operations and LogLevelWin is nothing but an example using it.
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 is an example using the above methods based on Swing.
This is a bit log code so you can skip this.
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();
}
}
}