使用Spring Boot日志框架在已有的微服务代码中添加日志功能

  引言:我们需要在已有的微服务代码中添加日志功能,用于输出需要关注的内容,这是最平常的技术需求了。由于我们的微服务代码是基于SpringBoot开发的,那么问题就转换为如何在Spring Boot应用程序中输出相应的日志。

  在传统Java应用程序中,我们一般会使用类似Log4j这样的日志框架来输出日志,而不是直接在代码中通过System.out.println()来输出日志。为什么要这么做呢?原因有两点。其一,我们希望日志能输出到文件中,而不是输出到应用程序的控制台中,这样更加容易收集和分析。其二,我们可以通过异步多线程的方式,将日志输出到文件中,这样既不会影响主线程,可以提高应用程序的吞吐率,也是一种节省性能开销的方法。直接将内容打印到控制台中,这种做法比较粗暴,不是业界所推荐的做法。
  这样一来,我们最终要解决的问题就非常清楚了,那就是如何在Spring Boot中添加日志框架。幸运的是,Spring Boot自带了一款名为Spring Boot Logging的插件(在Spring Boot中,称插件为Starter),它已经为我们提供了日志功能。

1 使用Spring Boot Logging插件

  Spring Boot使用Apache开源项目Commons Logging作为内部的日志框架,它是一个日志接口,在实际应用中,我们需要为该接口指定相应的日志实现。Spring Boot默认的日志实现是Java Util Logging,它是JDK自带的日志包,一般场景下很少会用到。此外,Spring Boot也提供了Log4J、Logback这类流行的日志实现,我们只需要添加简单的配置,就能开启对这些日志实现的支持。
  为了便于描述,我们将以上提到的“日志实现”统称为“日志框架”。
  大家可以通过以下网站,进一步学习这类日志框架。

  在Java应用程序中,日志一般分为以下5个级别。

  • ERROR:错误信息;
  • WARN:警告信息;
  • INFO:一般信息;
  • DEBUG:调试信息;
  • TRACE:跟踪信息。

  以上日志级别按照严重程度,从高往低排序,一般常用的三种日志级别是ERROR、INFO、DEBUG。Spring Boot Logging插件默认输出到INFO级别,也就是说,只包含ERROR、WARN、INFO,不包含DEBUG、TRACE。如果我们希望日志可以输出到DEBUG级别,则需在Spring Boot的application.properties文件中添加如下配置:

logging.level.root=DEBUG

  重新运行应用程序,我们就可在代码中看到DEBUG级别的日志了。
  以下是Spring Boot的应用程序代码片段,我们使用SLF4J类库输出日志,而不要使用具体的日志实现类库,比如Log4J。

package demo.msa;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...

@RestController
@SpringBootApplication
public class HelloApplication {

  private static Logger logger =LoggerFactory.getLogger(HelloApplication.class);

  public static void main(String[] args) {
    SpringApplication.run(HelloApplication.class, args);
  }

  @GetMapping("/hello")
  public String hello() {
    logger.debug("log..."); // 输出DEBUG级别的日志
    return "hello";
  }
}

  运行以上Spring Boot应用程序,会发现控制台中输出了大量INFO级别的日志,这些日志是由Spring Boot框架输出的。因为我们调整日志输出到DEBUG级别,而INFO级别在DRBUG级别之上,所以INFO级别的日志也会输出,但TRACE级别的日志不会输出。
  当我们打开浏览器,发送http://localhost:8080/hello请求时,可在控制台中看到我们想要输出的DEBUG级别日志。
  如果我们不想关注Spring Boot框架的日志,则可将日志级别统一设置为ERROR,此时只会输出ERROR级别的日志。随后,再将Spring Boot应用程序指定的包(应用程序所对应的包)设置为DEBUG级别的日志,此时我们看到的就只是指定包中的日志了。

logging.level.root=ERROR
logging.level.demo.msa=DEBUG

  上面的logging.level.root表示所有包,logging.level.demo.msa表示应用程序的指定包(demo.msa是包名)。以上配置可以理解为,整个应用程序的日志输出到ERROR级别,除了demo.msa包中的日志输出到DEBUG级别。这是一种“先禁止所有,再允许个别”的配置方法,这种配置方法在很多技术中都应用过。
  默认情况下日志框架会将日志输出到控制台中,我们需要在application.properties文件中添加如下配置,才能将日志输出到文件中:

