web项目日志记录方案

一、概述

 

1、采用slf4j作为日志API,采用logback作为日志输出工具,用slf4j桥接方式替换掉log4j和commons-logging。

2、采用trace(追踪)、debug(调试)、info(信息)、warn(警告)、error(错误)、fatal(致命)共6种日志级别。

3、采用dev(开发环境)、test(测试环境)、production(生产环境)等不同的日志配置,根据环境变量自动识别。

4、特殊的记录,需要大批量写入日志文件,应该采用异步线程写文件。

 

二、日志级别定义

    采用trace(追踪)、debug(调试)、info(信息)、warn(警告)、error(错误)、fatal(致命)共6种日志级别。

    log4j建议使用4种级别 :优先级 从高到低分别是 ERROR、WARN、INFO、DEBUG;如果添加了日志开关,那么会优先展示优先级别高的;

    如 : 在这里定义了INFO级别, 则应用程序中所有DEBUG级别的日志信息将不被打印出来。

 

日志级别使用原则:

1、fatal(致命错误)使用原则

fatal为系统级别的异常,发生fatal错误,代表服务器整个或者核心功能已经无法工作了!!

1)在服务器启动时就应该检查,如果存在致命错误,直接抛异常,让服务器不要启动起来(启动了也无法正常工作,不如不启动)。

2)如果在服务器启动之后,发生了致命的错误,则记录fatal级别的错误日志,最好是同时触发相关的修复和告警工作(比如,给开发和维护人员发送告警邮件)。

 

2、error(错误)使用原则

error为功能或者逻辑级别的严重异常,发生error级别的异常,代表功能或者重要逻辑遇到问题、无法正常工作。

 

3、warn(警告)使用原则

warn用在某些逻辑非常规,发生了一些小故障但是没有大的影响,或者重要数据被修改,或者某些操作需要引起重视。

 

4、info(信息)使用原则

info用于记录一些有用的、关键的信息,一般这些信息出现得不频繁,只是在初始化的地方或者重要操作的地方才记录。

 

5、debug(调试)使用原则

debug用于记录一些调试信息,为了方便查看程序的执行过程和相关数据、了解程序的动态。

 

6、trace(跟踪)使用原则

trace用于记录一些更详细的调试信息,这些信息无需每次调试时都打印出来,只在需要更详细的调试信息时才开启。

 

7、项目稳定运行时的日志量

1)正常情况下,trace日志至少是debug日志的100倍,

trace级别的日志量 : debug级别的日志量  >  100 : 1,

也就是说trace日志非常多,debug日志相对较少。

 

2)debug级别的日志量 : info级别的日志量 > 1000 : 1,

也就是说正常情况下,info日志很少,只在部分重要位置会输出 info日志。

 

3)error日志和warn日志,正常情况下,几乎为0,当出现异常时,error日志和warn日志量 也在可控范围,不会超过debug级别的最大日志量。

 

三、日志输出(Appender)分类

 

分为5个一般类: 

    FILE_EXCEPTION (异常日志,包括ERROR和WARN)

    FILE_APP (应用日志,包括当前应用package下面的日志和DEBUG级别以上的其他日志)

    FILE_INFO (普通信息日志)

    FILE_DEBUG (调试日志)

    FILE_TRACE(追踪日志)

    SYSOUT(控制台输出,可以包括以上所有日志)

扩展类: 包括异步输出的日志,或者特殊业务日志。

 

举例说明:

假如 

当前应用的 Main Package 为 cn.zollty.lightning

ROOT_LEVEL为 trace,应用日志 LEVEL 为 debug

有以下日志打印:

1
2
3
4
5
6
7
8
9
10
11
12
13
Logger loggerA = LoggerFactory.getLogger(cn.zollty.lightning.Tests. class );
loggerA.trace( "--------" );
loggerA.debug( "--------" );
loggerA.info( "--------" );
loggerA.warn( "--------" );
loggerA.error( "--------" );
 
