2.1、服务日志输出规范
服务日志输出规范
为了方便日志的统一管理,要求业务系统需要将日志输出到统一的日志存储空间。
日志存储空间,我们有以下3个选择,请根据业务部署的实际情况进行选择:
- 输出到本地磁盘:适用于无日志系统,无对象存储的部署环境
- 输出到对象存储:适用于无日志系统,有对象存储的部署环境
- 输出到日志系统:适用于有日志系统的部署环境
配置日志输出
在服务的 conf/ 目录下增加 log4j2-k8s.xml 配置,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<Configuration status="WARN" monitorInterval="30">
<!-- Properties:设置全局变量 -->
<Properties>
<!--
%m 输出代码中指定的消息
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss ,SSS},输出类似:2002年10月18日 22 : 10 : 28 , 921
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java: 10 )
-->
<!-- 定义LOG存储位置 -->
<Property name="LOG_HOME">/logs</Property>
<!-- 定义应用名称 -->
<property name="APP_NAME">tianyin-edu-user</property>
<!-- 日志输出格式:什么时间(日志时间)?什么应用(应用标记)?什么位置(线程、类、方法)?发送了什么(日志内容)? -->
<Property name="LOG_CONSOLE_LAYOUT">%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{[${APP_NAME}]}{red} [%traceId] %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n%xwEx</Property>
<Property name="LOG_CONSOLE_LAYOUT2">%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{[${APP_NAME}]}{red} [%clr{%p} %clr{${sys:PID}}{magenta}] %clr{---}{faint} %clr{[%t]}{faint} %clr{[%C:%M:%L]}{cyan} %clr{:}{faint} %m%n%xwEx</Property>
<Property name="LOG_FILE_LAYOUT">%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{[${APP_NAME}]}{red} [%traceId] %clr{%5p} %clr{${sys:PID}}{magenta} %clr{---}{faint} %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n%xwEx</Property>
<Property name="LOG_FILE_LAYOUT2">%d{yyyy-MM-dd HH:mm:ss.SSS} [${APP_NAME}] %p ${sys:PID} [%X{X-B3-TraceId}] [%t] [%C:%M:%L] : %m%n%xwEx</Property>
<!-- 日志文件主名称规则 -->
<Property name="LOG_FILE_NAME">${LOG_HOME}/${APP_NAME}/app-log.log</Property>
<!-- 日志文件备份名称规则 -->
<Property name="LOG_FILE_PATTERN">${LOG_HOME}/${APP_NAME}/%d{yyyy-MM-dd}/app-log-%d{yyyy-MM-dd}-%i.log</Property>
</Properties>
<!-- Appenders:定义日志输出目的地,内容和格式等 -->
<Appenders>
<!--
Console:用于输出在控制台
File:输出日志文件,不可设置,无限增长
RollingFile:输出日志文件,超过指定大小会将文件保存至文件夹中,再删除,然后新建文件
RollingRandomAccessFile:输出日志文件,超过指定大小会将文件保存至文件夹中,再删除,然后新建文件
-->
<!--Console:日志输出到控制台标准输出 -->
<Console name="Console" target="SYSTEM_OUT">
<!--pattern:日期,线程名,日志级别,日志名称,日志信息,换行 -->
<PatternLayout pattern="${LOG_CONSOLE_LAYOUT}" disableAnsi="false" noConsoleNoAnsi="false"></PatternLayout>
<Filters>
<!--ERROR及以上的不接受,只接受一下的 -->
<ThresholdFilter level="ERROR" onMatch="DENY" onMismatch="ACCEPT"></ThresholdFilter>
</Filters>
</Console>
<!--SYSTEM_ERR:输出的为红色-->
<Console name="ConsoleError" target="SYSTEM_ERR">
<!--pattern:日期,线程名,日志级别,日志名称,日志信息,换行 -->
<PatternLayout pattern="${LOG_CONSOLE_LAYOUT}" ></PatternLayout>
<Filters>
<!--ERROR以下的不接受,只接受ERROR及以上的 -->
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"></ThresholdFilter>
</Filters>
</Console>
<!--RollingRandomAccessFile:日志输出到文件 -->
<!-- 实时日志放到 logs/main.log 文件中,按天或者超过size则自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
<RollingRandomAccessFile name="LogRollingFile" fileName="${LOG_FILE_NAME}" filePattern="${LOG_FILE_PATTERN}">
<Filters>
<!--只接受DEBUG级别的日志,其余的全部拒绝处理-->
<ThresholdFilter level="DEBUG"></ThresholdFilter>
</Filters>
<!-- 输出日志事件调用者的完全限定名、源文件名和行号,注意可能会影响性能,请谨慎使用。 -->
<PatternLayout pattern="${LOG_FILE_LAYOUT}" ></PatternLayout>
<!--Policies:触发策略决定何时执行备份 -->
<Policies>
<!--TimeBasedTriggeringPolicy:日志文件按照时间备份 -->
<!--interval:每1天分钟生成一个新文件,需要结合filePattern时间%d{yyyy-MM-dd} -->
<!--同理,如果要每1小时生成一个新文件,则改成%d{yyyy-MM-ddHH} -->
<!--modulate:对备份日志的生成时间纠偏,纠偏以0为基准进行,"0+interval"决定启动后第一次备份时间 -->
<TimeBasedTriggeringPolicy interval="1" modulate="true" ></TimeBasedTriggeringPolicy>
<!--SizeBasedTriggeringPolicy:日志文件按照大小备份 -->
<!--size:指定日志文件最大为100MB,单位可以为KB、MB或GB -->
<SizeBasedTriggeringPolicy size="100MB" ></SizeBasedTriggeringPolicy>
</Policies>
<!--DefaultRolloverStrategy:翻转策略决定如何执行备份 -->
<!--max:最多保存5个日志备份文件,结合时间使用后,在每个时间段内最多有5个备份,多出来的会被覆盖 -->
<!--compressionLevel:配置日志压缩级别,范围0-9,0不压缩,1压缩速度最快,9压缩率最好,目前只对于zip压缩文件类型有效 -->
<DefaultRolloverStrategy max="10" compressionLevel="1">
<!--Delete:删除匹配到的过期备份日志文件 -->
<!--maxDepth:由于备份日志保存在${LOG_HOME}/$${date:yyyy-MM},所以目录深度设置为2 -->
<Delete basePath="${LOG_HOME}" maxDepth="3">
<!--IfFileName:匹配文件名称 -->
<!--glob:匹配2级目录深度下的以.log.gz结尾的备份文件 -->
<IfFileName glob="*/*.log" ></IfFileName>
<!--IfLastModified:匹配文件修改时间 -->
<!--age:匹配超过180天的文件,单位D、H、M、S分别表示天、小时、分钟、秒-->
<IfLastModified age="31D" ></IfLastModified>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
<!-- skywalking grpc 日志收集 8.4.0版本开始支持 -->
<GRPCLogClientAppender name="grpc-log">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"></PatternLayout>
</GRPCLogClientAppender>
</Appenders>
<!--Loggers:定义日志级别和使用的Appenders -->
<Loggers>
<!-- ###############同步日志配置############### -->
<!--Root:日志默认打印到控制台 -->
<!--level日志级别: ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF -->
<Root level="ALL" includeLocation="true">
<AppenderRef ref="ConsoleError"></AppenderRef>
<AppenderRef ref="LogRollingFile"></AppenderRef>
<AppenderRef ref="grpc-log"></AppenderRef>
</Root>
<!-- 框架、依赖组件日志过滤 -->
<Logger name="com.alibaba.druid" level="ERROR" additivity="true"></Logger>
<Logger name="com.alibaba.nacos" level="ERROR" additivity="true"></Logger>
<Logger name="com.baomidou.mybatisplus" level="WARN" additivity="true"></Logger>
<Logger name="com.github.dozermapper" level="ERROR" additivity="true"></Logger>
<Logger name="com.mongodb" level="WARN" additivity="true"></Logger>
<Logger name="com.opensymphony.xwork2" level="WARN" additivity="true"></Logger>
<Logger name="com.zaxxer.hikari" level="WARN" additivity="true"></Logger>
<Logger name="de.codecentric.boot" level="WARN" additivity="true"></Logger>
<Logger name="io.lettuce" level="WARN" additivity="true"></Logger>
<Logger name="io.undertow" level="WARN" additivity="true"></Logger>
<Logger name="io.netty" level="WARN" additivity="true"></Logger>
<Logger name="net.sf.ehcache" level="WARN" additivity="true"></Logger>
<Logger name="java.sql" level="WARN" additivity="true"></Logger>
<Logger name="java.sql.Connection" level="WARN" additivity="true"></Logger>
<Logger name="java.sql.Statement" level="WARN" additivity="true"></Logger>
<Logger name="java.sql.PreparedStatement" level="WARN" additivity="true"></Logger>
<Logger name="java.sql.ResultSet" level="WARN" additivity="true"></Logger>
<Logger name="org.apache.commons" level="ERROR" additivity="true"></Logger>
<Logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR" additivity="true"></Logger>
<Logger name="org.apache.catalina.util.LifecycleBase" level="ERROR" additivity="true"></Logger>
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN" additivity="true"></Logger>
<Logger name="org.apache.http" level="WARN" additivity="true" ></Logger>
<Logger name="org.apache.shiro" level="WARN" additivity="true" ></Logger>
<Logger name="org.apache.ibatis" level="WARN" additivity="true"></Logger>
<Logger name="org.apache.ibatis.jdbc.ScriptRunner" level="WARN" additivity="true"></Logger>
<Logger name="org.apache.rocketmq" level="WARN" additivity="true"></Logger>
<logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"></logger>
<Logger name="org.apache.struts2" level="WARN" additivity="true"></Logger>
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN" additivity="true"></Logger>
<Logger name="org.dozer" level="WARN" additivity="true"></Logger>
<Logger name="org.crsh.plugin" level="WARN" additivity="true" ></Logger>
<logger name="org.crsh.ssh" level="WARN" additivity="true"></logger>
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR" additivity="true" ></Logger>
<Logger name="org.flywaydb" level="WARN" additivity="true"></Logger>
<Logger name="org.hibernate.validator" level="WARN" additivity="true" ></Logger>
<Logger name="org.mybatis" level="WARN" additivity="true"></Logger>
<Logger name="org.pac4j" level="WARN" additivity="true"></Logger>
<Logger name="org.quartz" level="WARN" additivity="true"></Logger>
<Logger name="org.redisson" level="WARN" additivity="true"></Logger>
<Logger name="org.springframework" level="WARN" additivity="true"></Logger>
<Logger name="org.springframework.data.redis" level="WARN" additivity="true"></Logger>
<Logger name="org.springframework.security" level="WARN" additivity="true"></Logger>
<Logger name="org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration" level="WARN" additivity="true"></Logger>
<Logger name="org.springframework.boot.actuate.endpoint.jmx" level="WARN" additivity="true"></Logger>
<Logger name="org.thymeleaf" level="WARN" additivity="true"></Logger>
<Logger name="org.xnio" level="WARN" additivity="true"></Logger>
<Logger name="net.bull.javamelody" level="WARN" additivity="true"></Logger>
<Logger name="net.oschina" level="WARN" additivity="true"></Logger>
<Logger name="reactor" level="WARN" additivity="true"></Logger>
<Logger name="RocketmqClient" level="WARN" additivity="true"></Logger>
<Logger name="springfox" level="WARN" additivity="true"></Logger>
<!--log4j2 自带过滤日志-->
<!-- 应用系统日志过滤 -->
<Logger name="com.tianyin" level="DEBUG" additivity="true"></Logger>
<Logger name="com.tianyin.authz" level="DEBUG" additivity="true"></Logger>
<Logger name="com.tianyin.biz" level="DEBUG" additivity="true"></Logger>
<Logger name="[Mybatis]com.tianyin" level="DEBUG" additivity="true"></Logger>
</Loggers>
</Configuration>生产环境,在服务启动配置 application-prod.yaml , 增加下面日志的配置(从配置中心读取的需修改配置中心的配置内容):
################################################################################################################
###logging (log4j2) 基本配置:
###http://www.cnblogs.com/yhtboke/p/Mybatis.html
################################################################################################################
logging:
config: classpath:conf/log4j2-k8s.xml完成上面的配置后,重新打包镜像,启动后,日志将会输出到 Docker 的 /logs 目录中,可通过控制台进入Pod后,通过 Linux 命令查看日志。

