How to properly create a RollingFileAppender with

2019-05-31 10:19发布

问题:

I would like the user to choose the type of the appender(s) that will be created via a configurable option.

For example, let's say that I have a command line argument that controls the type of the appenders that will be created for that process. The user can choose one of these values: file,syslog, or both.

I would like to do this in a programmatic way, rather than using an external xml configuration file.

This is a simplified version of my attempt to create a logger with a syslog appender in a programmatic way.

// simplified version of a method that creates and returns a logger
// using AppenderComponentBuilder
static Logger createLogger()
{
        ConfigurationBuilder< BuiltConfiguration > builder =
                ConfigurationBuilderFactory.newConfigurationBuilder();

        builder.setStatusLevel( Level.OFF );

        // create the syslog appender
        AppenderComponentBuilder appenderBuilder =
                builder.newAppender( "syslogAppender", "Syslog" )
                .addAttribute( "protocol", "TCP" )
                .addAttribute( "host", "localhost" )
                .addAttribute( "port", 514 )
                .addAttribute( "facility", "LOCAL2" )
                .addAttribute( "immediateFlush", true )
                .addAttribute( "newLine", true );
        builder.add( appenderBuilder );

        // create the new logger
        builder.add( builder.newLogger( "TestLogger", Level.DEBUG )
                .add( builder.newAppenderRef( "syslogAppender" ) )
                .addAttribute( "additivity", false ) );

        builder.add( builder.newRootLogger( Level.DEBUG )
                .add( builder.newAppenderRef( "syslogAppender" ) ) );

        // Initialize the new configuration
        LoggerContext ctx = Configurator.initialize( builder.build() );
        Logger logger = ctx.getLogger( "TestLogger" );
        return logger;
}

My questions:

1) Do you believe that this is the best way to use the log4j 2 API in order to programmatically create a logger and a syslog appender?

2) I would like to extend the above createLogger() method so that it will create the proper appenders depending on the user choice: file,syslog,both. The "file" option should create a Rolling file appender with a specific pattern layout, triggering policy, and rollover strategy. I tried to use the same log4j 2 API and use the AppenderComponentBuilder to do this, but I couldn't find a correct way of doing this. The only way I managed to programmatically do this was with the RollingFileAppender.createAppender() method, which is a real pain and makes it very difficult to allow me to create, on the fly, programmatically, a single logger with either a rolling file appender, a syslog appender or both (depending on the user input).

So, in essence, what I am looking for is the proper way to programmatically create a RollingFileAppender with a specific pattern layout, triggering policy, and rollover strategy using AppenderComponentBuilder.

Thanks in advance

回答1:

  1. Yes, this is the intended way to programmatically create a new configuration.

  2. Here is an example of how to create a rolling file appender. Since Appenders can be configured with arbitrary components you use the generic ComponentBuilder to specify those plugins.

    ConfigurationBuilder< BuiltConfiguration > builder =
            ConfigurationBuilderFactory.newConfigurationBuilder();
    
    builder.setStatusLevel( Level.ERROR);
    builder.setConfigurationName("RollingBuilder");
    // create the console appender
    AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
            ConsoleAppender.Target.SYSTEM_OUT);
    appenderBuilder.add(builder.newLayout("PatternLayout").
            addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
    builder.add( appenderBuilder );
    
    LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
            .addAttribute("pattern", "%d [%t] %-5level: %msg%n");
    ComponentBuilder triggeringPolicy = builder.newComponent("Policies")
            .addComponent(builder.newComponent("CronTriggeringPolicy").addAttribute("schedule", "0 0 0 * * ?"))
            .addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", "100M"));
    appenderBuilder = builder.newAppender("rolling", "RollingFile")
            .addAttribute("fileName", "target/rolling.log")
            .addAttribute("filePattern", "target/archive/rolling-%d{MM-dd-yy}.log.gz")
            .add(layoutBuilder)
            .addComponent(triggeringPolicy);
    builder.add(appenderBuilder);
    
    // create the new logger
    builder.add( builder.newLogger( "TestLogger", Level.DEBUG )
            .add( builder.newAppenderRef( "rolling" ) )
            .addAttribute( "additivity", false ) );
    
    builder.add( builder.newRootLogger( Level.DEBUG )
            .add( builder.newAppenderRef( "rolling" ) ) );
    Configurator.initialize(builder.build());