Logger loggerB = LoggerFactory.getLogger(org.apache.kafka.Consumer. class );
loggerB.trace( "--------" );
loggerB.debug( "--------" );
loggerB.info( "--------" );
loggerB.warn( "--------" );
loggerB.error( "--------" );

那么,异常日志(FILE_EXCEPTION)输出的为:

loggerA.warn("--------");

loggerA.error("--------");

loggerB.warn("--------");

loggerB.error("--------");

控制台(SYSOUT)输出日志的为;

loggerA.debug("--------");

loggerA.info("--------");

loggerA.warn("--------");

loggerA.error("--------");

loggerB.trace("--------");

loggerB.debug("--------");

loggerB.info("--------");

loggerB.warn("--------");

loggerB.error("--------");

应用日志(FILE_APP)输出的为:

loggerA.debug("--------");

loggerA.info("--------");

loggerA.warn("--------");

loggerA.error("--------");

loggerB.info("--------");

loggerB.warn("--------");

loggerB.error("--------");

 

2、历史日志文件

异常日志(error和warn)最多保存 9000 M(生产,测试)

app日志最多保存 9000 M (生产,测试)

trace日志最多保存 1000 M (仅供测试用,一般不用)

debug、info日志最多保存 5000 M(一般不用,用app日志就够了)

 

四、各环境默认日志定义

 

开发环境

1)默认日志级别定义为:

    app包为TRACE级别。日志的ROOT Level为DEBUG级别。

2)

启用 System.out 控制台输出日志;

启用error.log为错误和警告日志、app.log为应用日志(包括app包下的日志和其他INFO级别以上的日志)。

 

测试环境

1)默认日志级别定义为:

    app包为DEBUG级别。日志的ROOT Level为DEBUG级别。

2)

禁用 System.out 控制台输出日志;

启用error.log为错误和警告日志、app.log为应用日志(包括app包下的日志和其他INFO级别以上的日志)。

 

生产环境

1)默认日志级别定义为:

    app包为DEBUG级别。日志的ROOT Level为INFO级别。

2)

禁用 System.out 控制台输出日志;

启用error.log为错误和警告日志、app.log为应用日志(包括app包下的日志和其他INFO级别以上的日志)。

 

五、根据环境自动选择日志配置(借助Logback)

 

关键点1:使用logback的环境变量定义和读取功能

例如下面的各种环境变量定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 部署的环境类型:dev、test、product -->
< property  name = "DEPLOY_ENV"  value = "${deploy.env:-dev}"  />
 
<!-- 日志路径,这里是相对路径,web项目eclipse下会输出到当前目录./logs/下,如果部署到linux上的tomcat下,会输出到tomcat/logs/目录 下 -->
< property  name = "LOG_HOME"  value = "${catalina.base:-.}/logs"  />
 
<!-- 日志文件大小,超过这个大小将被压缩 -->
< property  name = "LOG_MAX_SIZE"  value = "100MB"  />
<!-- 日志输出格式 -->
< property  name = "LOG_COMMON_PATTERN"  value = "%d{HH:mm:ss.SSS} [%thread] [%level] %logger - %msg%n"  />
< property  name = "LOG_DEV_PATTERN"  value = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{48}:%line - %msg%n"  />
 
<!-- 主日志级别 -->
< property  name = "ROOT_LEVEL"  value = "${log.root.level:-DEBUG}"  />
 
<!-- APP 日志级别 -->
< property  name = "APP_LEVEL"  value = "${log.app.level:-TRACE}"  />
<!-- APP Package 前缀: cn.zollty.lightning -->
< property  name = "APP_PACKAGE"  value = "cn.zollty.lightning"  />

其中 ${deploy.env:-dev} 代表的意思是,如果环境变量中没有 deploy.env,则使用默认值dev。

 

一个小技巧:可以自定义类似下面这个类,在logback初始化之前,先设置变量的值:

