简体   繁体   English

以编程方式在 log4j2.xml 中添加记录器

[英]Adding logger in log4j2.xml programmatically

Is it possible to add loggers programmability in log4j2 just by specifying the logger name?是否可以仅通过指定记录器名称在log4j2添加记录器可编程性? I tired to search it on the web and I came across something saying that log4j2 doesn't allow this kind of feature.我厌倦了在网络上搜索它,我遇到了一些说log4j2不允许这种功能的东西。 Here is the link:链接在这里:

How to add Log4J2 appenders at runtime programmatically? 如何以编程方式在运行时添加 Log4J2 附加程序?

Is there a way to do this?有没有办法做到这一点?

I want to share how I implemented it using log4j2.我想分享我如何使用 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 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. 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 is an example using the above methods based on Swing. LogLevelWin 是基于 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();            
        }
    }
}

I recently had a chance to implement log4j2 loggers programmatically which I would like to share.我最近有机会以编程方式实现 log4j2 记录器,我想分享一下。

Following is a code snippet to create/add loggers in log4j2 environment using the ConfigurationBuider API:以下是使用 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);
    }
}

And for testing, you can have following in any test class:对于测试,您可以在任何测试类中进行以下操作:

    Log4j2Logger testLogger = new Log4j2Logger();
    testLogger.log();

This API helps you to handle logs in a powerful way.此 API 可帮助您以强大的方式处理日志。

You can :你可以 :

  • Create multiple loggers with your configuration使用您的配置创建多个记录器
  • Add multiple Appenders to it.Configure them also.向其中添加多个 Appender。也要配置它们。
  • Remove logger when the usage is over.使用结束后删除记录器。
  • Create Asynchronous Loggers also.也创建异步记录器。

PS : I have used log4j2 version 2.12.1. PS:我用的是log4j2 2.12.1版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM