Log4j2 SyslogAppender Set Layout Programmatically - java

i recently had the necessity to migrate from log4j 1.x to log4j 2.x.
In my code, i dynamically instantiate different Syslog appenders which may use two different layout types.
I'm using a getSysLogAppender method to generate a SyslogAppender object whenever i need in my code. Unfortunately, if i set the layout using the setLayout() function, my logs do not get sent one-at-a-time as i've expected. If i remove the setLayout() function from the builder and just leave the setFormat("RFC5424"), logs are sent correctly.
Due to application needs, i cannot just take the RFC5424 as it is implemented in log4j2, i need to customize the layout of the logs.
Looking at log4j2 SyslogAppender source code, if the format is RFC5424 and a layout is given, format RFC5424 is not taken into consideration: https://github.com/apache/logging-log4j2/blob/release-2.x/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SyslogAppender.java (line 114).
What's the correct way to customize the SyslogAppender layout?
Thanks in advance.
// Class variables
private static final String pattern1 = "%d %-1p - %m";
private static final String pattern2 = "%d %-5p [%t] %-4c{2} (%13F:%L) %3x - %m";
private static final String hostname = "localhost";
private static final String port = "2601";
private void createAppender() {
Appender appender = getSyslogAppender("TESTID", Facility.USER, pattern1); //third parameter may be also pattern2 var
appender.start();
}
// Method that generates my appender
private SyslogAppender getSyslogAppender(String id, Facility facility, String pattern) {
return SyslogAppender.newSyslogAppenderBuilder().withProtocol(myprotocol).withHost(hostname).withPort(port).setFacility(facility).setId(id).withBufferedIo(false)
.setLayout(org.apache.logging.log4j.core.layout.PatternLayout.newBuilder().withPattern(pattern).build())
.setName("log4jAppender").withImmediateFlush(true).setNewLine(true).setFormat("RFC5424").build();
}

Related

Log4j2 Different color per logger

In my project I use Log4j 2.17.1.
I would like to format the output so that the class names have different colors.
public class MyClass {
Logger LOGGER = LogManager.getLogger(MyClass.class.getSimpleName());
//...
LOGGER.debug("Some Information");
}
public class MySecondClass {
Logger LOGGER = LogManager.getLogger(MySecondClass.class.getSimpleName());
//...
LOGGER.debug("Another Output");
}
In my example, I want the two classes to appear in different (perhaps random) colors (instead of yellow as in the example).
My current pattern layout:
%highlight{${LOG_LEVEL_PATTERN:-%5p}}{FATAL=red blink, ERROR=red, WARN=yellow bold, INFO=green, DEBUG=green bold, TRACE=blue} : %style{%logger{36}:}{blue} %msg%n
Is this possible with Log4j?
Per defeault log4j writes simple text files with no fancy formatting applied (FileAppender, ConsoleAppender).
I have never done this, but I believe you can add ANSI escape sequences using a suitable formatting pattern, then enjoy the colours when the log output is sent to a terminal capable of understanding these sequences.

log4j2: custom formating for pattern parameter