1
< statusListener  class = "cn.zollty.commons.logbackext.InitConfigOnConsoleStatusListener"  />

这个类继承自ch.qos.logback.core.status.OnConsoleStatusListener。

 

关键点2:使用logback的 if-then 条件语法

1
2
3
4
5
6
7
8
9
10
11
12
< root  level = "${ROOT_LEVEL}" >
   <!-- Required: exception log -->
   < appender-ref  ref = "FILE_EXCEPTION" />
   <!-- Required: app log  -->
   < appender-ref  ref = "FILE_APP" />
 
   < if  condition = 'p("DEPLOY_ENV").contains("dev")' >
     < then >
     < appender-ref  ref = "STDOUT"  />
     </ then >
   </ if >
</ root >

 

参考配置:

logback.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<? xml  version = "1.0"  encoding = "UTF-8" ?>
< configuration  scan = "true"  scanPeriod = "60 seconds"  debug = "false" >
 
   < statusListener  class = "cn.zollty.commons.logbackext.InitConfigOnConsoleStatusListener"  />
 
   <!-- 部署的环境类型:dev、test、product -->
   < property  name = "DEPLOY_ENV"  value = "${deploy.env:-dev}"  />
 
   <!-- 日志路径,这里是相对路径,web项目eclipse下会输出到当前目录./logs/下,如果部署到linux上的tomcat下,会输出到tomcat/logs/目录 下 -->
   < property  name = "LOG_HOME"  value = "${catalina.base:-.}/logs"  />
   
   <!-- 日志文件大小,超过这个大小将被压缩 -->
   < property  name = "LOG_MAX_SIZE"  value = "100MB"  />
   <!-- 日志输出格式 -->
   < property  name = "LOG_COMMON_PATTERN"  value = "%d{HH:mm:ss.SSS} [%thread] [%level] %logger - %msg%n"  />
   < property  name = "LOG_DEV_PATTERN"  value = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{48}:%line - %msg%n"  />
 
   <!-- 主日志级别 -->
   < property  name = "ROOT_LEVEL"  value = "${log.root.level:-DEBUG}"  />
 
   <!-- APP 日志级别 -->
   < property  name = "APP_LEVEL"  value = "${log.app.level:-TRACE}"  />
   <!-- APP Package 前缀: cn.cstonline.zollty -->
   < property  name = "APP_PACKAGE"  value = "cn.zollty.lightning"  />
   
   < include  resource = "includedConfig.xml" />
   
   < appender  name = "STDOUT"  class = "ch.qos.logback.core.ConsoleAppender" >
     < encoder >
       < pattern >${LOG_DEV_PATTERN}</ pattern >
     </ encoder >
   </ appender >
   
   < appender  name = "FILTER-DATA"  class = "ch.qos.logback.core.rolling.RollingFileAppender" >
     < file >${LOG_HOME}/filter.log</ file >
     < rollingPolicy  class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >
       < fileNamePattern >${LOG_HOME}/filter/filter-%d{yyyy-MM-dd}-%i.log.zip</ fileNamePattern >
       < maxHistory >90</ maxHistory >
       < TimeBasedFileNamingAndTriggeringPolicy  class = "ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" >
         < MaxFileSize >100MB</ MaxFileSize >
       </ TimeBasedFileNamingAndTriggeringPolicy >
     </ rollingPolicy >
     < encoder >
       < pattern >${LOG_COMMON_PATTERN}</ pattern >
     </ encoder >
   </ appender >
   
   < appender  name = "ASYNC1"  class = "ch.qos.logback.classic.AsyncAppender" >
     < appender-ref  ref = "FILTER-DATA"  />
   </ appender >
   
   < include  resource = "special_log_level.xml" />
 
   < logger  name = "${APP_PACKAGE}"  level = "${APP_LEVEL}"  />
   
   < logger  name = "FILTER-LOGGER"  level = "${APP_LEVEL}"  additivity = "false" >
     < appender-ref  ref = "ASYNC1"  />
   </ logger >
 
   < root  level = "${ROOT_LEVEL}" >
     <!-- Required: exception log -->
     < appender-ref  ref = "FILE_EXCEPTION" />
     <!-- Required: app log  -->
     < appender-ref  ref = "FILE_APP" />
     
     <!-- Optional: show all debug or trace info -->
     <!-- <appender-ref ref="FILE_DEBUG"/> -->
     <!-- <appender-ref ref="FILE_TRACE"/> -->
     
     < if  condition = 'p("DEPLOY_ENV").contains("dev")' >
       < then >
         < appender-ref  ref = "STDOUT"  />
       </ then >
     </ if >
     
   </ root >
 
