logback how to log only the classname not also the package path? - java

I have an appender in my logback xml config:
<encoder>
<pattern>%d{"yyyy-MM-dd HH:mm:ss"} [%thread] %-5level %logger{5} - %msg %n</pattern>
</encoder>
but it prints out the abbreviated package along with the class, even if I set it to %logger{1} like:
2019-12-19 10:26:16 [main] INFO o.f.d.d.u.Myclass - my message
I want it to just log the class MyClass like log4j does. How?

looks like the number you specify for %logger is some kind of special case and doesnt' exactly dictate size. Except it does dictate size, but never less than a minimum size which is the entire package path with the full class name. Unless you set it to "0" which is a special case to mean "don't include the package".
So if I set it to %logger{0} then I get just the class name, see http://logback.qos.ch/manual/layouts.html#conversionWord
2019-12-19 10:28:45 [main] INFO MyClass - my message
In log4j the equivalent would have been %c{1} or %logger{1} so I guess it's different.

Related

Print event severity in sentencecase: log4j2

I want to print the event severity in sentence case, in the logs instead of default Uppercase. I have modified the log4j2 xml like below,
<Console name="STDOUT" target="SYSTEM_OUT" direct=true>
<PatternLayout pattern="%level{WARN=Warning, DEBUG=Debug, ERROR=Error, TRACE=Trace, INFO=Info}"/>
</Console>
<Loggers>
<AsyncRoot level="INFO" includeLocation="false">
<AppenderRef ref="STDOUT">
</AsyncRoot>
</Loggers>
Current Event Severity Printed in Logs :
INFO / WARNING / DEBUG / ERROR / TRACE
Expected Event Severity Printed in Logs :
Info/ Warning / Debug / Error / Trace
I still see the event is getting printed in Uppercase in logs. Something else need to be changed ?
According to my reading of the org.apache.logging.log4j.core.pattern.LevelPatternConverter source code, Log4j2 should output the level replacement strings exactly as you gave them in the pattern.
If that's not happening, check that Log4j2 is actually using that config.
If that doesn't resolve the problem, you may need to use a debugger to figure out what is going on.

How to add dynamic metadata to a singleton SLF4J logger in Java?

This is a Java question.
I have around 100 static functions that use a slf4j logger.
I want to add some metadata to standardise the logs - assume it's some kind of preamble that is a function of what processing is currently going on.
How can I get the logger to print that metadata without going in to each of the static functions and changing them to explicitly add in the metadata.
e.g.
static Logger logger; ...
void mainProcessing() {
String file = "current_file.txt";
int line = 3;
...
func1();
func2();
...
}
void func1() {
...
logger.warn("some warning");
}
I'd like to see "WARN: File current_file.txt, line 3, msg: some warning" in the logs.
Any ideas?
(Prefer not to have to change each of the func1() functions obviously, if possible)
Thanks in advance.
You need to specify print format. However beware, that obtaining line number and/or file will greatly decrease your application performance. This is not C++, Logback will probably create a Throwable object for each line, to retrieve the stacktrace and extract the line number and file name.
Regarding line:
L / line Outputs the line number from where the logging request was
issued.
Generating the line number information is not particularly fast. Thus,
its use should be avoided unless execution speed is not an issue.
Regarding file:
F / file Outputs the file name of the Java source file where the
logging request was issued.
Generating the file information is not particularly fast. Thus, its
use should be avoided unless execution speed is not an issue.
http://logback.qos.ch/manual/layouts.html#file
Sample logback.xml configuration would be:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{"yy-MM-dd HH:mm:ss,SSS"}: %-5p %F:%L [%t] %c{0}: %M - %m%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="console" />
</root>
</configuration>
Better to redesign your code, that messages are more verbose and not unique, containing the context and required data to debug it by a person that does not know the code very well (your future co-worker)

How to log the second argument in log4j

I am trying to use log4j for the first time and I have configured it correctly, I just wanted to know how can I print the details of the argument passed as second parameter:
LogManager.getLogger(SomeName.class.getName()).info(message, detail);
and my configuration appender is:
<File name="file1" fileName="output.log">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
I think there should be some switch within the pattern after %msg if I want to log the detail there. But I am not sure what or how.
Though I was expecting some better solution, but this seems to be the only one available.
LogManager.getLogger(SomeName.class.getName()).info("Message: {}, Detail: {}", message, detail);
LogManager.getLogger().info(
"The {} is that {}, there are more {},"
+ " not necessarily in a message + details {}.",
"reason", "often", "parameters", "relationship");

Log4j2 Rolling appender - fileName "sliding" according to pattern