logging.file=${user.home}/logs/hello.log

  其中,${user.home}表示当前用户目录(该变量由Spring Boot框架在运行时传入),后面的/logs/hello.log是相对于该目录的路径。大家可根据实际情况,设置所需的日志文件路径,以上仅为示例。
  重新运行应用程序,就能看到日志输出到指定路径下的文件中了。
  目前我们虽然可以将日志输出到文件中,但控制台中仍然会输出同样的日志,这不是我们最终想要的效果。我们希望的是日志全部输出到文件中,控制台中不输出任何日志。也就是说,我们需要关闭控制台中的输出。通过以上的尝试,我们不难发现,仅通过修改Spring Boot的配置,貌似是无法做到的。
  下面我们不妨考虑集成经典的Log4J日志框架,看看能否实现我们的需求。

2 集成Log4J日志框架

  Spring Boot Logging默认集成了Logback,我们只需提供Logback的配置文件就能开启Logback日志功能,但我们现在想要尝试的是自己熟知的Log4J,而不是比较新潮的Logback。毫不犹豫,现在我们就来开启对Log4J的支持。通过学习Spring Boot的官方文档与示例代码,我们了解到,只需在pom.xml文件中添加如下Maven配置,就能在Spring Boot中集成Log4J。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</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>

  在第一段dependency配置中,我们排除掉spring-boot-starter-logging依赖是因为要去掉默认集成的Logback日志功能。在第二段dependency配置中,我们自行添加了spring-boot-starter- log4j2依赖,它是Spring Boot所提供的Log4J插件,此时使用的是Log4J的2.x版本。
  当完成了Maven依赖配置以后,我们接下来需要在源码中的resources目录下添加log4j2.xml文件,其内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appenders>
    <File name="file" fileName="${sys:user.home}/logs/hello.log">
      <PatternLayout pattern="%d{HH:mm:ss,SSS} %p %c (%L) - %m%n"/>
    </File>
  </appenders>
  <loggers>
    <root level="ERROR">
      <appender-ref ref="file"/>
    </root>
    <logger name="demo.msa" level="DEBUG"/>
  </loggers>
</configuration>

  log4j2.xml配置文件分为两大部分,即appenders与loggers。在appenders中,我们添加了一个File类型的appenders,表示日志以文件的方式进行输出,该文件路径基于根目录${sys:user.home},即当前用户目录(该变量由Log4J框架在运行时传入)。此外,还需指定PatternLayout为日志输出格式。在loggers中,我们先后添加了两段配置,第一段的root表示将所有包中的日志输出到ERROR级别,第二段的logger表示将指定包demo.msa中的日志输出到DEBUG级别。很明显,这段配置与之前在Spring Boot中配置的意义相同。
  通过以上配置,可将Log4J集成到Spring Boot应用中。
  重新运行应用程序,日志不再输出到控制台中,而是全部输出到指定路径下的文件中了。
  大家如果想了解更为详尽的Spring Boot日志特性,可参考它的官方技术文档。

  目前,虽然日志已经成功输出到文件中,但是我们的微服务是以Docker容器的方式来运行的,此时输出的日志文件仍然和应用程序在一个Docker容器中,我们得想办法将日志文件输出到Docker容器外。也就是说,需要将数据与程序相分离,以便后续更加方便地获取并分析日志内容。

3 将日志输出到Docker容器外

  最容易想到的办法就是,通过Docker数据卷的方式,将文件路径挂载到Docker容器上,这样日志文件就自然与Docker文件分离了,就像下面这样启动Docker容器。

docker run -v ~/logs:~/logs hello

  这样一来,我们可随时在宿主机上查看Docker容器内部的日志了。但是回过头想想,却不难发现,其实完全不需要将日志输出到文件中,因为即便将日志输出到控制台中,我们也能随时通过docker logs的方式来获取日志内容,将日志输出到文件似乎有些多余了,还占用了磁盘空间。
  那我们现在做的事情是否有意义呢?感兴趣的读者不妨到《架构探险:轻量级微服务架构(下册)》一书中探索详情~
  本文选自《架构探险:轻量级微服务架构(下册)》,点此链接可在博文视点官网查看此书。
                 
  想及时获得更多精彩文章,可在微信中搜索“博文视点”或者扫描下方二维码并关注。
                    

时间: 2024-08-17 15:03:21

使用Spring Boot日志框架在已有的微服务代码中添加日志功能的相关文章