</ configuration >

includedConfig.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<? xml  version = "1.0"  encoding = "UTF-8"  ?>
 
< included >
 
   <!-- WARN and ERROR -->
   < appender  name = "FILE_EXCEPTION"  class = "ch.qos.logback.core.rolling.RollingFileAppender" >
     < filter  class = "ch.qos.logback.classic.filter.ThresholdFilter" >
       < level >WARN</ level >
     </ filter >
     < file >${LOG_HOME}/error.log</ file >
     < rollingPolicy  class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >
       <!-- rollover daily -->
       < fileNamePattern >${LOG_HOME}/error/error-%d{yyyy-MM-dd}-%i.log.zip</ fileNamePattern >
       < maxHistory >90</ maxHistory >
       < TimeBasedFileNamingAndTriggeringPolicy  class = "ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" >
         <!-- or whenever the file size reaches 100MB -->
         < MaxFileSize >${LOG_MAX_SIZE}</ MaxFileSize >
       </ TimeBasedFileNamingAndTriggeringPolicy >
     </ rollingPolicy >
     < encoder >
       < pattern >${LOG_COMMON_PATTERN}</ pattern >
     </ encoder >
   </ appender >
 
   <!-- INFO or Greater -->
   < appender  name = "FILE_INFO"  class = "ch.qos.logback.core.rolling.RollingFileAppender" >
     < filter  class = "ch.qos.logback.classic.filter.ThresholdFilter" >
       < level >INFO</ level >
     </ filter >
     < file >${LOG_HOME}/info.log</ file >
     < rollingPolicy  class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >
       < fileNamePattern >${LOG_HOME}/info/info-%d{yyyy-MM-dd}-%i.log.zip</ fileNamePattern >
       < maxHistory >50</ maxHistory >
       < TimeBasedFileNamingAndTriggeringPolicy  class = "ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" >
         < MaxFileSize >${LOG_MAX_SIZE}</ MaxFileSize >
       </ TimeBasedFileNamingAndTriggeringPolicy >
     </ rollingPolicy >
     < encoder >
       < pattern >${LOG_COMMON_PATTERN}</ pattern >
     </ encoder >
   </ appender >
 
   <!-- DEBUG or Greater-->
   < appender  name = "FILE_DEBUG"  class = "ch.qos.logback.core.rolling.RollingFileAppender" >
     < filter  class = "ch.qos.logback.classic.filter.ThresholdFilter" >
       < level >DEBUG</ level >
     </ filter >
     < file >${LOG_HOME}/debug.log</ file >
     < rollingPolicy  class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >
       < fileNamePattern >${LOG_HOME}/debug/debug-%d{yyyy-MM-dd}-%i.log.zip</ fileNamePattern >
       < maxHistory >50</ maxHistory >
       < TimeBasedFileNamingAndTriggeringPolicy  class = "ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" >
         < MaxFileSize >${LOG_MAX_SIZE}</ MaxFileSize >
       </ TimeBasedFileNamingAndTriggeringPolicy >
     </ rollingPolicy >
     < encoder >
       < pattern >${LOG_COMMON_PATTERN}</ pattern >
     </ encoder >
   </ appender >
 
   <!-- TRACE and ALL -->
   < appender  name = "FILE_TRACE"  class = "ch.qos.logback.core.rolling.RollingFileAppender" >
     < file >${LOG_HOME}/trace.log</ file >
     < rollingPolicy  class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >
       < fileNamePattern >${LOG_HOME}/trace/trace-%d{yyyy-MM-dd}-%i.log.zip</ fileNamePattern >
       < maxHistory >10</ maxHistory >
       < TimeBasedFileNamingAndTriggeringPolicy  class = "ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" >
         < MaxFileSize >${LOG_MAX_SIZE}</ MaxFileSize >
       </ TimeBasedFileNamingAndTriggeringPolicy >
     </ rollingPolicy >
     < encoder >
       < pattern >${LOG_COMMON_PATTERN}</ pattern >
     </ encoder >
   </ appender >
   
   <!-- (INFO or Greater) or logname prefix = ${APP_PACKAGE} -->
   < appender  name = "FILE_APP"  class = "ch.qos.logback.core.rolling.RollingFileAppender" >
     < filter  class = "cn.zollty.lightning.common.PackageOrThresholdFilter" >
       < level >INFO</ level >
       < prefix >${APP_PACKAGE}</ prefix >
     </ filter >
     < file >${LOG_HOME}/app.log</ file >
     < rollingPolicy  class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >
       < fileNamePattern >${LOG_HOME}/app/app-%d{yyyy-MM-dd}-%i.log.zip</ fileNamePattern >
       < maxHistory >90</ maxHistory >
       < TimeBasedFileNamingAndTriggeringPolicy  class = "ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" >
         < MaxFileSize >${LOG_MAX_SIZE}</ MaxFileSize >
       </ TimeBasedFileNamingAndTriggeringPolicy >
     </ rollingPolicy >
     < encoder >
       < pattern >${LOG_COMMON_PATTERN}</ pattern >
     </ encoder >
   </ appender >
 
