Java日志
JDK日志
日志级别
级别 SEVERE WARNING INFO CONFIG FINE FINER FINEST 调用方法 severe() warning() info() config() fine() finer() finest() 含义 严重 警告 信息 配置 良好 较好 最好
示例
package cn. chenzhen ;
import java. io. IOException ;
import java. text. SimpleDateFormat ;
import java. util. Date ;
import java. util. logging. * ;
public class MainApplication {
private static final Logger logger = Logger . getLogger ( MainApplication . class . getName ( ) ) ;
static {
Logger parent = logger. getParent ( ) ;
Handler handler = parent. getHandlers ( ) [ 0 ] ;
Formatter formatter = new Formatter ( ) {
private final String dataPatter = "yyyy-MM-dd HH:mm:ss:SSS" ;
@Override
public String format ( LogRecord record ) {
SimpleDateFormat format = new SimpleDateFormat ( dataPatter) ;
return String . format ( "%s %-7s %s %s %s\n" ,
format. format ( new Date ( record . getMillis ( ) ) ) ,
record . getLevel ( ) . getName ( ) ,
record . getSourceClassName ( ) ,
record . getSourceMethodName ( ) ,
record . getMessage ( ) ) ;
}
} ;
handler. setFormatter ( formatter) ;
try {
new File ( "logs" ) . mkdirs ( ) ;
FileHandler fileHandler = new FileHandler ( "logs/log_%g.log" ) ;
fileHandler. setFormatter ( formatter) ;
parent. addHandler ( fileHandler) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public static void main ( String [ ] args) {
logger. finest ( "日志 finest" ) ;
logger. finer ( "日志 finer" ) ;
logger. fine ( "日志 fine" ) ;
logger. config ( "日志 config" ) ;
logger. info ( "日志 info" ) ;
logger. warning ( "日志 warning" ) ;
logger. severe ( "日志 severe" ) ;
}
}
Log4J 日志
依赖:
< dependency>
< groupId> log4j</ groupId>
< artifactId> log4j</ artifactId>
< version> 1.2.17</ version>
</ dependency>
Log4j有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局)。这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。
日志级别
从小到大 TRACE 《 FATAL
方法 级别 TRACE 查出 DEBUG 调试 INFO 信息 WARN 警告 ERROR 错误 FATAL 致命的
Appenders 日志处理器
类 作用 org.apache.log4j.ConsoleAppender 吧日志输出到 控制台 org.apache.log4j.FileAppender 吧日志输出到 文件 org.apache.log4j.DailyRollingFileAppender 每天产生一个日志文件 org.apache.log4j.RollingFileAppender 文件大小到达指定尺寸的时候产生一个新的文件 org.apache.log4j.WriterAppender 将日志信息以流格式发送到任意指定的地方
Layouts 日志输出格式处理器
类 作用 org.apache.log4j.HTMLLayout 输出日式 以HTML表格形式布局 org.apache.log4j.PatternLayout 可以灵活地指定布局模式 org.apache.log4j.SimpleLayout 输出日式 包含日志信息的级别和信息字符串 org.apache.log4j.TTCCLayout 输出日式 包含日志产生的时间、线程、类别等信息
日志格式
参数 说明 %c 日志消息所在类名 %c{2} 日志消息所在类名 设置输出最大层级数 %20c 若名字空间长度小于20,则左边用空格填充 %-20c 若名字空间长度小于20,则右边用空格填充 %.30c 若名字空间长度超过30,截去多余字符 %20.30c 若名字空间长度小于20,则左边用空格填充;若名字空间长度超过30,截去多余字符 %-20.30c 若名字空间长度小于20,则右边用空格填充;若名字空间长度超过30,截去多余字符 %C 列出调用logger的类的全名包含包路径 %C{1} 设置输出最大层级数 只输出类名 %d 显示日志记录时间,{<日期格式>} 自定义格式:%d{yyyy/MM/dd HH:mm:ss,SSS} %F 显示调用logger的源文件名 如:%F XXX.java %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数 %L 显示调用logger的代码行 %m 显示输出消息 %M 显示调用logger的方法名 %n 当前平台下的换行符 %n Windows平台下表示\r\n UNIX平台下表示\n %p 显示该条日志的优先级 %r 显示从程序启动时到记录该条日志时已经经过的毫秒数 %t 输出产生该日志事件的线程名 %x 按NDC(Nested Diagnostic Context,线程堆栈)顺序输出日志 %% 显示一个百分号 %%
输出日志到控制台
配置文件设置
文件名:log4j.properties
# 创建日志 多个使用 , 隔开 日志名自定义
# 第一个是日志级别
log4j.rootLogger=ALL,CONSOLE
# 输出日志到控制台
# 设置自定义日志 类
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
# 设置日志输出都哪里
log4j.appender.CONSOLE.Target=System.out
# 设置日志输出格式处理类
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
# 设置日志输出格式
log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] %d(%r) [%t] %l: %m %x %n
输出日志
import org. apache. log4j. Logger ;
public class MainLog4jApplication {
private static final Logger logger = Logger . getLogger ( MainLog4jApplication . class ) ;
public static void main ( String [ ] args) {
logger. debug ( "日志 debug" ) ;
logger. info ( "日志 info" ) ;
logger. warn ( "日志 warn" ) ;
logger. error ( "日志 error" ) ;
}
}
日志配置
配置 log4j.properties 文件
Logger 配置根
log4j.rootLogger = [ level ] , appenderName1, appenderName2, …
log4j.additivity.org.apache=false:表示Logger不会在父Logger的appender里输出,默认为true。
# level :设定日志记录的最低级别,可设的值有OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别,Log4j建议只使用中间四个级别。通过在这里设定级别,您可以控制应用程序中相应级别的日志信息的开关,比如在这里设定了INFO级别,则应用程序中所有DEBUG级别的日志信息将不会被打印出来。
# appenderName:就是指定日志信息要输出到哪里。可以同时指定多个输出目的地,用逗号隔开。
# 例如:log4j.rootLogger=INFO,A1,B2,C3
appender 配置日志信息输出目的地
语法:log4j.appender.appenderName = className
appenderName:自定义appderName,在log4j.rootLogger设置中使用;
className:可设值如下:
(1)org.apache.log4j.ConsoleAppender 控制台
(2)org.apache.log4j.FileAppender 文件
(3)org.apache.log4j.DailyRollingFileAppender 每天产生一个日志文件
(4)org.apache.log4j.RollingFileAppender 文件大小到达指定尺寸的时候产生一个新的文件)
(5)org.apache.log4j.WriterAppender 将日志信息以流格式发送到任意指定的地方
# ---------- 配置appender ----------
log4j.rootLogger=ALL,appenderName1,appenderName2,appenderName3,appenderName4,appenderName5
log4j.appender.appenderName1=org.apache.log4j.ConsoleAppender
log4j.appender.appenderName2=org.apache.log4j.FileAppender
log4j.appender.appenderName3=org.apache.log4j.DailyRollingFileAppender
log4j.appender.appenderName4=org.apache.log4j.RollingFileAppender
log4j.appender.appenderName5=org.apache.log4j.WriterAppender
ConsoleAppender 选项
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Target=System.err:默认值是System.out。
# --------------- 日志输出到控制台 配置 ---------------
log4j.rootLogger=ALL,CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=ALL
log4j.appender.CONSOLE.ImmediateFlush=true
log4j.appender.CONSOLE.Target=System.out
# 设置日志输出格式处理类
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
# 设置日志输出格式
log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] %d(%r) [%t] %.50l: %m %x %n
FileAppender选项
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true 表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。
# --------------- 日志保存到文件 配置 ---------------
log4j.rootLogger=ALL,FILE
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.Threshold=ALL
log4j.appender.FILE.ImmediateFlush=true
log4j.appender.FILE.Append=true
log4j.appender.FILE.File=./logs/data_log.log
# 设置日志输出格式处理类
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
# 设置日志输出格式
log4j.appender.FILE.layout.ConversionPattern=[%-5p] %d(%r) [%t] %.50l: %m %x %n
DailyRollingFileAppender选项
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=D:/logs/logging.log4j:指定当前消息输出到logging.log4j文件中。
DatePattern='.'yyyy-MM:每月滚动一次日志文件,即每月产生一个新的日志文件。当前月的日志文件名为logging.log4j,
另外,也可以指定按周、天、时、分等来滚动日志文件,对应的格式如下:
1)'.'yyyy-MM:每月
2)'.'yyyy-ww:每周
3)'.'yyyy-MM-dd:每天
4)'.'yyyy-MM-dd-a:每天两次
5)'.'yyyy-MM-dd-HH:每小时
6)'.'yyyy-MM-dd-HH-mm:每分钟
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true 表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。
# --------------- 日志保存到文件 根据日期动态滚动 配置 ---------------
log4j.rootLogger=ALL,DRFILE
log4j.appender.DRFILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DRFILE.Threshold=ALL
log4j.appender.DRFILE.ImmediateFlush=true
log4j.appender.DRFILE.Append=true
log4j.appender.DRFILE.File=./logs/data_log.log
log4j.appender.DRFILE.DatePattern='.'yyyyMMddHHmm
# 设置日志输出格式处理类
log4j.appender.DRFILE.layout=org.apache.log4j.PatternLayout
# 设置日志输出格式
log4j.appender.DRFILE.layout.ConversionPattern=[%-5p] %d(%r) [%t] %.50l: %m %x %n
RollingFileAppender选项
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。
MaxFileSize=100KB:后缀可以是KB, MB 或者GB。在日志文件到达该大小时,将会自动滚动,即将原来的内容移到logging.log4j.1文件中。
MaxBackupIndex=2:指定可以产生的滚动文件的最大数,例如,设为2则可以产生logging.log4j.1,logging.log4j.2两个滚动文件和一个logging.log4j文件。
# --------------- 日志保存到文件 根据文件大小动态滚动 配置 ---------------
log4j.rootLogger=ALL,RFILE
log4j.appender.RFILE=org.apache.log4j.RollingFileAppender
log4j.appender.RFILE.Threshold=ALL
log4j.appender.RFILE.ImmediateFlush=true
log4j.appender.RFILE.Append=true
log4j.appender.RFILE.File=./logs/data_log.log
log4j.appender.RFILE.MaxFileSize=10KB
log4j.appender.RFILE.MaxBackupIndex=100
# 设置日志输出格式处理类
log4j.appender.RFILE.layout=org.apache.log4j.PatternLayout
# 设置日志输出格式
log4j.appender.RFILE.layout.ConversionPattern=[%-5p] %d(%r) [%t] %.50l: %m %x %n
自定义 实现滚动文件夹
复制DailyRollingFileAppender类
dirPattern 文件夹滚动规则
log4j.rootLogger=ALL,MDRFILE
# --------------- 自定义日志保存到文件 文件夹和文件通过日期动态滚动 配置 ---------------
log4j.appender.MDRFILE=cn.chenzhen.logger.DirectoryAndDailyRollingFileAppender
log4j.appender.MDRFILE.Threshold=ALL
log4j.appender.MDRFILE.ImmediateFlush=true
log4j.appender.MDRFILE.Append=true
log4j.appender.MDRFILE.File=./logs/log.log
log4j.appender.MDRFILE.DatePattern=yyyyMMddHHmm
# 设置文件夹滚动规则
log4j.appender.MDRFILE.dirPattern=yyyyMMddHHmm
# 设置日志输出格式处理类
log4j.appender.MDRFILE.layout=org.apache.log4j.PatternLayout
# 设置日志输出格式
log4j.appender.MDRFILE.layout.ConversionPattern=[%-5p] %d(%r) [%t] %.50l: %m %x %n
package cn. chenzhen. logger ;
import java. io. IOException ;
import java. io. File ;
import java. io. InterruptedIOException ;
import java. text. SimpleDateFormat ;
import java. util. Date ;
import java. util. GregorianCalendar ;
import java. util. Calendar ;
import java. util. TimeZone ;
import java. util. Locale ;
import org. apache. log4j. FileAppender ;
import org. apache. log4j. Layout ;
import org. apache. log4j. helpers. LogLog ;
import org. apache. log4j. spi. LoggingEvent ;
public class DirectoryAndDailyRollingFileAppender extends FileAppender {
static final int TOP_OF_TROUBLE= - 1 ;
static final int TOP_OF_MINUTE = 0 ;
static final int TOP_OF_HOUR = 1 ;
static final int HALF_DAY = 2 ;
static final int TOP_OF_DAY = 3 ;
static final int TOP_OF_WEEK = 4 ;
static final int TOP_OF_MONTH = 5 ;
private String datePattern = "'.'yyyy-MM-dd" ;
private String dirPattern = "yyyyMMdd" ;
private String scheduledFilename;
private long nextCheck = System . currentTimeMillis ( ) - 1 ;
Date now = new Date ( ) ;
SimpleDateFormat sdf;
RollingCalendar rc = new RollingCalendar ( ) ;
int checkPeriod = TOP_OF_TROUBLE;
static final TimeZone gmtTimeZone = TimeZone . getTimeZone ( "GMT" ) ;
public DirectoryAndDailyRollingFileAppender ( ) {
}
public DirectoryAndDailyRollingFileAppender ( Layout layout, String filename,
String datePattern) throws IOException {
super ( layout, filename, true ) ;
this . datePattern = datePattern;
activateOptions ( ) ;
}
public void setDatePattern ( String pattern) {
datePattern = pattern;
}
public String getDatePattern ( ) {
return datePattern;
}
public void activateOptions ( ) {
super . activateOptions ( ) ;
if ( datePattern != null && fileName != null ) {
now. setTime ( System . currentTimeMillis ( ) ) ;
sdf = new SimpleDateFormat ( datePattern) ;
SimpleDateFormat psdf = new SimpleDateFormat ( dirPattern) ;
int type = computeCheckPeriod ( ) ;
printPeriodicity ( type) ;
rc. setType ( type) ;
File file = new File ( fileName) ;
scheduledFilename = file. getParentFile ( ) . getPath ( ) + "/" + psdf. format ( new Date ( file. lastModified ( ) ) ) + "/" + sdf. format ( new Date ( file. lastModified ( ) ) ) + file. getName ( ) ;
new File ( scheduledFilename) . getParentFile ( ) . mkdirs ( ) ;
System . out. println ( "得到新文件名:" + scheduledFilename) ;
} else {
LogLog . error ( "Either File or DatePattern options are not set for appender ["
+ name+ "]." ) ;
}
}
void printPeriodicity ( int type) {
switch ( type) {
case TOP_OF_MINUTE:
LogLog . debug ( "Appender [" + name+ "] to be rolled every minute." ) ;
break ;
case TOP_OF_HOUR:
LogLog . debug ( "Appender [" + name
+ "] to be rolled on top of every hour." ) ;
break ;
case HALF_DAY:
LogLog . debug ( "Appender [" + name
+ "] to be rolled at midday and midnight." ) ;
break ;
case TOP_OF_DAY:
LogLog . debug ( "Appender [" + name
+ "] to be rolled at midnight." ) ;
break ;
case TOP_OF_WEEK:
LogLog . debug ( "Appender [" + name
+ "] to be rolled at start of week." ) ;
break ;
case TOP_OF_MONTH:
LogLog . debug ( "Appender [" + name
+ "] to be rolled at start of every month." ) ;
break ;
default :
LogLog . warn ( "Unknown periodicity for appender [" + name+ "]." ) ;
}
}
int computeCheckPeriod ( ) {
RollingCalendar rollingCalendar = new RollingCalendar ( gmtTimeZone, Locale . getDefault ( ) ) ;
Date epoch = new Date ( 0 ) ;
if ( datePattern != null ) {
for ( int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++ ) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat ( datePattern) ;
simpleDateFormat. setTimeZone ( gmtTimeZone) ;
String r0 = simpleDateFormat. format ( epoch) ;
rollingCalendar. setType ( i) ;
Date next = new Date ( rollingCalendar. getNextCheckMillis ( epoch) ) ;
String r1 = simpleDateFormat. format ( next) ;
if ( r0 != null && r1 != null && ! r0. equals ( r1) ) {
return i;
}
}
}
return TOP_OF_TROUBLE;
}
void rollOver ( ) throws IOException {
if ( datePattern == null ) {
errorHandler. error ( "Missing DatePattern option in rollOver()." ) ;
return ;
}
String datedFilename = fileName+ sdf. format ( now) ;
if ( scheduledFilename. equals ( datedFilename) ) {
return ;
}
this . closeFile ( ) ;
File target = new File ( scheduledFilename) ;
if ( target. exists ( ) ) {
target. delete ( ) ;
}
File file = new File ( fileName) ;
boolean result = file. renameTo ( target) ;
if ( result) {
LogLog . debug ( fileName + " -> " + scheduledFilename) ;
} else {
LogLog . error ( "Failed to rename [" + fileName+ "] to [" + scheduledFilename+ "]." ) ;
}
try {
this . setFile ( fileName, true , this . bufferedIO, this . bufferSize) ;
}
catch ( IOException e) {
errorHandler. error ( "setFile(" + fileName+ ", true) call failed." ) ;
}
scheduledFilename = datedFilename;
}
protected void subAppend ( LoggingEvent event) {
long n = System . currentTimeMillis ( ) ;
if ( n >= nextCheck) {
now. setTime ( n) ;
nextCheck = rc. getNextCheckMillis ( now) ;
try {
rollOver ( ) ;
}
catch ( IOException ioe) {
if ( ioe instanceof InterruptedIOException ) {
Thread . currentThread ( ) . interrupt ( ) ;
}
LogLog . error ( "rollOver() failed." , ioe) ;
}
}
super . subAppend ( event) ;
}
public String getDirPattern ( ) {
return dirPattern;
}
public void setDirPattern ( String dirPattern) {
this . dirPattern = dirPattern;
}
}
class RollingCalendar extends GregorianCalendar {
private static final long serialVersionUID = - 3560331770601814177L ;
int type = DirectoryAndDailyRollingFileAppender . TOP_OF_TROUBLE;
RollingCalendar ( ) {
super ( ) ;
}
RollingCalendar ( TimeZone tz, Locale locale) {
super ( tz, locale) ;
}
void setType ( int type) {
this . type = type;
}
public long getNextCheckMillis ( Date now) {
return getNextCheckDate ( now) . getTime ( ) ;
}
public Date getNextCheckDate ( Date now) {
this . setTime ( now) ;
switch ( type) {
case DirectoryAndDailyRollingFileAppender . TOP_OF_MINUTE:
this . set ( Calendar . SECOND, 0 ) ;
this . set ( Calendar . MILLISECOND, 0 ) ;
this . add ( Calendar . MINUTE, 1 ) ;
break ;
case DirectoryAndDailyRollingFileAppender . TOP_OF_HOUR:
this . set ( Calendar . MINUTE, 0 ) ;
this . set ( Calendar . SECOND, 0 ) ;
this . set ( Calendar . MILLISECOND, 0 ) ;
this . add ( Calendar . HOUR_OF_DAY, 1 ) ;
break ;
case DirectoryAndDailyRollingFileAppender . HALF_DAY:
this . set ( Calendar . MINUTE, 0 ) ;
this . set ( Calendar . SECOND, 0 ) ;
this . set ( Calendar . MILLISECOND, 0 ) ;
int hour = get ( Calendar . HOUR_OF_DAY) ;
if ( hour < 12 ) {
this . set ( Calendar . HOUR_OF_DAY, 12 ) ;
} else {
this . set ( Calendar . HOUR_OF_DAY, 0 ) ;
this . add ( Calendar . DAY_OF_MONTH, 1 ) ;
}
break ;
case DirectoryAndDailyRollingFileAppender . TOP_OF_DAY:
this . set ( Calendar . HOUR_OF_DAY, 0 ) ;
this . set ( Calendar . MINUTE, 0 ) ;
this . set ( Calendar . SECOND, 0 ) ;
this . set ( Calendar . MILLISECOND, 0 ) ;
this . add ( Calendar . DATE, 1 ) ;
break ;
case DirectoryAndDailyRollingFileAppender . TOP_OF_WEEK:
this . set ( Calendar . DAY_OF_WEEK, getFirstDayOfWeek ( ) ) ;
this . set ( Calendar . HOUR_OF_DAY, 0 ) ;
this . set ( Calendar . MINUTE, 0 ) ;
this . set ( Calendar . SECOND, 0 ) ;
this . set ( Calendar . MILLISECOND, 0 ) ;
this . add ( Calendar . WEEK_OF_YEAR, 1 ) ;
break ;
case DirectoryAndDailyRollingFileAppender . TOP_OF_MONTH:
this . set ( Calendar . DATE, 1 ) ;
this . set ( Calendar . HOUR_OF_DAY, 0 ) ;
this . set ( Calendar . MINUTE, 0 ) ;
this . set ( Calendar . SECOND, 0 ) ;
this . set ( Calendar . MILLISECOND, 0 ) ;
this . add ( Calendar . MONTH, 1 ) ;
break ;
default :
throw new IllegalStateException ( "Unknown periodicity type." ) ;
}
return getTime ( ) ;
}
}
全面的配置
#Log4j配置文件实现了输出到控制台、文件、回滚文件、发送日志邮件、输出到数据库日志表、自定义标签等全套功能。
log4j.rootLogger=DEBUG,console,dailyFile,im,MDRFILE
log4j.additivity.org.apache=true
# 控制台(console)
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 日志文件(logFile)
log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=D:/logs/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 回滚文件(rollingFile)
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.Threshold=DEBUG
log4j.appender.rollingFile.ImmediateFlush=true
log4j.appender.rollingFile.Append=true
log4j.appender.rollingFile.File=D:/logs/log.log4j
log4j.appender.rollingFile.MaxFileSize=200KB
log4j.appender.rollingFile.MaxBackupIndex=50
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 定期回滚日志文件(dailyFile)
log4j.appender.dailyFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyFile.Threshold=DEBUG
log4j.appender.dailyFile.ImmediateFlush=true
log4j.appender.dailyFile.Append=true
log4j.appender.dailyFile.File=D:/logs/log.log4j
log4j.appender.dailyFile.DatePattern='.'yyyy-MM-dd
log4j.appender.dailyFile.layout=org.apache.log4j.PatternLayout
log4j.appender.dailyFile.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 应用于socket
log4j.appender.socket=org.apache.log4j.RollingFileAppender
log4j.appender.socket.RemoteHost=localhost
log4j.appender.socket.Port=5001
log4j.appender.socket.LocationInfo=true
# Set up for Log Factor 5
log4j.appender.socket.layout=org.apache.log4j.PatternLayout
log4j.appender.socket.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# Log Factor 5 Appender
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
# 发送日志到指定邮件
log4j.appender.mail=org.apache.log4j.net.SMTPAppender
log4j.appender.mail.Threshold=FATAL
log4j.appender.mail.BufferSize=10
log4j.appender.mail.From = xxx@mail.com
log4j.appender.mail.SMTPHost=mail.com
log4j.appender.mail.Subject=Log4J Message
log4j.appender.mail.To= xxx@mail.com
log4j.appender.mail.layout=org.apache.log4j.PatternLayout
log4j.appender.mail.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 应用于数据库
log4j.appender.database=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.database.URL=jdbc:mysql://localhost:3306/test
log4j.appender.database.driver=com.mysql.jdbc.Driver
log4j.appender.database.user=root
log4j.appender.database.password=
log4j.appender.database.sql=INSERT INTO LOG4J (Message) VALUES('=[%-5p] %d(%r) --> [%t] %l: %m %x %n')
log4j.appender.database.layout=org.apache.log4j.PatternLayout
log4j.appender.database.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# 自定义Appender
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = corlin@cybercorlin.net
log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
# --------------- 自定义日志保存到文件 文件夹和文件通过日期动态滚动 配置 ---------------
log4j.appender.MDRFILE=cn.chenzhen.logger.DirectoryAndDailyRollingFileAppender
log4j.appender.MDRFILE.Threshold=ALL
log4j.appender.MDRFILE.ImmediateFlush=true
log4j.appender.MDRFILE.Append=true
log4j.appender.MDRFILE.File=./logs/log.log
log4j.appender.MDRFILE.DatePattern=yyyyMMddHHmm
# 设置文件夹滚动规则
log4j.appender.MDRFILE.dirPattern=yyyyMMddHHmm
# 设置日志输出格式处理类
log4j.appender.MDRFILE.layout=org.apache.log4j.PatternLayout
# 设置日志输出格式
log4j.appender.MDRFILE.layout.ConversionPattern=[%-5p] %d(%r) [%t] %.50l: %m %x %n
给不同包路径配置不同日志
语法:log4j.logger.包[.类]= DEBUG, test
# --------------- 给不同包配置 或者 类 不同日志文件 ---------------
# 语法:log4j.logger.包=日志级别,日志处理器
# 语法:log4j.logger.包.类名=日志级别,日志处理器
log4j.logger.cn.chenzhen=ALL,CNLOGGER
log4j.appender.CNLOGGER=org.apache.log4j.FileAppender
log4j.appender.CNLOGGER.Threshold=ALL
log4j.appender.CNLOGGER.ImmediateFlush=true
log4j.appender.CNLOGGER.Append=true
log4j.appender.CNLOGGER.File=./logs/cn/data_log.log
# 设置日志输出格式处理类
log4j.appender.CNLOGGER.layout=org.apache.log4j.PatternLayout
# 设置日志输出格式
log4j.appender.CNLOGGER.layout.ConversionPattern=[%-5p] %d(%r) [%t] %.50l: %m %x %n
log4j2
导入依赖
< dependency>
< groupId> org.apache.logging.log4j</ groupId>
< artifactId> log4j-core</ artifactId>
< version> 2.17.2</ version>
</ dependency>
日志级别
日志级别 作用 trace 追踪,就是程序推进一下,可以写个trace输出 debug 调试,一般作为最低级别,trace基本不用 info 输出重要的信息,使用较多 warn 警告,有些信息不是错误信息,但也要给程序员一些提示 error 错误信息。用的也很多 fatal 致命错误。级别较高,这种级别不用调试了,重写吧……
日志处理器
类 作用 org.apache.logging.log4j.core.appender.ConsoleAppender 输出日志到控制台 org.apache.logging.log4j.core.appender.FileAppender 输出日志到文件 org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender 输出日志到数据库 org.apache.logging.log4j.core.appender.HttpAppender 输出日志到 HTTP请求 org.apache.logging.log4j.core.appender.RollingFileAppender 输出日志到文件 通过日期时间、大小动态滚动文件
日志输出格式处理器 日志布局
类 作用 org.apache.logging.log4j.core.layout.PatternLayout 自定义输出日志格式 org.apache.logging.log4j.core.layout.HtmlLayout 输出日志格式为HTML org.apache.logging.log4j.core.layout.JsonLayout 输出日志格式为JSON org.apache.logging.log4j.core.layout.XmlLayout 输出日志以为XML org.apache.logging.log4j.core.layout.YamlLayout 输出日志以为YAML
日志格式
参数 说明 %c{precision} = %logger{precision} 输出发布日志事件的日志程序的名称 %C{precision} = %class{precision} 输出发出日志记录请求的调用者的完全限定类名,可能会影响性能,谨慎使用 %d{pattern} = %date{pattern} 输出日志事件的日期。日期转换说明符后面可以跟一组大括号,其中包含每个SimpleDateFormat的日期和时间模式字符串 %enc{pattern}{[HTML|XML|JSON|CRLF]} = %encode{pattern}{[HTML|XML|JSON|CRLF]} 对适合用特定标记语言输出的特殊字符进行编码和转义。默认情况下如果只指定了一个选项,它将对HTML进行编码。第二个选项用于指定应该使用哪种编码格式。此转换器特别适用于对用户提供的数据进行编码,这样输出数据就不会写得不正确或不安全 %ex = %exception = %throwable 输出绑定到日志事件的可抛出跟踪,默认情况下,这将输出完整的跟踪,就像调用Throwable. printstacktrace()时通常会看到的那样 %F = %file 输出发出日志记录请求的文件名。生成文件信息(位置信息)是一项昂贵的操作,可能会影响性能,请谨慎使用 %highlight{pattern}{style} 根据当前事件的日志级别将ANSI颜色添加到所包含模式的结果中。(见Jansi配置。) %l = %location 输出生成日志事件的调用者的位置信息。位置信息取决于JVM实现,但通常由调用方法的完全限定名、调用者源文件名和括号之间的行号组成。生成位置信息是一项昂贵的操作,可能会影响性能,请谨慎使用 %L = %line 上面location功能的简略版,仅仅输出发出日志请求的行号。同样生成行号信息可能会影响性能,请谨慎使用 %m{nolookups}{ansi} = %msg{nolookups}{ansi} = %message{nolookups}{ansi} 输出应用程序提供的与日志事件关联的消息 %M = %method 输出发出日志请求的方法名。生成调用者的方法名(位置信息)是一项昂贵的操作,可能会影响性能,请谨慎使用 %maxLen = %maxLength 输出评估模式的结果并截断结果。如果长度大于20,则输出将包含一个拖尾省略号。如果提供的长度无效,则使用默认值100。示例语法:%maxLen{%p: %c{1} - %m%notEmpty{=>%ex{short}}}{160}将被限制为160个字符,后面加一个省略号。另一个例子:%maxLen{%m}{20}将被限制为20个字符,并且没有拖尾省略号 %n 输出平台相关的行分隔符字符。与使用不可移植的行分隔符字符串(如“\n”或“\r\n”)相比,这个转换字符提供了几乎相同的性能。因此,它是指定行分隔符的首选方法 %N = %nano 在创建日志事件时输出System.nanoTime()的结果 %pid{[defaultValue]} = %processId{[defaultValue]} 如果底层平台支持,则输出进程ID。如果平台不支持进程id,可以指定一个可选的默认值来显示 %p = %evel 输出日志事件的级别 %r = %relative 输出从JVM启动到日志事件创建的毫秒数 %replace{pattern}{regex}{substitution} 将正则表达式’regex’的出现替换为对模式求值后字符串中的’替换’。例如,“%replace{%msg}{\s}{}”将删除事件消息中包含的所有空格。模式可以任意复杂,特别是可以包含多个转换关键字。例如,“%替换{%logger %msg}{\。}{/}将用正斜杠替换日志记录器或事件消息中的所有点 %sn = %sequenceNumber 包含将在每个事件中递增的序列号。计数器是一个静态变量,因此它只在共享相同转换器类对象的应用程序中是唯一的 %T = %tid = %threadId 输出生成日志事件的线程ID %t = %tn = %thread = %threadName 输出生成日志事件的线程名称 %tp = %threadPriority 输出生成日志事件的线程的优先级 %fqcn 输出记录器的完全限定类名 %endOfBatch 输出日志事件的EndOfBatch状态,为“true”或“false” u{“RANDOM” |“TIME”} = uuid 包括一个随机的或基于时间的UUID。基于时间的UUID是一个1型UUID,可以产生高达每毫秒10000独特的id,将使用每个主机的MAC地址,并试图确保唯一性跨多个jvm和/或类加载器在同一个主机上0到16384之间的一个随机数将与每个UUID生成类的实例相关联,包括在每一个基于时间的UUID生成。因为基于时间的uuid包含MAC地址和时间戳,所以应该小心使用它们,因为它们可能会导致安全漏洞 %% 输出一个百分比符号
日志格式长度限制 截取
规则 值 实际输出值 %c{1} org.apache.commons.Foo Foo %c{2} org.apache.commons.Foo commons.Foo %c{10} org.apache.commons.Foo org.apache.commons.Foo %c{-1} org.apache.commons.Foo apache.commons.Foo %c{-2} org.apache.commons.Foo commons.Foo %c{-10} org.apache.commons.Foo org.apache.commons.Foo %c{1.} org.apache.commons.Foo o.a.c.Foo %c{1.1…} org.apache.commons.test.Foo o.a…Foo %c{.} org.apache.commons.test.Foo …Foo
日志长度占位符 填充空格
格式修饰符 对齐方式 最小宽度 最大宽度 说明 %20c 右对齐 20 无 不足20个字符则在数值前面用空格补足,超过20个字符则保留原信息。 %-20c 左对齐 20 无 同上。 %.30c NA 无 30 如果信息超过30个字符,则只保留最后30个字符。 %20.30c 右对齐 20 30 不足20个字符则在信息前面用空格补足,超过30个字符则只保留最后30个字符。 %-20.30c 左对齐 20 30 同上。 %-20.-30c 左对齐 20 30 不足20个字符则在信息前面用空格补足,超过30个字符则只保留前面30个字符。
日志过滤器
Accept 表示日志事件会被立即处理,不会调用其他 Filter; Deny 表示日志事件被立即忽略并不再经过其他过滤器; Neutral 表示日志事件将传递给其他 Filter,如果没有其他 Filter,则事件将会被处理。
参数 类型 描述 level String 匹配的可用的日志级别,可以为 OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE 、ALL 之一 onMatch String 当日志级别匹配时匹配时执行的过滤动作,可以为 ACCEPT(接受)、DENY(否认)、NEUTRAL(中立) 之一,默认为 NEUTRAL onMismatch String 当日志级别不匹配时执行的过滤动作,可以为ACCEPT(接受)、DENY(否认)、NEUTRAL(中立)之一,默认为 DENY
调用日志
import org. apache. logging. log4j. LogManager ;
import org. apache. logging. log4j. Logger ;
public class MainLog4j2Application {
private static final Logger logger = LogManager . getLogger ( MainLog4j2Application . class ) ;
public static void main ( String [ ] args) {
for ( int i = 0 ; i < 100 ; i++ ) {
logger. debug ( "日志 debug" + i) ;
logger. info ( "日志 info" + i) ;
logger. warn ( "日志 warn" + i) ;
logger. error ( "日志 error" + i) ;
}
}
}
输出日志到控制台
<?xml version="1.0" encoding="UTF-8" ?>
< Configuration status = " ALL" >
< Appenders>
< Console name = " Console" target = " SYSTEM_OUT" >
< ThresholdFilter level = " INFO" onMatch = " ACCEPT" onMismatch = " DENY" />
< PatternLayout pattern = " [%-5level] %d (%r) %t %l %m %n" > </ PatternLayout>
</ Console>
</ Appenders>
< Loggers>
< Root level = " ALL" >
< AppenderRef ref = " Console" additivity = " false" > </ AppenderRef>
</ Root>
</ Loggers>
</ Configuration>
输出日志到文件
<?xml version="1.0" encoding="UTF-8" ?>
< Configuration status = " ALL" >
< Appenders>
< File type = " File" name = " FILE" fileName = " logs/log.log" append = " true" >
< ThresholdFilter level = " INFO" onMatch = " ACCEPT" onMismatch = " DENY" />
< PatternLayout pattern = " [%-5level] %d (%r) %t %l %m %n" > </ PatternLayout>
</ File>
</ Appenders>
< Loggers>
< Root level = " ALL" >
< AppenderRef ref = " FILE" > </ AppenderRef>
</ Root>
</ Loggers>
</ Configuration>
日志滚动 根据时间、大小
<?xml version="1.0" encoding="UTF-8" ?>
< Configuration status = " ALL" >
< Appenders>
< RollingFile name = " ROLLINGFILE" fileName = " logs/log4j2/log.log"
filePattern = " logs/$${date:yyyyMMddHHmm}/%d{yyyyMMddHHmm}-%i.log"
>
< ThresholdFilter level = " INFO" onMatch = " ACCEPT" onMismatch = " DENY" />
< PatternLayout pattern = " [%-5level] %d (%r) %t %l %m %n" > </ PatternLayout>
< Policies>
< TimeBasedTriggeringPolicy modulate = " true"
interval = " 1" />
< SizeBasedTriggeringPolicy size = " 1KB" />
</ Policies>
< DefaultRolloverStrategy max = " 10" />
</ RollingFile>
</ Appenders>
< Loggers>
< Root level = " ALL" >
< AppenderRef ref = " ROLLINGFILE" > </ AppenderRef>
</ Root>
</ Loggers>
</ Configuration>
定期清理日志文件
<?xml version="1.0" encoding="UTF-8" ?>
< Configuration status = " ALL" >
< Appenders>
< RollingFile name = " ROLLINGFILE" fileName = " logs/log4j2/log.log"
filePattern = " logs/$${date:yyyyMMddHHmm}/%d{yyyyMMddHHmm}-%i.log"
>
< ThresholdFilter level = " INFO" onMatch = " ACCEPT" onMismatch = " DENY" />
< PatternLayout pattern = " [%-5level] %d (%r) %t %l %m %n" > </ PatternLayout>
< Policies>
< TimeBasedTriggeringPolicy modulate = " true"
interval = " 1" />
< SizeBasedTriggeringPolicy size = " 1KB" />
</ Policies>
< DefaultRolloverStrategy max = " 5" >
< Delete basePath = " logs/tmp/" maxDepth = " 5" >
< IfFileName glob = " tmp*.log" />
< IfLastModified age = " 30d" />
</ Delete>
</ DefaultRolloverStrategy>
</ RollingFile>
</ Appenders>
< Loggers>
< Root level = " ALL" >
< AppenderRef ref = " ROLLINGFILE" > </ AppenderRef>
</ Root>
</ Loggers>
</ Configuration>
Logback
导入依赖
< dependency>
< groupId> ch.qos.logback</ groupId>
< artifactId> logback-classic</ artifactId>
< version> 1.2.11</ version>
</ dependency>
日志级别
日志级别 作用 trace 追踪,就是程序推进一下,可以写个trace输出 debug 调试,一般作为最低级别,trace基本不用 info 输出重要的信息,使用较多 warn 警告,有些信息不是错误信息,但也要给程序员一些提示 error 错误信息。用的也很多
日志处理器
类 作用 ch.qos.logback.core.ConsoleAppender 输出日志到控制台 ch.qos.logback.core.FileAppender 输出日志到文件 ch.qos.logback.core.RollingFileAppender 输出日志到文件 动态滚动日志 支持时间、文件大小进行滚动
日志格式处理器
类 作用 ch.qos.logback.classic.PatternLayout 自定义输出日志格式 ch.qos.logback.classic.html.HTMLLayout 输出日志格式为HTML格式 ch.qos.logback.classic.log4j.XMLLayout 输出日志格式为xml格式
日志格式 占位符
占位符 作用 %c = %log = %logger 输出日志的logger名 %c = %class 输出执行记录请求的调用者的全限定名 %contextName = %cn 输出上下文名称 %d = %date 输出日志的打印日志 %F = %file 输出执行记录请求的java源文件名 %caller 输出生成日志的调用者的位置信息,整数选项表示输出信息深度 %L = %line 输出执行日志请求的行号 %m = %msg = %message 输出应用程序提供的信息 %M = %method 输出执行日志请求的方法名 %n 输出平台先关的分行符 %p = %le = %level 输出日志级别 %r = %relative 输出从程序启动到创建日志记录的时间,单位毫秒 %t = %thread 输出产生日志的线程名 %replace§{r,t} 替换内容 p 为日志内容,r 是正则表达式,将p 中符合r 的内容替换为t
日志输出包名长度限制 截取
符号 内容 实际输出内容 %logger mainPackage.sub.sample.Bar mainPackage.sub.sample.Bar %logger{0} mainPackage.sub.sample.Bar Bar %logger{5} mainPackage.sub.sample.Bar m.s.s.Bar %logger{10} mainPackage.sub.sample.Bar m.s.s.Bar %logger{15} mainPackage.sub.sample.Bar m.s.sample.Bar %logger{16} mainPackage.sub.sample.Bar m.sub.sample.Bar %logger{26} mainPackage.sub.sample.Bar mainPackage.sub.sample.Bar
日志长度内容限制、截取
符号 左对齐 最小字符 最大长度 描述 %20logger false 20 none 内容长度小于20个字符,在左侧填充空格。 %-20logger true 20 none 长度小于20个字符,在右键填充空格 %.30logger NA none 30 内容超过30个字符,则从开头(左边)截断。 %.-30logger NA none 30 如果记录器名称超过30个字符,则从结束(右边)处截断。 %20.30logger false 20 30 内容短于20个字符,则左空格为空格。但是,如果记录器名称超过30个字符,则从开头(左边)截断。 %-20.30logger true 20 30 内容少于20个字符,则右键填充空格。但是,如果记录器名称超过30个字符,则从开始(左边)截断
列子:
符号 内容 实际输出内容 %20.20logger main.Name main.Name %-20.20logger main.Name main.Name %10.10logger main.foo.foo.bar.Name o.bar.Name %10.-10logger main.foo.foo.bar.Name main.foo.f
输出日志到控制台
<?xml version="1.0" encoding="UTF-8" ?>
< configuration>
< property name = " pattern" value = " %d{yyyy-MM-dd:HH:mm:ss.SSS} %r [%thread] %-5level %c %M %L %msg%n" />
< appender name = " console" class = " ch.qos.logback.core.ConsoleAppender" >
< target> System.out</ target>
< encoder>
< pattern> ${pattern}</ pattern>
</ encoder>
</ appender>
< root level = " TRACE" >
< appender-ref ref = " console" />
</ root>
</ configuration>
输出日志到文件
<?xml version="1.0" encoding="UTF-8" ?>
< configuration>
< property name = " pattern" value = " %d{yyyy-MM-dd:HH:mm:ss.SSS} %r [%thread] %-5level %c %M %L %msg%n" />
< appender name = " console" class = " ch.qos.logback.core.ConsoleAppender" >
< target> System.out</ target>
< encoder>
< pattern> ${pattern}</ pattern>
</ encoder>
</ appender>
< appender name = " FILE" class = " ch.qos.logback.core.FileAppender" >
< encoder class = " ch.qos.logback.classic.encoder.PatternLayoutEncoder" >
< pattern> ${pattern}</ pattern>
</ encoder>
< file> logs/logback/test.log</ file>
</ appender>
< root level = " TRACE" >
< appender-ref ref = " console" />
< appender-ref ref = " FILE" />
</ root>
</ configuration>
日志滚动 根据时间、大小
<?xml version="1.0" encoding="UTF-8" ?>
< configuration>
< property name = " pattern" value = " %d{yyyy-MM-dd:HH:mm:ss.SSS} %r [%thread] %-5level %c %M %L %msg%n" />
< appender name = " console" class = " ch.qos.logback.core.ConsoleAppender" >
< target> System.out</ target>
< encoder>
< pattern> ${pattern}</ pattern>
</ encoder>
</ appender>
< appender name = " FILE" class = " ch.qos.logback.core.FileAppender" >
< encoder class = " ch.qos.logback.classic.encoder.PatternLayoutEncoder" >
< pattern> ${pattern}</ pattern>
</ encoder>
< file> logs/logback/test.log</ file>
</ appender>
< appender name = " RFILE" class = " ch.qos.logback.core.rolling.RollingFileAppender" >
< file> logs/RFILE.log</ file>
< rollingPolicy class = " ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >
< fileNamePattern> logs/logback/%d{yyyyMMddHHmm}/log_%d{yyyyMMddHHmm}_%i.log</ fileNamePattern>
< timeBasedFileNamingAndTriggeringPolicy class = " ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" >
< maxFileSize> 10KB</ maxFileSize>
</ timeBasedFileNamingAndTriggeringPolicy>
< maxHistory> 5</ maxHistory>
</ rollingPolicy>
< encoder class = " ch.qos.logback.classic.encoder.PatternLayoutEncoder" >
< pattern> ${pattern}</ pattern>
</ encoder>
< filter class = " ch.qos.logback.classic.filter.LevelFilter" >
< level> INFO</ level>
< onMatch> ACCEPT</ onMatch>
< onMismatch> DENY</ onMismatch>
</ filter>
</ appender>
< root level = " TRACE" >
< appender-ref ref = " console" />
< appender-ref ref = " FILE" />
< appender-ref ref = " RFILE" />
</ root>
</ configuration>
根据时间+大小滚动
<?xml version="1.0" encoding="UTF-8" ?>
< configuration>
< property name = " pattern" value = " %d{yyyy-MM-dd:HH:mm:ss.SSS} %r [%thread] %-5level %c %M %L %msg%n" />
< appender name = " console" class = " ch.qos.logback.core.ConsoleAppender" >
< target> System.out</ target>
< encoder>
< pattern> ${pattern}</ pattern>
</ encoder>
</ appender>
< appender name = " FILE" class = " ch.qos.logback.core.FileAppender" >
< encoder class = " ch.qos.logback.classic.encoder.PatternLayoutEncoder" >
< pattern> ${pattern}</ pattern>
</ encoder>
< file> logs/logback/test.log</ file>
</ appender>
< appender name = " RFILE2" class = " ch.qos.logback.core.rolling.RollingFileAppender" >
< file> logs/RFILE2.log</ file>
< rollingPolicy class = " ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy" >
< fileNamePattern> logs/logback/%d{yyyyMMddHHmm}/log_%d{yyyyMMddHHmm}_%i.log</ fileNamePattern>
< maxFileSize> 10KB</ maxFileSize>
< maxHistory> 5</ maxHistory>
</ rollingPolicy>
< encoder class = " ch.qos.logback.classic.encoder.PatternLayoutEncoder" >
< pattern> ${pattern}</ pattern>
</ encoder>
< filter class = " ch.qos.logback.classic.filter.LevelFilter" >
< level> INFO</ level>
< onMatch> ACCEPT</ onMatch>
< onMismatch> DENY</ onMismatch>
</ filter>
</ appender>
< root level = " TRACE" >
< appender-ref ref = " console" />
< appender-ref ref = " FILE" />
< appender-ref ref = " RFILE2" />
</ root>
</ configuration>
完整配置
<?xml version="1.0" encoding="UTF-8" ?>
< configuration>
< property name = " pattern" value = " %d{yyyy-MM-dd:HH:mm:ss.SSS} %r [%thread] %-5level %c %M %L %msg%n" />
< appender name = " console" class = " ch.qos.logback.core.ConsoleAppender" >
< target> System.out</ target>
< encoder>
< pattern> ${pattern}</ pattern>
</ encoder>
</ appender>
< appender name = " FILE" class = " ch.qos.logback.core.FileAppender" >
< encoder class = " ch.qos.logback.classic.encoder.PatternLayoutEncoder" >
< pattern> ${pattern}</ pattern>
</ encoder>
< file> logs/logback/test.log</ file>
</ appender>
< appender name = " RFILE" class = " ch.qos.logback.core.rolling.RollingFileAppender" >
< file> logs/RFILE2.log</ file>
< rollingPolicy class = " ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy" >
< fileNamePattern> logs/logback/%d{yyyyMMddHHmm}/log_%d{yyyyMMddHHmm}_%i.log</ fileNamePattern>
< maxFileSize> 10KB</ maxFileSize>
</ rollingPolicy>
< encoder class = " ch.qos.logback.classic.encoder.PatternLayoutEncoder" >
< pattern> ${pattern}</ pattern>
</ encoder>
< filter class = " ch.qos.logback.classic.filter.LevelFilter" >
< level> INFO</ level>
< onMatch> ACCEPT</ onMatch>
< onMismatch> DENY</ onMismatch>
</ filter>
</ appender>
< root level = " TRACE" >
< appender-ref ref = " console" />
< appender-ref ref = " FILE" />
< appender-ref ref = " RFILE" />
</ root>
</ configuration>
日志门面
作用:所有的Java日志实现提供一个统一的接口,使项目与日志实现工具解耦
common-logging
依赖
< dependency>
< groupId> commons-logging</ groupId>
< artifactId> commons-logging</ artifactId>
< version> 1.2</ version>
</ dependency>
< dependency>
< groupId> log4j</ groupId>
< artifactId> log4j</ artifactId>
< version> 1.2.17</ version>
</ dependency>
< dependency>
< groupId> org.apache.logging.log4j</ groupId>
< artifactId> log4j-jcl</ artifactId>
< version> 2.17.2</ version>
</ dependency>
< dependency>
< groupId> org.apache.logging.log4j</ groupId>
< artifactId> log4j-core</ artifactId>
< version> 2.17.2</ version>
</ dependency>
配置文件
创建文件:commons-logging.properties
# 使用commons-logging的SimpleLog
# org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
# 选择使用 log4j 或者 log4j2
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
# 选择jdk的 logger
#org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger
调用日志门面
package cn. chenzhen. logging ;
import org. apache. commons. logging. Log ;
import org. apache. commons. logging. LogFactory ;
public class MainLoggngApplication {
private static final Log logger = LogFactory . getLog ( MainLoggngApplication . class ) ;
public static void main ( String [ ] args) {
for ( int i = 0 ; i < 1000 ; i++ ) {
logger. trace ( "输出日志: trace " + i) ;
logger. debug ( "输出日志: debug " + i) ;
logger. info ( "输出日志: info " + i) ;
logger. warn ( "输出日志: warn " + i) ;
logger. error ( "输出日志: error " + i) ;
}
}
}
日志实现类查找原理
在classpath下寻找自己的配置文件commons-logging.properties 如果找到,则使用其中定义的Log实现类 org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog; //使用commons-logging的SimpleLog org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger;//选择使用 log4j org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger; //选择jdk的 logger 找不到commons-logging.properties文件,则在查找是否已定义系统环境变量 org.apache.commons.logging.Log,找到则使用其定义的Log实现类 查看classpath中是否有Log4j的包,如果发现,则自动使用Log4j作为日志实现类。 使用JDK自身的日志实现类(JDK1.4以后才有日志实现类) 如果都没命中使用commons-logging自己提供的一个简单的日志实现类SimpleLog
SLF4J
依赖
< dependency>
< groupId> org.slf4j</ groupId>
< artifactId> slf4j-api</ artifactId>
< version> 1.7.36</ version>
</ dependency>
日志转换 依赖
slf4j-api.jar slf4j 的api接口jar包
slf4j-ext.jar 扩展功能
吧日志转换到slf4j
jcl-over-slf4j.jar 将Jakarta Commons Logging(commons-logging)日志框架到 slf4j 的桥接
jul-to-slf4j.jar 将java.util.logging的日志桥接到 slf4j
log4j-over-slf4j.jar 将log4j 的日志,桥接到slf4j
log4j-to-slf4j.jar 将log4j2 的日志 桥接到slf4j log4j2官方提供的jar
osgi-over-slf4j.jar 将osgi环境下的日志,桥接到slf4j
slf4j-android.jar 将android环境下的日志,桥接到slf4j
slf4j吧日志输出到指定日志
slf4j-jcl.jar slf4j 转接到 Jakarta Commons Logging日志输出框架
slf4j-jdk14.jar slf4j 转接到 java.util.logging,所以这个包不能和jul-to-slf4j.jar同时用,否则会死循环!!
slf4j-log4j12.jar slf4j 转接到 log4j,所以这个包不能和log4j-over-slf4j.jar同时用,否则会死循环!!
slf4j-migrator.jar 一个GUI工具,支持将项目代码中 JCL,log4j,java.util.logging的日志API转换为slf4j的写法
slf4j-nop.jar slf4j的空接口输出绑定,丢弃所有日志输出
slf4j-simple.jar slf4j的自带的简单日志输出接口
log4j-slf4j-impl 输出到log4j2 有apache提供
日志框架替换
jcl 替换
< dependency>
< groupId> org.slf4j</ groupId>
< artifactId> jcl-over-slf4j</ artifactId>
< version> 1.7.36</ version>
</ dependency>
log4j2 替换
< dependency>
< groupId> org.apache.logging.log4j</ groupId>
< artifactId> log4j-to-slf4j</ artifactId>
< version> 2.17.2</ version>
</ dependency>
log4j替换
< dependency>
< groupId> org.slf4j</ groupId>
< artifactId> log4j-over-slf4j</ artifactId>
< version> 1.7.36</ version>
</ dependency>
日志实现
吧日志输出到 jcl
< dependency>
< groupId> org.slf4j</ groupId>
< artifactId> slf4j-jcl</ artifactId>
< version> 1.7.36</ version>
</ dependency>
< dependency>
< groupId> commons-logging</ groupId>
< artifactId> commons-logging</ artifactId>
< version> 1.2</ version>
</ dependency>
吧日志输出到 JDK日志
< dependency>
< groupId> org.slf4j</ groupId>
< artifactId> slf4j-jdk14</ artifactId>
< version> 1.7.36</ version>
</ dependency>
吧日志输出到log4j
< dependency>
< groupId> org.slf4j</ groupId>
< artifactId> slf4j-log4j12</ artifactId>
< version> 1.7.36</ version>
< type> pom</ type>
</ dependency>
< dependency>
< groupId> log4j</ groupId>
< artifactId> log4j</ artifactId>
< version> 1.2.17</ version>
</ dependency>
吧日志输出到 log4j2
< dependency>
< groupId> org.apache.logging.log4j</ groupId>
< artifactId> log4j-slf4j-impl</ artifactId>
< version> 2.17.2</ version>
</ dependency>
< dependency>
< groupId> org.apache.logging.log4j</ groupId>
< artifactId> log4j-core</ artifactId>
< version> 2.17.2</ version>
</ dependency>
吧日志输出到 logback
< dependency>
< groupId> ch.qos.logback</ groupId>
< artifactId> logback-classic</ artifactId>
< version> 1.2.11</ version>
</ dependency>