Usually logging looks like this:
Duration duration = ...;
log.info("Duration: {}", duration);
But what do if you need custom formatting?
if (log.isInfoEnabled()) {
String value = duration.toSeconds() + "." + duration.toMillis();
log.info("Duration: {}", value);
}
In this case code is complicated. I'm looking for a way to do simple logging as in first sample but to be able to customize value formatting using some mechanism, e.g, define a format function for given type:
LogSystem.install(Duration.class, duration -> {
return String.format("%d.%d", duration.toSeconds(), duration.toMillis();
});
Questions:
does log4j 2.x have such or similar feature?
may be it exists in other logging libraries?
if no, can if (log.isInfoEnabled()) { ... } be simplified somehow?
does log4j 2.x have such or similar feature?
Yes, you can use
log.info("Duration: {}.{}", duration.toSeconds(), duration.toMillis());
You can pass as many parameters as you like. If you use parameterized logging, you don't need to check log.isInfoEnabled().
may be it exists in other logging libraries?
SLF4j also supports parameterized logging.
Yes, you can do it using the properties file.Set policies pattern in your log4j2.properties file like:
appender.rolling.type = RollingFile
appender.rolling.name = RollingFile
appender.rolling.fileName = ABClog/ABCapplication.log
appender.rolling.filePattern = ABClog/ABCapplication.%d{dd-MMM}.log
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = { [%-5level %d{dd-MM-yyyy hh:mm:ss.SSS } ] [%msg] }%n
After setting the above configuration in your log4j2.proerties file, you will get your desired output, even using properties file concept you can add extra info too e.g. Correlation-ID
log.info("hello")
Log4j2 document for more pattern style: https://logging.apache.org/log4j/2.x/manual/layouts.html

How to print event level in lowercase using log4j12?

Is there any possibility to print event levels to log in lower case in log4j 2?
Like %level{lowerCase=true} in pattern in Log4j 2.
Can I process result string somehow, or use custom renderer?
You have to set a pattern to the appropriate appender in the log4j.properties file.
For instance, with ConsoleAppender:
log4j.appender.ConsoleAppender.layout.ConversionPattern=%d [%p{lowerCase=true}] %c{1} - %m%n
You can check the output here.

How to change slf4j log into html link

I have java code as:
final URI myUri = new URIBuilder()
.setScheme(azkabanHostProtocol)
.setHost(azkabanHost + ":" + azkabanPort)
.setPath("/executor")
.setParameter("execid", executionID).build();
logger.info(myUri.toString());
I want to display myURI in form of an url/html link into Azkaban's logs so that by clicking on the url it is opened. I am using log4j for logging.
You may create your own Layout class extending HTMLLayout .
Then override the format method to suit your needs.
The actual implementation has the following lines, that you may want to replace :
sbuf.append(Transform.escapeTags(event.getRenderedMessage()));
See that all tags in the message String, will be escaped by default.
Your version could be based on a kind of marker, say String mark = "[LINK]"; for instance
if(event.getRenderedMessage().startsWith(mark)){
String uri = event.getRenderedMessage().substring(mark.length());
String link = "" + uri + "";
sbuf.append(link);
}
else
sbuf.append(Transform.escapeTags(event.getRenderedMessage()));
And you would call the logger this way :
logger.info(mark + myUri.toString());
The following topic will help you use a custom HTMLLayout : how to change htmllayout in log4j2
Here is the source code for the default HTMLLayout, as a starter.
How do you view the Azkaban log files? If they are just raw text files being viewed with a vanilla text editor then there is no way to accomplish what you want. If you are viewing them in a smarter UI then you need to format them according to what that UI requires.
In short, the answer to your question is completely driven by whatever tool you are using to view the logs.

Using log4j2, how to log key value pairs

I need to create logs with key value pairs as below. Is there any support in PatternLayout to do this for the static fields in a thread like log_level, class_name, event_id etc with the log4j2.xml.
Sample log:
2014-06-18 11:57:46,719 log_level="INFO"
class_name="com.abc.dgl.App:main(158)" name="Application start event" event_id="b88f7ea0-4cb1-438f-a728-ac7c2bdac578" app="Test App" severity="info" action="loaded sfor file processing" desc="props was read and loaded" result="success" reason="abc" transaction_id="b88f7ea0-4cb1-438f-a728-ac7c2bdac578"
Yes, this is possible.
You can either use a MapMessage, which is supported by the map (or K) conversion pattern of PatternLayout: an example layout pattern would be "%-5p [%t]: %m %map%n".
Logging a MapMessage looks like this: Map<String,String> myMap = getMyMap(); Logger.debug(new MapMessage(myMap));
Another way to do this is to use the ThreadContext map. This is supported by the mdc (or X) conversion pattern of PatternLayout. Example pattern: "%-5p [%t]: %m %mdc%n".
A common usage is putting a user ID in the Thread Context Map when a user logs in, and having this user ID shown in all log messages emitted by that thread until the user logs out.
Instead of logging the whole map you can also log specific keys only by specifying the key in the layout pattern: e.g. "%-5p [%t]: %m %mdc{userID}%n".

Categories

Resources