</ included >

special_log_level.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<? xml  version = "1.0"  encoding = "UTF-8"  ?>
< included >
 
   < logger  name = "org.apache.zookeeper.ClientCnxn"  level = "ERROR"  />
   < logger  name = "org.apache.kafka.clients.consumer.internals.ConsumerCoordinator"  level = "INFO"  />
   < logger  name = "kafka.producer.BrokerPartitionInfo"  level = "INFO"  />
   < logger  name = "kafka.producer.async.ProducerSendThread"  level = "INFO"  />
   < logger  name = "kafka.producer.async.DefaultEventHandler"  level = "INFO"  />
   < logger  name = "org.apache.kafka.common.metrics.Metrics"  level = "INFO"  />
   < logger  name = "org.apache.kafka.clients.Metadata"  level = "INFO"  />
   
   < logger  name = "org.apache.kafka.clients.consumer.internals.AbstractCoordinator"  level = "INFO"  />
   < logger  name = "org.apache.kafka.clients.consumer.internals.Fetcher"  level = "INFO"  />
   < logger  name = "org.apache.kafka.clients.NetworkClient"  level = "INFO"  />
   
</ included >

 

也可以把变量定义到properties文件中,本地就放在 

src/resources/conf/logback_val.properties

服务器上放在

${catalina.base}/conf/logback_val.properties

配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<? xml  version = "1.0"  encoding = "UTF-8" ?>
< configuration  scan = "true"  scanPeriod = "60 seconds"  debug = "false" >
 
   < if  condition = 'isDefined("catalina.base")' >
     < then >
       < property  file = "${catalina.base}/conf/logback_val.properties"  />
     </ then >
     < else >
       < property  resource = "./conf/logback_val.properties"  />
     </ else >
   </ if >
   
   ...

logback_val.properties:

