Is it possible for using different pattern layout for different log level and output to SYSTEM_OUT?
Asked Answered
P

4

10

For log4j2, is it possible for using different pattern layout for different log level and output to SYSTEM_OUT?

Here is my log4j2.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration>
        <Appenders>
            <Console name="debugMsg" target="SYSTEM_OUT">
                <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %l - %msg%n"/>
            </Console>
            <Console name="infoMsg" target="SYSTEM_OUT">
                <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %msg%n"/>
            </Console>
        </Appenders>
        <Loggers>
            <Root level="trace"  additivity="false">
                <AppenderRef ref="infoMsg" level="info"/>
                <AppenderRef ref="debugMsg" level="debug"/>
            </Root>
        </Loggers>
    </Configuration>

However, the INFO level message are shown in both "infoMsg" and "debugMsg" pattern.

2015-12-24 10:51:56.176 Log4j is ready.
[INFO ] 2015-12-24 10:51:56.176 com.myftpserver.MyFtpServer.<init>(MyFtpServer.java:65) - Log4j is ready.
2015-12-24 10:51:56.176 Configuration file is loaded
[INFO ] 2015-12-24 10:51:56.176 com.myftpserver.Configuration.load(Configuration.java:74) - Configuration file is loaded
[DEBUG] 2015-12-24 10:51:56.176 com.myftpserver.Configuration.load(Configuration.java:82) - supportPassiveMode=true
2015-12-24 10:51:56.301 User Manager class is loaded.
[INFO ] 2015-12-24 10:51:56.301 com.myftpserver.Configuration.load(Configuration.java:119) - User Manager class is loaded.
2015-12-24 10:51:56.301 File Manager class is loaded.
[INFO ] 2015-12-24 10:51:56.301 com.myftpserver.Configuration.load(Configuration.java:121) - File Manager class is loaded.
2015-12-24 10:51:56.301 Server Initialization completed.
[INFO ] 2015-12-24 10:51:56.301 com.myftpserver.MyFtpServer.<init>(MyFtpServer.java:69) - Server Initialization completed.
2015-12-24 10:51:56.301 Available passive port:[1232, 1233, 1234]
[INFO ] 2015-12-24 10:51:56.301 com.myftpserver.MyFtpServer.<init>(MyFtpServer.java:75) - Available passive port:[1232, 1233, 1234]

So, is it possible to remove duplicate item?

thank you very much and Merry X'mas

Pretended answered 24/12, 2015 at 3:3 Comment(0)
T
10

The latest versions of Log4j2 allow a pattern selector instead of just a single pattern. Log4j provides a selector based on markers but not one based on levels. Create a Jira issue and I will add it. However, Log4j does allow you to used a script to select the pattern. It would be simple to write one that selects based on the level.

In the configuration above the debug appender is also going to output info level events, which is why you see the duplicates.

I haven't tested it but I believe the configuration below should do what you want:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout>
                <ScriptPatternSelector defaultPattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %l - %msg%n">
                    <Script name="LevelSelector" language="bsh"><![CDATA[
                        if (logEvent.getLevel() == org.apache.logging.log4j.Level.INFO) {
                            return "INFO";
                        } 
                        return null;
                        ]]>
                    </Script>
                    <PatternMatch key="INFO" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %msg%n"/>
                </ScriptPatternSelector>
            </PatternLayout>
        </Console> 
    </Appenders>
    <Loggers>
        <Root level="trace">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>
Twedy answered 24/12, 2015 at 14:31 Comment(0)
E
7

Yes. Since log4j 2.13 there is the LevelPatternSelector. You can use it like that.

I use the error/fatal case as default pattern. You can also specify it explicite.

      <Console name="stdout" target="SYSTEM_OUT">
         <PatternLayout>
            <LevelPatternSelector defaultPattern="%highlight{[%p] %d{HH:mm:ss} %c:%L %m}{bright,red}%n">
               <PatternMatch key="WARN" pattern="%highlight{[%p] %d{HH:mm:ss} %c:%L %m}{bright,yellow}%n" />
               <PatternMatch key="INFO" pattern="[%style{%p}{blue}] %d{HH:mm:ss} %c:%L %m%n" />
               <PatternMatch key="DEBUG" pattern="[%p] %d{HH:mm:ss} %c:%L %m%n" />
               <PatternMatch key="TRACE" pattern="[%p] %d{HH:mm:ss} %c:%L %m%n" />
            </LevelPatternSelector>
         </PatternLayout>
      </Console>
Epicotyl answered 22/10, 2021 at 10:13 Comment(0)
P
4

Finally, I get it works

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration>
        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout>
                    <ScriptPatternSelector defaultPattern="">
                        <Script name="LevelSelector" language="javascript"><![CDATA[
                            result=null;
                            switch (logEvent.getLevel())
                            {
                                case org.apache.logging.log4j.Level.DEBUG:
                                case org.apache.logging.log4j.Level.INFO:result=logEvent.getLevel();
                                                                         break;
                                default:result=null;                                            
                            }
                            result;
                            ]]>
                        </Script>
                        <PatternMatch key="DEBUG" pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %l - %msg%n"/>
                        <PatternMatch key="INFO" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %msg%n"/>
                    </ScriptPatternSelector>
                </PatternLayout>
            </Console> 
        </Appenders>
        <Loggers>
            <Root level="trace">
                <AppenderRef ref="Console"/>
            </Root>
        </Loggers>
    </Configuration>

thank you for your inspiration.

Pretended answered 25/12, 2015 at 13:34 Comment(0)
F
0

I was very interested in the programmatic version of this. If you go here, it’ll get you started. Then you can use this, which works:

    String level = String.format("\u001b[0;34m%s\u001b[m", "%-5level");
    AppenderComponentBuilder sqlConsole = builder.newAppender("sqlconsole", "Console");
    LayoutComponentBuilder sqlLayout = builder.newLayout("PatternLayout");
    String colorSql = String.format("\u001b[0;35m%s\u001b[m", "%msg");
    
    String redLevel = String.format("\u001b[0;31m%s\u001b[m", "%-5level");
    ComponentBuilder patternSelector = builder.newComponent("LevelPatternSelector")
      .addAttribute("defaultPattern", level + ": " + colorSql + "%n")
      .addComponent(builder.newComponent("PatternMatch")
          .addAttribute("key", "ERROR")
          .addAttribute("pattern", redLevel + ": " + colorSql + "%n"));
        
    sqlLayout.addComponent(patternSelector);
    sqlConsole.add(sqlLayout);
    builder.add(sqlConsole);

It’s using bash (shell?) color codes but…I hope you can manage. Then reference the “sqlconsole” appender when you configure the loggers, or as otherwise needed.

Formyl answered 13/3 at 1:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.