Don't log sensitive information
Include as much dynamic info as possible
Paste logging in PR if applicable
Make sure there is enough logging to help trouble shooting issues in production later
sfl4j
log.warn("hello: {}, {}", "A", "B", new RuntimeException("wtf"));
Throwable throwableCandidate = getThrowableCandidate(argArray);
Logback
-Dlogback.debug=true
<configuration debug="true">
Log method and line number
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n
Pattern
Use %M to print method name in debug environment.
%class{1}
MDC - Mapped Diagnostic Context
%X{X-RequestId}, %X{sessionId}
MDC.put("X-RequestId", requestId)
-- Don't forget to MDC.clear() at the beginning and end of the request.
Use MDC in thread pools
Only log stats into app-stats.log
- Don't log to app.log and stdout(in dev)
Async logging
logger.error("xx {} yy {} xx {}", x, y, z);
SiftingAppender
Log4j
-Dlog4j.debug
Log4j2
https://logging.apache.org/log4j/2.0/faq.html#troubleshooting
-DLog4jDefaultStatusLevel=DEBUG
-Dorg.apache.logging.log4j.simplelog.StatusLogger.level=TRACE
Lazy Logging
logger.trace("Some long-running operation returned {}", () -> expensiveOperation());
Logging level configuration
Logging Cassandra Query CQL
Set log level of com.datastax.driver.core.RequestHandler = TRACE
Programmatic configuration of slf4j/logback
splunk - logging best practice
Use clear key-value pairs
To clear log without delete the file
cp /dev/null log
> log
Include as much dynamic info as possible
Paste logging in PR if applicable
Make sure there is enough logging to help trouble shooting issues in production later
sfl4j
log.warn("hello: {}, {}", "A", "B", new RuntimeException("wtf"));
- will print the exception's stack trace
org.slf4j.helpers.MessageFormatter.arrayFormat(String, Object[])Throwable throwableCandidate = getThrowableCandidate(argArray);
-Dlogback.debug=true
<configuration debug="true">
Log method and line number
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n
Pattern
Use %M to print method name in debug environment.
%class{1}
MDC - Mapped Diagnostic Context
%X{X-RequestId}, %X{sessionId}
MDC.put("X-RequestId", requestId)
-- Don't forget to MDC.clear() at the beginning and end of the request.
Use MDC in thread pools
@SuppressWarnings("serial")
public class MdcThreadPoolExecutor extends ThreadPoolTaskExecutor {
public MdcThreadPoolExecutor() {
super();
}
@Override
public void execute(final Runnable command) {
super.execute(wrap(command, MDC.getCopyOfContextMap()));
}
public static Runnable wrap(final Runnable runnable, final Map<String, String> context) {
return new Runnable() {
@Override
public void run() {
final Map<String, String> previous = MDC.getCopyOfContextMap();
if (context == null) {
MDC.clear();
} else {
MDC.setContextMap(context);
}
try {
runnable.run();
} finally {
if (previous == null) {
MDC.clear();
} else {
MDC.setContextMap(previous);
}
}
}
};
}
}
Duplicated log - fix: additivity="false"Only log stats into app-stats.log
- Don't log to app.log and stdout(in dev)
Async logging
<root level="INFO">
<appender-ref ref="dailyrolling" />
<appender-ref ref="STDOUT" />
</root>
<logger name="common.statistic" level="INFO" additivity="false">
<appender-ref ref="statsRolling" />
</logger>
<appender name="statsRolling-async" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>1000</queueSize>
<discardingThreshold>0</discardingThreshold>
<appender-ref ref="statsRolling" />
</appender>
<if condition='property("env").equals("local") || property("env").equals("docker")'>
<then>
</then>
<else>
<root level="WARN">
<appender-ref ref="dailyrolling-async" />
</root>
<logger name="com.xyz.services" level="INFO">
<appender-ref ref="dailyrolling-async" />
</logger>
<logger name="com.xyz.statistic" level="INFO">
<appender-ref ref="statsRolling-async" />
</logger>
</else>
</if>
Parameterized Logginglogger.error("xx {} yy {} xx {}", x, y, z);
SiftingAppender
Log4j
-Dlog4j.debug
Log4j2
https://logging.apache.org/log4j/2.0/faq.html#troubleshooting
-DLog4jDefaultStatusLevel=DEBUG
-Dorg.apache.logging.log4j.simplelog.StatusLogger.level=TRACE
Lazy Logging
logger.trace("Some long-running operation returned {}", () -> expensiveOperation());
Logging level configuration
Logging Cassandra Query CQL
Set log level of com.datastax.driver.core.RequestHandler = TRACE
Programmatic configuration of slf4j/logback
splunk - logging best practice
Use clear key-value pairs
To clear log without delete the file
cp /dev/null log
> log