<ul class="tag-group">
<li class="tag tag-item">
<a href="/tags/type_blog-tagid_467/" target="_blank" class="label-item"><span>日志</span></a>
</li>
<li class="tag tag-item">
<a href="/tags/type_blog-tagid_641/" target="_blank" class="label-item"><span>spring</span></a>
</li>
<li class="tag tag-item">
<a href="/tags/type_blog-tagid_951/" target="_blank" class="label-item"><span>logger</span></a>
</li>
<li class="tag tag-item">
<a href="/tags/type_blog-tagid_1383/" target="_blank" class="label-item"><span>Annotation</span></a>
</li>
<li class="tag tag-item">
<a href="/tags/type_blog-tagid_2468/" target="_blank" class="label-item"><span>pattern</span></a>
</li>
<li class="tag tag-item">
<a href="/tags/type_blog-tagid_2952/" target="_blank" class="label-item"><span>BIND</span></a>
</li>
</ul>
<div class="article-hide-content">
<div class="content-detail unsafe markdown-body" data-spm-anchor-id="a2c4e.11153940.0.i1.23f37c8fEbedt7">
概述
Java应用中,日志一般分为以下5个级别:
- ERROR 错误信息
- WARN 警告信息
- INFO 一般信息
- DEBUG 调试信息
- TRACE 跟踪信息
Spring Boot使用Apache的Commons Logging作为内部的日志框架,其仅仅是一个日志接口,在实际应用中需要为该接口来指定相应的日志实现。
SpringBt默认的日志实现是Java Util Logging,是JDK自带的日志包,此外SpringBt当然也支持Log4J、Logback这类很流行的日志实现。
统一将上面这些日志实现统称为日志框架
下面我们来实践一下!
使用Spring Boot Logging插件
- 首先application.properties文件中加配置:
logging.level.root=INFO
- 控制器部分代码如下:
package com.hansonwang99.controller;
import com.hansonwang99.K8sresctrlApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
("/testlogging")
public class LoggingTestController {
private static Logger logger = LoggerFactory.getLogger(K8sresctrlApplication.class);
("/hello")
public String hello() {
logger.info(“test logging…”);
return “hello”;
}
}
- 运行结果
由于将日志等级设置为INFO,因此包含INFO及以上级别的日志信息都会打印出来
这里可以看出,很多大部分的INFO日志均来自于SpringBt框架本身,如果我们想屏蔽它们,可以将日志级别统一先全部设置为ERROR,这样框架自身的INFO信息不会被打印。然后再将应用中特定的包设置为DEBUG级别的日志,这样就可以只看到所关心的包中的DEBUG及以上级别的日志了。
- 控制特定包的日志级别
application.yml中改配置
logging:
level:
root: error
com.hansonwang99.controller: debug
很明显,将root日志级别设置为ERROR,然后再将com.hansonwang99.controller
包的日志级别设为DEBUG,此即:即先禁止所有再允许个别的 设置方法
- 控制器代码
package com.hansonwang99.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
("/testlogging")
public class LoggingTestController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
("/hello")
public String hello() {
logger.info(“test logging…”);
return “hello”;
}
}
- 运行结果
可见框架自身的INFO级别日志全部藏匿,而指定包中的日志按级别顺利地打印出来
- 将日志输出到某个文件中
logging:
level:
root: error
com.hansonwang99.controller: debug
file: ${user.home}/logs/hello.log
- 运行结果
使用Spring Boot Logging,我们发现虽然日志已输出到文件中,但控制台中依然会打印一份,发现用org.slf4j.Logger
是无法解决这个问题的
集成Log4J日志框架
- pom.xml中添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
- 在resources目录下添加
log4j2.xml
文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<span class="hljs-tag"><<span class="hljs-name">appenders</span>></span>
<span class="hljs-tag"><<span class="hljs-name">File</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"file"</span> <span class="hljs-attr">fileName</span>=<span class="hljs-string">"${sys:user.home}/logs/hello2.log"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">PatternLayout</span> <span class="hljs-attr">pattern</span>=<span class="hljs-string">"%d{HH:mm:ss,SSS} %p %c (%L) - %m%n"</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">File</span>></span>
<span class="hljs-tag"></<span class="hljs-name">appenders</span>></span>
<span class="hljs-tag"><<span class="hljs-name">loggers</span>></span>
<span class="hljs-tag"><<span class="hljs-name">root</span> <span class="hljs-attr">level</span>=<span class="hljs-string">"ERROR"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">appender-ref</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"file"</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">root</span>></span>
<span class="hljs-tag"><<span class="hljs-name">logger</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"com.hansonwang99.controller"</span> <span class="hljs-attr">level</span>=<span class="hljs-string">"DEBUG"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">loggers</span>></span>
</configuration>
- 其他代码都保持不变
运行程序发现控制台没有日志输出,而hello2.log文件中有内容,这符合我们的预期:
而且日志格式和pattern="%d{HH:mm:ss,SSS} %p %c (%L) - %m%n"
格式中定义的相匹配
Log4J更进一步实践
- pom.xml配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<span class="hljs-tag"><<span class="hljs-name">dependency</span>></span>
<span class="hljs-tag"><<span class="hljs-name">groupId</span>></span>org.springframework.boot<span class="hljs-tag"></<span class="hljs-name">groupId</span>></span>
<span class="hljs-tag"><<span class="hljs-name">artifactId</span>></span>spring-boot-starter-log4j2<span class="hljs-tag"></<span class="hljs-name">artifactId</span>></span>
<span class="hljs-tag"></<span class="hljs-name">dependency</span>></span></code></pre>
- log4j2.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="warn">
<properties>
<span class="hljs-tag"><<span class="hljs-name">Property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"app_name"</span>></span>springboot-web<span class="hljs-tag"></<span class="hljs-name">Property</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"log_path"</span>></span>logs/${app_name}<span class="hljs-tag"></<span class="hljs-name">Property</span>></span>
<span class="hljs-tag"></<span class="hljs-name">properties</span>></span>
<span class="hljs-tag"><<span class="hljs-name">appenders</span>></span>
<span class="hljs-tag"><<span class="hljs-name">console</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"Console"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"SYSTEM_OUT"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">PatternLayout</span> <span class="hljs-attr">pattern</span>=<span class="hljs-string">"[%d][%t][%p][%l] %m%n"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">console</span>></span>
<span class="hljs-tag"><<span class="hljs-name">RollingFile</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"RollingFileInfo"</span> <span class="hljs-attr">fileName</span>=<span class="hljs-string">"${log_path}/info.log"</span>
<span class="hljs-attr">filePattern</span>=<span class="hljs-string">"${log_path}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log.gz"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Filters</span>></span>
<span class="hljs-tag"><<span class="hljs-name">ThresholdFilter</span> <span class="hljs-attr">level</span>=<span class="hljs-string">"INFO"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">ThresholdFilter</span> <span class="hljs-attr">level</span>=<span class="hljs-string">"WARN"</span> <span class="hljs-attr">onMatch</span>=<span class="hljs-string">"DENY"</span>
<span class="hljs-attr">onMismatch</span>=<span class="hljs-string">"NEUTRAL"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">Filters</span>></span>
<span class="hljs-tag"><<span class="hljs-name">PatternLayout</span> <span class="hljs-attr">pattern</span>=<span class="hljs-string">"[%d][%t][%p][%c:%L] %m%n"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">Policies</span>></span>
<span class="hljs-comment"><!-- 归档每天的文件 --></span>
<span class="hljs-tag"><<span class="hljs-name">TimeBasedTriggeringPolicy</span> <span class="hljs-attr">interval</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">modulate</span>=<span class="hljs-string">"true"</span> /></span>
<span class="hljs-comment"><!-- 限制单个文件大小 --></span>
<span class="hljs-tag"><<span class="hljs-name">SizeBasedTriggeringPolicy</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"2 MB"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">Policies</span>></span>
<span class="hljs-comment"><!-- 限制每天文件个数 --></span>
<span class="hljs-tag"><<span class="hljs-name">DefaultRolloverStrategy</span> <span class="hljs-attr">compressionLevel</span>=<span class="hljs-string">"0"</span> <span class="hljs-attr">max</span>=<span class="hljs-string">"10"</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">RollingFile</span>></span>
<span class="hljs-tag"><<span class="hljs-name">RollingFile</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"RollingFileWarn"</span> <span class="hljs-attr">fileName</span>=<span class="hljs-string">"${log_path}/warn.log"</span>
<span class="hljs-attr">filePattern</span>=<span class="hljs-string">"${log_path}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log.gz"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Filters</span>></span>
<span class="hljs-tag"><<span class="hljs-name">ThresholdFilter</span> <span class="hljs-attr">level</span>=<span class="hljs-string">"WARN"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">ThresholdFilter</span> <span class="hljs-attr">level</span>=<span class="hljs-string">"ERROR"</span> <span class="hljs-attr">onMatch</span>=<span class="hljs-string">"DENY"</span>
<span class="hljs-attr">onMismatch</span>=<span class="hljs-string">"NEUTRAL"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">Filters</span>></span>
<span class="hljs-tag"><<span class="hljs-name">PatternLayout</span> <span class="hljs-attr">pattern</span>=<span class="hljs-string">"[%d][%t][%p][%c:%L] %m%n"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">Policies</span>></span>
<span class="hljs-comment"><!-- 归档每天的文件 --></span>
<span class="hljs-tag"><<span class="hljs-name">TimeBasedTriggeringPolicy</span> <span class="hljs-attr">interval</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">modulate</span>=<span class="hljs-string">"true"</span> /></span>
<span class="hljs-comment"><!-- 限制单个文件大小 --></span>
<span class="hljs-tag"><<span class="hljs-name">SizeBasedTriggeringPolicy</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"2 MB"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">Policies</span>></span>
<span class="hljs-comment"><!-- 限制每天文件个数 --></span>
<span class="hljs-tag"><<span class="hljs-name">DefaultRolloverStrategy</span> <span class="hljs-attr">compressionLevel</span>=<span class="hljs-string">"0"</span> <span class="hljs-attr">max</span>=<span class="hljs-string">"10"</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">RollingFile</span>></span>
<span class="hljs-tag"><<span class="hljs-name">RollingFile</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"RollingFileError"</span> <span class="hljs-attr">fileName</span>=<span class="hljs-string">"${log_path}/error.log"</span>
<span class="hljs-attr">filePattern</span>=<span class="hljs-string">"${log_path}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log.gz"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">ThresholdFilter</span> <span class="hljs-attr">level</span>=<span class="hljs-string">"ERROR"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">PatternLayout</span> <span class="hljs-attr">pattern</span>=<span class="hljs-string">"[%d][%t][%p][%c:%L] %m%n"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">Policies</span>></span>
<span class="hljs-comment"><!-- 归档每天的文件 --></span>
<span class="hljs-tag"><<span class="hljs-name">TimeBasedTriggeringPolicy</span> <span class="hljs-attr">interval</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">modulate</span>=<span class="hljs-string">"true"</span> /></span>
<span class="hljs-comment"><!-- 限制单个文件大小 --></span>
<span class="hljs-tag"><<span class="hljs-name">SizeBasedTriggeringPolicy</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"2 MB"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">Policies</span>></span>
<span class="hljs-comment"><!-- 限制每天文件个数 --></span>
<span class="hljs-tag"><<span class="hljs-name">DefaultRolloverStrategy</span> <span class="hljs-attr">compressionLevel</span>=<span class="hljs-string">"0"</span> <span class="hljs-attr">max</span>=<span class="hljs-string">"10"</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">RollingFile</span>></span>
<span class="hljs-tag"></<span class="hljs-name">appenders</span>></span>
<span class="hljs-tag"><<span class="hljs-name">loggers</span>></span>
<span class="hljs-tag"><<span class="hljs-name">root</span> <span class="hljs-attr">level</span>=<span class="hljs-string">"info"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">appender-ref</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"Console"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">appender-ref</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"RollingFileInfo"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">appender-ref</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"RollingFileWarn"</span> /></span>
<span class="hljs-tag"><<span class="hljs-name">appender-ref</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">"RollingFileError"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">root</span>></span>
<span class="hljs-tag"></<span class="hljs-name">loggers</span>></span>
</configuration>
- 控制器代码:
package com.hansonwang99.controller;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
("/testlogging")
public class LoggingTestController {
private final Logger logger = LogManager.getLogger(this.getClass());
("/hello")
public String hello() {
for(int i=0;i<10_0000;i++){
logger.info(“info execute index method”);
logger.warn(“warn execute index method”);
logger.error(“error execute index method”);
}
return “My First SpringBoot Application”;
}
}
- 运行结果
日志会根据不同的级别存储在不同的文件,当日志文件大小超过2M以后会分多个文件压缩存储,生产环境的日志文件大小建议调整为20-50MB。
后记
作者更多的SpringBt实践文章在此:
</div>
<div class="copyright-outer-line">
<div class="yq-blog-sem-remove copyright-notice">
版权声明:本文内容由互联网用户自发贡献,版权归作者所有,本社区不拥有所有权,也不承担相关法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:<a href="mailto:yqgroup@service.aliyun.com">yqgroup@service.aliyun.com</a>
进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
</div>
</div>
<div class="yq-line"></div>
<div class="yq-blog-comment yq-blog-sem-remove" data-async-load="true" data-type="article" data-pid="580120" data-p="1">
<h3 class="title-info">网友评论</h3>
<section class="comments-box clearfix">
<form accept-charset="UTF-8" action="/comments" method="POST" data-remote="true" data-target="#comments" class="js-comment-create">
<input type="hidden" name="type" value="article">
<input type="hidden" name="yunqi_csrf" value="5FBARN3VIR">
<input type="hidden" name="isCheck" value="1">
<input type="hidden" name="pid" value="580120">
<div class="form-group">
<div class="editor">
<div class="editor-container">
<div class="editor-actions">
<a href="https://account.aliyun.com/login/login.htm?from_type=yqclub&oauth_callback=https%3A%2F%2Fyq.aliyun.com%2Farticles%2F580120%3Fdo%3Dlogin">登录</a><span>后评论</span>
</div><!-- /.editor-actions -->
<div class="computed-count unlogin-count">
<span class="font-count">0</span>/500
</div>
<textarea name="content" rows="4" maxlength="500" class="form-control js-mention js-auto-expand editor-content" style="height: 82px" id="comment" placeholder="写下你的评论…" required=""></textarea>
</div><!-- /.editor-container -->
</div><!-- /.editor -->
</div>
<div class="form-group text-right">
<div class="comment_button comment_new_button" data-toggle="modal" name="showLoginBtn">评论
</div>
</div>
</form>
<div class="media-list comments" id="comments">
codesheep 赞同
<div class="actions clearfix">
<a href="#modal-login" title="赞" class="btn btn-link btn-sm action" data-toggle="modal" name="showLoginBtn">
<span class="glyphicon glyphicon-thumbs-up icon-zan"></span>
1
</a>
<span class="sep"></span>
<a href="#modal-login" title="评论" class="btn btn-link btn-sm action" data-toggle="modal" name="showLoginBtn">
<span class="glyphicon glyphicon-comment icon-pinglun"></span>
<span id="sub-comments-count-91177873762667606">1</span>
</a>
</div>
<div class="sub-comments-box" id="sub-comments-box-91177873762667606">
<div class="sub-comments media-list" id="comment-91177873762667606-sub">
<div class="content unsafe">
<p>谢谢你的支持呀</p>
</div>
<div class="actions clearfix">
<a href="#modal-login" title="赞" class="btn btn-link btn-sm action" data-toggle="modal" name="showLoginBtn">
<span class="glyphicon glyphicon-thumbs-up icon-zan"></span>
0
</a>
<button class="btn btn-link btn-sm action" onclick="$('#sub-comment-91222240707725107').toggle().find('textarea').focusend()"><span class="glyphicon glyphicon-comment icon-pinglun "></span></button>
</div>
<form id="sub-comment-91222240707725107" class="js-active-on-valid js-comment-create" style="display:none" action="/comments/91177873762667606/subcomments/" method="POST" data-remote="true" data-target="#comment-91177873762667606-sub" data-done="$('#sub-comments-count-91177873762667606').inc();$(this).hide();$.scrollTo($r)">
<input type="hidden" name="isCheck" value="1">
<input type="hidden" name="yunqi_csrf" value="5FBARN3VIR">
<div class="form-group">
<textarea name="content" rows="1" class="form-control js-mention js-auto-expand" required="">@codesheep </textarea>
</div>
<div class="form-group text-right">
<button type="reset" class="btn btn-default btn-sm comment_cancel_button" onclick="$(this.form).hide()">取消</button>
<a href="#modal-login" class="btn btn-default unlogin_comment_button" data-toggle="modal" name="showLoginBtn">评论</a>
</div>
</form>
<div class="yq-line"></div>
<div class="yq-blog-related-articles">
<h3 class="title-info">相关文章</h3>
<div class="related-articles-content">
<div class="item-uninclude-img">
<a href="/articles/613797" target="_blank" class="alllink">
</a>
<div class="item-title">
Spring Boot Admin 2.0开箱体验
</div>
<div class="item-info">
<a href="/users/rd4tb24sejyqy" target="_blank" class="item-author">codesheep<img src="https://yqfile.alicdn.com/8d41f5de338fc9698298b8a6adacc4e8.png" alt=""></a>
<span class="item-time icon-shijian1">2018-07-18 08:43:21</span>
<span class="item-watch icon-View">浏览2558</span>
</div>
</div>
<div class="item-uninclude-img">
<a href="/articles/689458" target="_blank" class="alllink">
</a>
<div class="item-title">
Spring Boot系列实战文章合集(附源码)
</div>
<div class="item-info">
<a href="/users/rd4tb24sejyqy" target="_blank" class="item-author">codesheep<img src="https://yqfile.alicdn.com/8d41f5de338fc9698298b8a6adacc4e8.png" alt=""></a>
<span class="item-time icon-shijian1">2019-01-31 07:48:27</span>
<span class="item-watch icon-View">浏览690</span>
</div>
</div>
<div class="item-uninclude-img">
<a href="/articles/683603" target="_blank" class="alllink">
</a>
<div class="item-title">
程序羊的2018年终总(gen)结(feng)
</div>
<div class="item-info">
<a href="/users/rd4tb24sejyqy" target="_blank" class="item-author">codesheep<img src="https://yqfile.alicdn.com/8d41f5de338fc9698298b8a6adacc4e8.png" alt=""></a>
<span class="item-time icon-shijian1">2018-12-31 08:15:49</span>
<span class="item-watch icon-View">浏览812</span>
</div>
</div>
<div class="item-uninclude-img">
<a href="/articles/650809" target="_blank" class="alllink">
</a>
<div class="item-title">
两年摸爬滚打 Spring Boot,总结了这 16 条最佳实践
</div>
<div class="item-info">
<a href="/users/o56geandm2j2o" target="_blank" class="item-author">java填坑路</a>
<span class="item-time icon-shijian1">2018-10-10 16:47:32</span>
<span class="item-watch icon-View">浏览16392</span>
</div>
</div>
<div class="item-uninclude-img">
<a href="/articles/681582" target="_blank" class="alllink">
</a>
<div class="item-title">
Java架构师必会的技能(你都会了吗?)
</div>
<div class="item-info">
<a href="/users/o56geandm2j2o" target="_blank" class="item-author">java填坑路</a>
<span class="item-time icon-shijian1">2018-04-29 19:13:14</span>
<span class="item-watch icon-View">浏览1201</span>
</div>
</div>
</div>
<div class="load-more">下拉加载更多</div>
</div>
</div>