1
2
3
4
5
6
7
8
9
10
# \u90E8\u7F72\u7684\u73AF\u5883\u7C7B\u578B\uFF1Adev\u3001test\u3001product
deploy.env=dev
# \u4E3B\u65E5\u5FD7\u7EA7\u522B
log.root.level=DEBUG
# APP \u65E5\u5FD7\u7EA7\u522B
log.app.level=TRACE
# Kafka LogStash \u9009\u62E9\u4F7F\u7528 value= "yes" or "no"
log.use.logstash=yes
# LogStash Kafka URL
log.logstash.kafka=172.16.1.164:9092,172.16.1.165:9092,172.16.1.166:9092

log4j中进行过滤的方法 :

log4j中log.isDebugEnabled(), log.isInfoEnabled()和log.isTraceEnabled()作用 :
  1、项目在应用log4j打印Debug,Info和Trace级别的log时需要加上对应的三个方法进行过滤,代码如下:
		if (log.isDebugEnabled()) {
		    log.debug(" From: " + req.getFrom().toString() + 
		                  " To: " + req.getTo().toString() + 
		                  " CallId: " + req.getCallId() + 
		                  " msg:" + msg);
		}
	其作用是因为Debug,Info和Trace一般会打印比较详细的信息,而且打印的次数较多,如果我们不加log.isDebugEnabled()等
	进行预先判断,当系统loglevel设置高于Debug或Info或Trace时,虽然系统不会答应出这些级别的日志,但是每次还是会拼接
	参数字符串,影响系统的性能。
  2、错误的优化方法
	部分编码人员因为不了解机制,从代码复用性和简洁性而言定义如下函数来封装
	    private void debug(String msg) {
	        if (log.isDebugEnabled()) {
	            log.debug(msg);
	        }
	    }
	其实这种封装方式是错误的,因为当系统中调用debug(msg)函数还是出现字符串的拼接。
 
结论:这3个方法是对项目的优化方法,加这个方法目的在于如果代码中存在连接字符串的情况,打印信息时会出现太多的拼接字符串影响
       系统性能。如果系统中是固定字符串加不加都可以。  

  

log4j的使用:

##define an appender named console
log4j.appender.console=org.apache.log4j.ConsoleAppender
#The Target value is System.out or System.err(out kong zhi tai xian shi wei hei se;err kong zhi tai xian shi hong se)
log4j.appender.console.Target=System.out
#set the layout type of the apperder
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#set the layout format pattern(ri zhi ge shi)
log4j.appender.console.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}] %c %L %m%n


##define an appender named file(shu chu dao wen jian)
log4j.appender.file=org.apache.log4j.FileAppender
#define the file path and name
log4j.appender.file.File=d:/logfile.txt
#set the layout type of the apperder
log4j.appender.file.layout=org.apache.log4j.PatternLayout
#set the layout format pattern
log4j.appender.file.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}] %c %L %m%n


##define an appender named rollfile(shu chu dao wen jian,dan da dao zhi ding nei cun,hui chong xin cheng cheng yi ge wen jian)
log4j.appender.rollfile=org.apache.log4j.RollingFileAppender
#define the file path and name
log4j.appender.rollfile.File=d:/logrollfile.txt
#set the log's size(zhi ding ri zhi wen jian da xiao)
log4j.appender.rollfile.MaxFileSize=10KB
#set the layout type of the apperder
log4j.appender.rollfile.layout=org.apache.log4j.PatternLayout
#set the layout format pattern
log4j.appender.rollfile.layout.ConversionPattern=[%-5p][%d{yyyy-MM-dd HH:mm:ss}] %c %L %m%n


##define a logger(zhi ding ri zhi ji bie he shi yong na xie zui jia qi)
#log4j.logger.全限定性类名或接口名=INFO,console,file,rollfile
log4j.rootLogger=INFO,console,file,rollfile

  

log4j2的使用:

