3

Right now I am trying use log4j2 to log everything that has a level of INFO or higher (WARN, ERROR, AND FATAL) to my server and anything that has a level of INFO to my console. I am able to log things to my console, however, I am having an issue logging the correct levels to the server properly.

Here is what I have tried so far:

Java

import java.time.Instant;

import org.apache.log4j.PropertyConfigurator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class App {
    private static final Logger log4j = LogManager.getLogger(App.class.getName());

    public static void main(String[] args) {
        try {
            String log4jConfPath = "src/main/resources/log4j2.xml";
            PropertyConfigurator.configure(log4jConfPath);
            log4j.info("this is a testmessage " + Instant.now().toString());
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace" packages="org.graylog2.log4j2">

    <Properties>
        <Property name="default_pattern">%d{MM/dd/yyyy hh:mm:ss} %5p %c{1} - %m%n
        </Property>
    </Properties>

    <Appenders>
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="${default_pattern}" />
        </Console>
        <GELF name="gelfAppender" server="graylog.x.something.com"
            hostName="some.host" port="12201">
            <PatternLayout pattern="%d{dd MMM yyyy HH:mm:ss,SSS} %5p %c{1} - %m%n" />
            <KeyValuePair key="extractStacktrace" value="true" />
            <KeyValuePair key="addExtendedInformation" value="true" />
            <KeyValuePair key="facility" value="gelf-java" />
            <KeyValuePair key="environment" value="TEST" />
            <KeyValuePair key="application" value="MyApp" />
            <KeyValuePair key="additionalFields" value="{'environment': 'TEST', 'application': 'MyAPP'}" />
        </GELF>
    </Appenders>

    <Loggers>
        <Root level="error">
            <AppenderRef ref="gelfAppender" />
            <AppenderRef ref="console" />
        </Root>
        <Root level="info">
            <AppenderRef ref="gelfAppender" />
            <AppenderRef ref="console" />

        </Root>
    </Loggers>
</Configuration>

The above code does not output what I want, which is to have INFO level output to the console and INFO Levels and up output to the server.

Instead, I am able to output: EVERYTHING (Trace) to console and INFO to the server.

I have messed around with the XML file a little bit and I noticed that when I change

status="trace"

to

status="off"

it logs only INFO to the console, but nothing to the server.

Lastly, and probably the most odd thing of all, if I remove

Instant.now().toString()

from my print statement, then nothing will be logged to the server, regardless of the status (if it's TRACE or OFF), but it still logs to the console. I thought it had something to do with the pattern layout of my GELF appender, so I changed

<PatternLayout pattern="%d{dd MMM yyyy HH:mm:ss,SSS} %5p %c{1} - %m%n" />

to

<PatternLayout pattern="${default_pattern}" />

but that did not change the output...

Here are my current dependencies:

enter image description here

In short, I just want to log levels of INFO to my console and levels of INFO or higher to my server.

mr nooby noob
  • 1,860
  • 5
  • 33
  • 56
  • [This question](http://stackoverflow.com/questions/26108045/how-to-log-only-one-level-with-log4j2) tells you how to set up Log4j2 so that INFO and only INFO log messages go to the console. Also, I'm not sure why you have two `` elements in ``: as I understand it there should only be one, so try removing `` and see if that helps. – Luke Woodward Oct 25 '16 at 21:09
  • Thank you for the link.I removed the extra ROOT element and I added the threshold filters, but still no luck. – mr nooby noob Oct 25 '16 at 23:18

1 Answers1

4

As you seem to have figured out you should use the threshold filter to filter messages of level WARN and up from the console appender.

The correct way to specify different levels for different appenders is to specify it on the <Appender> element like this:

<Loggers>
    <Root level="trace">
        <Appender ref="console"/>
        <Appender ref="file" level="info"/>
    </Root>
</Logger>

As to solving your problem, here's a simple example program and configuration that outputs INFO level messages to console, all log messages to everything.log and INFO and up to infoAndUp.log.

LogTest.java:

public class LogTest {

    public static void main(String[] args) {
        final Logger log = LogManager.getLogger();

        log.trace("This is a trace message");
        log.debug("This is a debug message");
        log.info("This is an info message");
        log.warn("This is a warning message");
        log.error("This is an error message");
        log.fatal("This is a fatal message");
    }
}

log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="console">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <Filters>
                <!-- Exclude messages logged above INFO -->
                <ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
            </Filters>
        </Console>
        <File name="everything" fileName="everything.log">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </File>
        <File name="infoAndUp" fileName="infoAndUp.log">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </File>
    </Appenders>
    <Loggers>
        <Root level="trace">
            <AppenderRef ref="console" level="info"/>
            <AppenderRef ref="everything" />
            <AppenderRef ref="infoAndUp" level="info"/>
        </Root>
    </Loggers>
</Configuration>

Results

Console output:

09:29:35.331 [main] INFO  LogTest - This is an info message

everything.log:

09:29:35.330 [main] TRACE LogTest - This is a trace message
09:29:35.331 [main] DEBUG LogTest - This is a debug message
09:29:35.331 [main] INFO  LogTest - This is an info message
09:29:35.332 [main] WARN  LogTest - This is a warning message
09:29:35.332 [main] ERROR LogTest - This is an error message
09:29:35.332 [main] FATAL LogTest - This is a fatal message

infoAndUp.log:

09:29:35.331 [main] INFO  LogTest - This is an info message
09:29:35.332 [main] WARN  LogTest - This is a warning message
09:29:35.332 [main] ERROR LogTest - This is an error message
09:29:35.332 [main] FATAL LogTest - This is a fatal message

You should be able to fix your own config using this as a base.

Raniz
  • 10,882
  • 1
  • 32
  • 64
  • Cool thank you, it works! I know you answered my question, but I have one last question: how come when I add my GELF appender to the above code everything works fine, but if I remove the two File appenders and their corresponding loggers, nothing gets logs to my GELF appender? – mr nooby noob Oct 27 '16 at 21:32
  • That sounds pretty weird and it's hard to say without actually seeing your config. Maybe you can open up a new question seeing as this one was solved. – Raniz Oct 28 '16 at 07:49
  • I agree, it makes no sense to me at all, since the File appender and logger should have nothing to do with anything else but logging to only that file. I have created the new question here: https://stackoverflow.com/questions/40315123/log4j2-does-not-log-to-server-after-removing-file-appender – mr nooby noob Oct 29 '16 at 01:21