spring boot log 配置

​ 使用log4j2

Q1:过滤掉系统日志??
1
2
3
4
5
6
7
8
9
10
11
12
<loggers>
<!-- 过滤掉org.springframework包下面的日志-->
<!-- name对应代码的包 additivity设置为false表示不会到root的log里面 -->
<logger name="org.springframework" level="INFO" additivity="false">
</logger>
<root level="INFO">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
Q2: 不同级别的日志输出到不同的文件??

https://github.com/bycuimiao/springboot2-log4j2-demo/blob/master/src/main/resources/log4j2.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
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log"
filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
<Filters>
<!-- 表示对于warn以及warn级别以上的日志 deny,对于warn一下子的日志不拦截 -->
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="NEUTRAL"/>
<!-- 表示info以及以上的日志接受,以下的deny掉 (因为info的以上的日志都被上面的filter过滤掉了,所以只有info的日志可以通过这两个filter)-->
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="1M"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log"
filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
<Filters>
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="1M"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log"
filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="1M"/>
</Policies>
</RollingFile>
Q3:不同环境日志文件位置问题??

对于日志的位置,不能使用绝对路径,原因是多人开发,每个人机器上的路径不一致,这个时候可以使用

1
<property name="FILE_PATH" value="${sys:user.home}/home/logs"/>

${sys:user.home}表示用户的目录,cd ~

在docker容器中对应/root 目录

Q4:日志打印

利用servelet拦截器

https://www.jianshu.com/p/afdd31bfbf94

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
96
97
98
99
100
101
102
103
104
package com.lingshiedu.lszy.filter

import org.slf4j.LoggerFactory
import org.slf4j.MDC
import org.springframework.stereotype.Component
import org.springframework.web.util.ContentCachingRequestWrapper
import org.springframework.web.util.ContentCachingResponseWrapper
import org.springframework.web.util.WebUtils
import java.io.UnsupportedEncodingException
import java.nio.charset.Charset
import java.util.*
import javax.servlet.*
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

@Component
class LogFilter : Filter {
val Logger = LoggerFactory.getLogger(LogFilter::class.java)
val SPLIT_STRING_M = "="
val SPLIT_STRING_DOT = ", "
override fun destroy() {
}

override fun doFilter(req: ServletRequest?, res: ServletResponse?, filterChain: FilterChain?) {
val request = req as HttpServletRequest
val response = res as HttpServletResponse
MDC.clear()
//给本次请求分配一个唯一的tradeId
MDC.put("trade_id", UUID.randomUUID().toString().replace("-", ""))

val wrapperRequest = ContentCachingRequestWrapper(request)
val wrapperResponse = ContentCachingResponseWrapper(response)

Logger.info("method[{}] | queryUrl[{}] | headers[{}] | queryParams[{}] | body:{}", request.method, request.requestURL, getHeaders(req), getRequestParams(request), getRequestBody(wrapperRequest))
filterChain!!.doFilter(wrapperRequest, wrapperResponse)
Logger.info("resp body:{}", getResponseBody(wrapperResponse))

wrapperResponse.copyBodyToResponse()
}

private fun getRequestBody(request: ContentCachingRequestWrapper): String? {
val wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper::class.java)
if (wrapper != null) {
val buf = wrapper.contentAsByteArray
if (buf.isNotEmpty()) {
val payload: String = try {
String(buf, 0, buf.size, Charset.forName(wrapper.characterEncoding))
} catch (e: UnsupportedEncodingException) {
"[unknown]"
}

return payload.replace("\\n".toRegex(), "")
}
}

return ""
}

private fun getHeaders(req: HttpServletRequest): String? {
var header = ""
for (key in req.headerNames) {
val value = req.getHeader(key)
header += " [key:${key} value:${value}] "
}

return header
}

private fun getResponseBody(response: ContentCachingResponseWrapper): String? {
val wrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper::class.java)
if (wrapper != null) {
val buf = wrapper.contentAsByteArray
if (buf.isNotEmpty()) {
val payload: String = try {
String(buf, 0, buf.size, Charset.forName(wrapper.characterEncoding))
} catch (e: UnsupportedEncodingException) {
"[unknown]"
}

return payload
}
}

return ""
}

fun getRequestParams(request: HttpServletRequest): String? {
val sb = StringBuilder()
val enu = request.parameterNames
//获取请求参数
while (enu.hasMoreElements()) {
val name = enu.nextElement()
sb.append(name + SPLIT_STRING_M).append(request.getParameter(name))
if (enu.hasMoreElements()) {
sb.append(SPLIT_STRING_DOT)
}
}

return sb.toString()
}

override fun init(p0: FilterConfig?) {
}
}