JNI的native代码中打印日志到eclipse的logcat中

1 添加ndk对log支持 若需要添加ndk对log的支持,只需要通过以下2步即可实现. 1.1 修改Android.mk 如生成的库文件是".so文件",则在Android.mk中添加如下内容: LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog 如生成的库文件是".a文件",则在Android.mk中添加如下内容: LOCAL_LDLIBS:=-llog 1.2 在.c或.cpp文件中引用log头文件 添加如下内容: // 引入lo

向已存在的要素类中添加字段

在写AE程序的时候,一定要进行License的验证.如果是WinForm程序,可以向窗口上拖放一个ArcGIS License控件:如果是Console程序,可以添加ArcGIS License Checking代码 1)通过IFieldsEdit接口的AddField方法的函数 static void AddField_IFields(IFeatureClass pFC, string name) { IFields pFields = pFC.Fields; IFieldsEdit pFie

linux中Sed 正则替换代码中的日志开关、错误级别值修改、注释代码

背景:多个项目进行代码的日志打印级别统一替换时,如果文件庞大,数目多,一个个去做显然力不从心,得通过脚本,这种替换sed最适合不过了. 如题: I: 我想把:log_threshold =N; 替换为:log_threshold =1; 我想把:show_debug_errors=AnyWord; 替换为:show_debug_errors=false; II: error_reporting(E_ALL ^ E_NOTICE); 变: //error_reporting(E_ALL ^ E_N

将Spring Boot程序打包成docker镜像

写了这多关于平台云的文章,其实我的平台云还没有搭建起来,但是我最终的目标是将spring boot运行于平台云当中.   我所知道我目前要学习的东西有CoreOS+Docker--这是平台云的基石.后面打算部署Deis或者flynn作为平台云.   不管怎么说,spring boot应用最终作为一种微服务运行于docker容器之中的.最后负载均衡也好,数据库也好,都是让平台云去做.   1.写一个简单的spring boot的例子. 使用STS新建一个spring boot项目,添加一点代码(其

【spring boot】8.spring boot的日志框架logback使用

 在继续上一篇的Debug调试之后,把spring boot的日志框架使用情况逐步蚕食. 参考:http://tengj.top/2017/04/05/springbo 开篇之前,贴上完整application.properties日志相关配置   ============================================================================================= 简介:spring boot的默认日志框架Logback SL

深入学习微框架:Spring Boot

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以 及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. 多年以来,Spring IO平台饱受非议的一点就是大量的XML配置以及复杂的依赖管理.在去年的SpringOne 2GX会议上,Pivotal的CTO Adrian Co

使用 Spring Boot 快速构建 Spring 框架应用,PropertyPlaceholderConfigurer

Spring 框架对于很多 Java 开发人员来说都不陌生.自从 2002 年发布以来,Spring 框架已经成为企业应用开发领域非常流行的基础框架.有大量的企业应用基于 Spring 框架来开发.Spring 框架包含几十个不同的子项目,涵盖应用开发的不同方面.如此多的子项目和组件,一方面方便了开发人员的使用,另外一个方面也带来了使用方面的问题.每个子项目都有一定的学习曲线.开发人员需要了解这些子项目和组件的具体细节,才能知道如何把这些子项目整合起来形成一个完整的解决方案.在如何使用这些组件上

Spring Boot

一.Spring Boot介绍 Spring Boot是为了简化Spring应用的创建.运行.调试.部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置. 简单来说,它提供了一堆依赖打包,并已经按照使用习惯解决了依赖问题-习惯大于约定. Spring Boot默认使用tomcat作为服务器,使用logback提供日志记录. Spring Boot提供了一系列的依赖包,所以需要构建工具的支持:maven 或 gradle. 二.一个简单的springboot po

Spring Boot与Docker(二):使用Spring Boot和Docker构建微服务架构

本文讲的是Spring Boot与Docker(二):使用Spring Boot和Docker构建微服务架构,[编者的话]本篇是<使用Spring Boot和Docker构建微服务架构>系列的第二篇,本篇我们将会利用工具进行设置,深入探讨如何使用Docker工作,然后搭建我们的第一个容器.原文作者为3Pillar环球旗下美国Adbanced技术集团的总监Dan Greene,Dan有十八年的软件设计和开发经验,包括在电子商务.B2B集成.空间分析.SOA架构.大数据以及云计算等领域的软件产品架