§ 开发约束
§ 日志开发
§ 日志级别
| 日志级别 | 级别描述 | 信息类别 |
|---|---|---|
| DEBUG | 细粒度的级别。对出错以及系统调试时输出的信息、事件进行记录。程序的关键路径,输出较频繁。 | 调试信息 |
| INFO | 粗粒度的级别。在正常运行状态中,对重要流程/事件以及表示系统健康度的信息、事件进行记录。 此级别不允许输出SQL语句等调试用敏感信息。 | 一般信息 |
| WARN | 有潜在风险的、不会造成大危害的错误发生(往往由应用餐部因素造成,如不正确的输入数据等)。 | 错误信息 |
| ERROR | 应用发生错误(包括业务错误和技术错误),但后续流程还能继续进行。 | 错误信息 |
| FATAL | 应用发生严重错误(技术型异常),应用服务停止。 | 错误信息 |
系统级日志级别:ERROR
§ 日志打印
Debug级别日志输出,需要增加debug状态判断
if (logger.isDebugEnabled()) {
logger.debug("菜单信息:{}", adminSmMenu);
}
1
2
3
2
3
日志输出时,避免逻辑操作,如下日志输出,user.getRole().getId()会存在空指针的情况
if ("admin".equals(user.getName) {
logger.debug("菜单信息:{}", user.getRole().getId());
}
1
2
3
2
3
§ 敏感信息
任何级别的系统日志中不允许出现客户相关的:
- 指纹、人脸等生物特征的特征码
- 信息加密所使用的密钥串
- 密码,明文密码、密文密码均不允许出现,可以以**的形式代替,但是的位数不能暴露密码的长度信息
- 银行卡相关的磁道信息、验证信息,包括2磁、3磁及相关信息
- IC卡相关的芯片信息,包括ARQC、等效2磁等信息
- (暂定为非强制性规范)客户姓名、手机号、证件号建议进行部分隐藏,隐藏规则如下:
§ 日志文件输出
§ 日志记录的内容应总体满足如下规则
- 应用程序日志原则上使用UTF-8字符编码,以便于将来的日志文件分析
- 不应使用系统输出进行日志记录。例如 System.out. print,printStackTrace等方法
- 不应将应用日志写入生产环境操作系统、以及其他中间件产品的日志文件中。例如 SystemErr.log、SystemOut.log等文件
- 日志在记录时无论成功与否,都不应改变业务逻辑
§ 输出格式
系统默认提供如下格式,如果启用了链路跟踪,将在 [main, , ]中打印链路中traceId和spanId的信息:
[${applicationName}, ${ip}] %-5p %d{yyyy-MM-dd HH:mm:ss.SSS} [%t, %X{X-B3-TraceId:-}, %X{X-B3-SpanId:-}] %c.%M:%L - %m%n
1
即输出的日志示例如下:
[yusp-app-oca, 172.16.20.208] INFO 2019-03-08 18:40:27.766 [main, , ] cn.com.yusys.yusp.commons.config.ExcelTaskAutoConfiguration.getExcelRemoteCall:55 - 加载缺省的ExcelRemoteCallDefaultImpl
[yusp-app-oca, 172.16.20.208] INFO 2019-03-08 18:40:28.680 [main, , ] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.register:549 - Mapped "{[/api/pdfdemo/gethtml],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView cn.com.yusys.yusp.admin.web.rest.AdminPdfDemoResource.gethtml()
[yusp-app-oca, 172.16.20.208] INFO 2019-03-08 18:40:28.693 [main, , ] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.register:549 - Mapped "{[/api/pdfdemo/getpdf],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView cn.com.yusys.yusp.admin.web.rest.AdminPdfDemoResource.getpdf(java.lang.String)
[yusp-app-oca, 172.16.20.208] INFO 2019-03-08 18:40:28.693 [main, , ] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.register:549 - Mapped "{[/api/adminsmauthinfo/delete/{id}],methods=[POST]}" onto public cn.com.yusys.yusp.commons.web.rest.dto.ResultDto<java.lang.Integer> cn.com.yusys.yusp.admin.web.rest.AdminSmAuthInfoResource.delete(java.lang.String)
1
2
3
4
2
3
4
§ 可用日志属性列表
| level | 输出日志级别 | 基础 |
|---|---|---|
| thread | 输出产生日志的线程名。 | 基础 |
| class | 输出执行记录请求的调用者的全限定名 | 基础 |
| line | 输出执行日志请求的行号 | 基础 |
| message | 输出应用程序提供的信息 | 基础 |
| exception{X} | 异常栈信息 | 基础 |
| logger{X} | 输出类名 | 基础 |
| PID | 进程ID | 基础 |
| springAppName | 记录跨度的应用程序的名称 | 基础 |
| X-B3-SpanId | 发生特定操作的ID | springCloud扩展 |
| X-B3-TraceId | 包含跨度的延迟图的ID | springCloud扩展 |
| X-B3-ParentSpanId | 日志是否应该被导出到Zipkin与否 | springCloud扩展 |
| X-Span-Export | 父级操作ID | springCloud扩展 |
| timestamp | 时间戳 | ELK扩展-默认打印,不需要配置 |
| host | 服务主机IP | ELK扩展-默认打印,不需要配置 |
| applicationName | 应用名称 | |
| IP | 应用ip地址,自定义输出字段 |
§ 关于pattern 控制输出的内容
%c,%c{参数},%C{参数},%class{参数},%lo{参数},%logger{参数}:输出类名称
| %c | org.apache.com.te.Foo | org.apache.com.te.Foo |
|---|---|---|
| %c{1} | org.apache.com.te.Foo | Foo |
| %c{2} | org.apache.com.te.Foo | te.Foo |
| %c{1.} | org.apache.com.te.Foo | o.a.c.t.Foo |
| %c{1.1.!} | org.apache.com.te.Foo | o.a.!.!.Foo |
| %c{.} | org.apache.com.te.Foo | ….Foo |
%d{参数},%date{参数}:输出时间。参数可以是text.SimpleDateFormat字符拼接而成,也可以使用系统默认
| %d | 2006-10-20 14:06:49,812 |
|---|---|
| %date | 2006-10-20 14:06:49,812 |
| %date{ISO8601} | 2006-10-20 14:06:49,812 |
| %date{HH:mm:ss.SSS} | 14:06:49.812 |
| %date{dd MMM yyyy ;HH:mm:ss.SSS} | 20 oct. 2006;14:06:49.812 |
%L,%line:输出执行日志请求的行号。尽量避免使用,除非执行速度不造成任何问题。
%m或%msg或%message:输出日志信息
%M或%method:输出方法名
%p,%le,%level:输出日志级别
%t,%thread:输出产生日志的线程名
§ ide模板提供的默认日志
如下为通过ide创建模板时提供的默认logback日志配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!-- 启用每隔60s读取该文件,刷新配置信息 -->
<configuration scan="true" scanPeriod="60000">
<!-- 导入SpringBoot默认的logback配置 -->
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<!-- 通过spring上下文获取对应的配置信息 -->
<!-- 获取日志文件的路径(取自bootstrap.yml/bootstrap.properties文件) -->
<springProperty scope="context" name="logPath" source="logging.path" defaultValue="../logs"></springProperty>
<!-- 获取日志文件的名称(取自bootstrap.yml/bootstrap.properties文件) -->
<springProperty scope="context" name="logFile" source="logging.file" defaultValue="application.log"></springProperty>
<!-- 获取当前启动的应用名称 (取自bootstrap.yml/bootstrap.properties文件)-->
<springProperty scope="context" name="applicationName" source="spring.application.name"></springProperty>
<!-- 获取当前启动应用的日志级别(取自bootstrap.yml/bootstrap.properties文件) -->
<springProperty scope="context" name="logLevel" source="logging.level.root" defaultValue="INFO"></springProperty>
<!-- 自定义属性,当前自定义为获取服务所在机器IP地址 -->
<define name="ip" class="cn.com.yusys.yusp.commons.log.CustomizedApplicationIP"></define>
<!-- logback上下文属性配置 -->
<!-- 日志文件输出格式定义(如不定义,默认取defaults.xml中配置) -->
<property name="FILE_LOG_PATTERN" value="[${applicationName}, ${ip}] %-5p %d{yyyy-MM-dd HH:mm:ss.SSS} [%t, %X{X-B3-TraceId:-}, %X{X-B3-SpanId:-}] %c.%M:%L - %m%n"/>
<!-- 控制台日志格式输出定义(如不定义,默认取defaults.xml中配置) -->
<property name="CONSOLE_LOG_PATTERN" value="[${applicationName}, ${ip}] %-5p %d{yyyy-MM-dd HH:mm:ss.SSS} [%t, %X{X-B3-TraceId:-}, %X{X-B3-SpanId:-}] %c.%M:%L - %m%n"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<!-- 默认的日志文件输出 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<append>true</append>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
<file>${logPath}/${logFile}</file>
<!-- 日志生成策略,按日备份,最大保留30天,每128M切分一个日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${logPath}/%d{yyyy-MM-dd}/${logFile}.%i.log</fileNamePattern>
<maxHistory>7</maxHistory>
<maxFileSize>128MB</maxFileSize>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
</appender>
<!-- 日志输出控制 -->
<root level="${logLevel}">
<appender-ref ref="FILE" />
<appender-ref ref="CONSOLE" />
</root>
</configuration>
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
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
其中的备份策略见rollingPolicy节点,默认为每128M切换一个文件,最大每天为1G的日志文件,保存历史为7天
其中日志输出到控制台和日志文件,日志文件的路径见file节点配置
§ 自定义日志输出字段属性
自定义日志属性的开发可参见CustomizedApplicationIP类,配置方式见上一章节define节点配置方式
示例代码如下:
public class CustomizedApplicationIP extends ClassicConverter implements PropertyDefiner {
private static String ip;
static {
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
@Override
public String convert(ILoggingEvent event) {
return ip;
}
@Override
public String getPropertyValue() {
return ip;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22