输出到本地磁盘(适用于无日志系统,无对象存储的部署环境)
在“配置日志输出”内容部分,已经将服务的日志,输出到了 Pod 的 /logs 目录下。但是存在一个问题,是如果 Pod 重启或删除,这个日志就会丢失,所以我们可以通过给 K8s Deployment 配置 存储卷 的方式把日志输出转到本地磁盘。

| 配置项 | 值 | 说明 |
|---|---|---|
| 卷名称 | log-dist |
HostPath 卷的名称 |
| 主机路径 | /www/wwwlogs |
宿主机上的路径,这里选择日志输出的根路径 |
| 读写权限 | 读写 |
需要写读写权限 |
| 挂载路径 | /logs |
Pod 的路径 |
输出到对象存储(适用于无日志系统,有对象存储的部署环境)
日志输出到本地磁盘,虽然能保证Pod 重启或删除时候,日志依旧存在,但还存在管理不方便的情况。这时候,我们可以考虑创建分布式持久卷声明,并将根据持久卷声明创建的持久卷挂载到容器。
- 基于 MinIO 创建分布式持久卷声明

- 将根据持久卷声明创建的持久卷挂载到容器

输出到日志系统(适用于有日志系统的部署环境)
如果我们有日志系统,通常会有日志采集的工具,我们只需要把日志输出到本地磁盘,并交给日志采集工具(Logtail、Logstash、FileBeat 等)把日志采集并输出到日志系统(SLS、Elasticsearch、Loki 等)即可。
- FileBeat 日志采集
作者:杭州天音 创建时间:2024-11-01 12:16
最后编辑:杭州天音 更新时间:2025-08-20 19:36
最后编辑:杭州天音 更新时间:2025-08-20 19:36