<?xml version="1.0" encoding="UTF-8"?>
<-- status 是否输出日志中的日志(引入了日志的jar包) -->
<configuration status="OFF">
	<appenders>
	    <-- SYSTEM_OUT/SYSTEM_ERR -->
		<Console name="myConsole" target="SYSTEM_OUT">
			<PatternLayout pattern="[%-5p][%d{yyyy-MM-dd HH:mm:ss}] [%c %L] %m%n" />
		</Console>
		<-- append="true" 表示追加,不删除之前的日志;false是会删除之前的日志	 -->
		<File name="myLogFile" fileName="log/test.log" append="true">
            <PatternLayout pattern="[%-5p][%d{yyyy-MM-dd HH:mm:ss}] [%c %L] %m%n"/>
        </File>
		<-- logs/app.log 项目根目录log -->
        <RollingFile name="myRollingFile" fileName="logs/app.log"
					 <-- 按月来管理日志 log.gz 的.gz为压缩格式 -->
                     filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
					 
					 <--
					 按日来管理日志  filePattern="logs/$${date:yyyy-MM-dd}/app-%d{MM-dd-yyyy}-%i.log.gz"
					 -->
					
					 
            <PatternLayout pattern="[%-5p][%d{yyyy-MM-dd HH:mm:ss}] [%c %L] %m%n"/>
			<-- 日志文件大小,超出这个空间,会重新生成一个文件 -->
            <SizeBasedTriggeringPolicy size="1KB"/>
        </RollingFile>
	</appenders>
	
	<loggers>
		<!-- 
		<logger name="全限定类名或接口名" level="info">
			<appender-ref ref="myConsole" />
		</logger>
		 -->
		<-- 日志输出级别 -->
		<root level="info">
			<-- 使用那些追加器 -->
			<appender-ref ref="myConsole" />
			<!-- <appender-ref ref="myLogFile" /> -->
			<!-- <appender-ref ref="myRollingFile" /> -->
		</root>
	</loggers>
	
</configuration>

  

 

 

 

参考资料:

http://logback.qos.ch/manual/configuration.html#conditional

转载于:https://www.cnblogs.com/qqyong123/p/8579037.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编写web项目运维手册是为了帮助运维团队更好地理解和操作项目,保证项目的正常运行。下面是关于如何编写web项目运维手册的一些建议。 1. 简要介绍项目:首先,在手册的开头部分,应该简要介绍项目的背景、目的和功能。这样有助于读者对项目有一个整体的了解。 2. 系统架构和组件:详细说明项目的系统架构,包括各个组件之间的关系和功能。可以使用流程图、架构图或者表格来明确显示每个组件的作用和位置。 3. 部署和安装:提供清晰的部署和安装指南,包括操作系统和软件依赖的安装、数据库的配置和建立等。同时,也应该考虑到可能遇到的常见问题,并提供解决方案。 4. 配置文件和参数:列出所有需要配置的文件和参数,包括每个参数的功能以及推荐的设置。确保读者能够根据手册进行正确的配置。 5. 监控和报警:介绍如何设置和使用监控系统来实时监测项目的状态,以及如何设置报警规则。可以提供一些常见的监控指标和解决方案。 6. 维护和升级:说明项目的日常维护工作,包括数据库备份、日志清理、定时任务的管理等。同时,也应该提供项目升级的步骤和注意事项。 7. 故障处理:列出可能遇到的常见故障以及相应的解决方案,提供故障排查的指导方法。同时,还可以提供联系方式,以便读者在遇到问题时能够及时求助。 8. 常见问题和解答:总结一些常见的问题和解答,如常见的配置错误、性能问题等。这样可以帮助读者快速定位和解决问题。 9. 参考资料:提供一些相关的参考资料,如项目的技术文档、第三方库的文档等。这样可以帮助读者进一步了解项目和相关技术。 10. 版本记录:最后,可以在手册中添加一个版本记录表,记录每次更新的内容和日期,方便用户查看手册的历史变更。 通过以上步骤的编写,可以使web项目运维手册更加清晰、具体和易于理解。这有助于提高运维效率和项目的稳定性,减少故障发生和处理的时间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值