I am looking for rollover strategy where current log (active output target in manual's terminology) file name is not fixed but specified by a pattern, or - more precisely - same pattern as in filePattern attribute.
I want to achieve daily rollover where today's log is, say, log-2015-05-05.log and on midnight framework just stops writing it and starts writing into log-2015-05-06.log. However, AFAIK, current configuration allows only
<RollingFile name="ROLFILE"
fileName="log.log"
filePattern="log-%d{yyyy-MM-dd}.log"
>
Specifying same value into fileName attribute doesn't work (leads to file with sensitive characters literally interpreted). I noticed no example or SO question with such a dynamic value of fileName. Note the fileName="log-${date:yyyy-MM-dd}.log" doesn't solve problem since expression is evaluated only at startup and events are still sent into file even if their timestamp doesn't match the expression.
I am migrating from Log4j 1.2 to Log4j 2.2. In old version, required behavior was possible using
<appender name="ROLFILE" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern" value="log-%d{yyyy-MM-dd}.log" />
</rollingPolicy>
...
I prefer to preserve current way since some log analyzing tools rely on it.
Is it possible in Log4j2?
Thanks.
Note sure if this works, but you can try using a double $$ in the date lookup. This allows the variable to be resolved at runtime.
<RollingFile name="ROLFILE"
fileName="log-$${date:yyyy-MM-dd}.log"
filePattern="oldlog-%d{yyyy-MM-dd}.log"
>
You may need to be careful to ensure that the active output target file name is different from the after-rollover file name. (I used 'oldlog' in the snippet above.)
Finally, I wrote my own rollover strategy which generates different set of rollover actions. Instead renaming active file the active file name is simply replaced inside RollingFileManager. Yes, it's ugly reflection hack and also appender must be initialized with fileName constant corresponding with current date and having same pattern, e.g.
<RollingFile name="ROLFILE"
fileName="log-${date:yyyy-MM-dd}.log"
filePattern="log-%d{yyyy-MM-dd}.log"
>
<SlidingFilenameRolloverStrategy />
...
yet for me this solution is worth doing it despite these small drawbacks.
(Initial fileName stays forever as a key in AbstractManager registry MAP even if in manager itself it has been changed - seems it doesn't mind, I also tried replacing manager in registry for new one but it's impossible to collect all parameters necessary for its construction.)
I hope this hack shouldn't have been so ugly if RollingFileManager API made it possible normal way. I got some hope seeing this javadoc but framework AFAIK never utilizes this field, let alone for mutating RollingFileAppender.
I think it would work just fine using:
fileName="log-${date:yyyy-MM-dd}.log"
filePattern="log-%d{yyyy-MM-dd}.log"
I use it with log4j2 version 2.5
This has been implemented in Log4j 2.8 (see issue LOG4J2-1101).
Currently it only works with a RollingFile appender by omitting the filename parameter and using a DirectWriteRolloverStrategy.
Also, this feature seems to have some issues with the TimeBasedTriggeringPolicy (the first rollover doesn't happen so every logfile is offset by one interval); CronTriggeringPolicy works properly.
Example config:
<RollingRandomAccessFile name="MyLogger"
filePattern="logs/application.%d{yyyy-MM-dd}.log">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
<Policies>
<CronTriggeringPolicy schedule="0 * * * * ?" evaluateOnStartup="true"/>
</Policies>
<DirectWriteRolloverStrategy/>
</RollingRandomAccessFile>
Support for RollingRandomAccessFile appender is requested in issue LOG4J2-1878.
Edit: Changed to CronTriggeringPolicy policy after finding TimeBasedTriggeringPolicy had issues.

log4j record-like log

I want log4j to produce record-like output.
What I DON'T want:
1 INFO ... - User login: Agostino
120 INFO ... - Start process: 0, elements to process 100
What I want:
1 INFO ... - User: Agostino, processid:null, elements: null, message: login
1 INFO ... - User: Agostino, processid:0, elements: 100, message: start process
I think I should use a ObjectRenderer, and since many data are contained in objects that I already have, so I think something like:
public class MyMessage {
Object myContextObject; //**this** contains user, processid, elements
String message;
}
What I am doing here is passing a "context object" that provides fields PLUS a message string. An ObjectRenderer then will do the formatting, based on myContextObject type.
Now i'm wondering if ObjectRenderer is designed with something like this in mind.
If this was the normal use of ObjectRenderer, probably they'd provide a
log(String message, Object myContextObject) that prevent the creation of the dummy wrapper MyMessage.
As an alternative to the ObjectRenderer, You might want to look into log4j's PatternLayout, which can be configured programmatically, or configuratively:
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
for instance, you can do something like this (just an arbitrary example):
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p (%-35F:%-4L) - %m%n"/>
</layout>
</appender>
Once you've established that, you can use the %X{clientNumber} pattern for retrieving data from your custom classes via MDC
http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html

Categories