微服务架构项目中的日志输出配置

详细的配置步骤如下。

第一步,引入 logstash-logback-encoder 依赖。

依次打开 newbee-mall-cloud-user-webnewbee-mall-cloud-recommend-webnewbee-mall-cloud-order-webnewbee-mall-cloud-shop-cart-webnewbee-mall-cloud-goods-web 5个微服务实例工程中的 pom.xml 文件,在 dependencies 节点下新增 logstash-logback-encoder 的依赖项,配置代码如下:

<dependency>
  <groupId>net.logstash.logback</groupId>
  <artifactId>logstash-logback-encoder</artifactId>
  <version>7.0.1</version>
</dependency>

第二步,添加 Logback 日志配置文件。

依次打开 newbee-mall-cloud-user-webnewbee-mall-cloud-recommend-webnewbee-mall-cloud-order-webnewbee-mall-cloud-shop-cart-webnewbee-mall-cloud-goods-web 5 个微服务实例工程,在 src/main/resources 目录下创建 logback.xml 配置文件,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>

    <!-- 应用名称 -->
    <property name="APP_NAME" value="newbee-mall-cloud-order-service-log"/>
    <contextName>${APP_NAME}</contextName>

    <!-- 控制台日志样式 -->
    <property name="CONSOLE_LOG_PATTERN" value="%clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr(${LOG_LEVEL_PATTERN:-$p}) %clr(${PID:- }) {magenta} %clr(%15.15t){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}"/>

    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <!-- 日志输出编码 -->
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- 输出到 Logstash 开启的 TCP 端口 -->
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <!-- 可以配置 Logstash 日志接收端口 -->
        <destination>10.168.110.57:4560</destination>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="LOGSTASH"/>
    </root>
</configuration>

配置信息基本一致,只是 APP_NAME 参数有差异。好的,“管子” 搭好了,接下来启动项目测试一下,结果如图 13-1 所示。

image 2025 04 28 15 27 16 741
Figure 1. 图13-1 启动结果

代码运行日志中出现错误,错误信息如下:

23:45:46,970 |-ERROR in ch.qos.logback.classic.jcan.action.
ContextNameAction - Failed to rename context
[newbee-mall-cloud-order-service-log] as [nacos]
java.lang.IllegalStateException: Context has been already given a name
	at java.lang.IllegalStateException: Context has been already given a name

报错的原因不复杂,是依赖冲突导致的。

Spring Boot 框架中已经集成了日志框架 Logback,而项目依赖 nacos-client 中也配置了 Logbacknacos-client 中的 Logback 加载要优先项目自身的 Logback 框架加载),在一个项目中,context_name 只能定义一次。所以,在项目启动时,nacos-client 中的 Logback 先加载完成后,再加载项目本身的 Logback 就出现了冲突。

这个报错并不影响使用,但是最好处理一下,需要在启动类中增加如下代码:

System.setProperty("nacos.logging.default.config.enabled", "false");

只加载自定义的 Logback 配置,不使用 nacos-client 依赖中的配置,这样就不会造成冲突了。因此,需要在 newbee-mall-cloud-user-webnewbee-mall-cloud-recommend-webnewbee-mall-cloud-order-webnewbee-mall-cloud-shop-cart-webnewbee-mall-cloud-goods-web 5个微服务实例工程下的启动类中添加上面这行代码。

第三步,新增日志输出的测试代码。

这里主要为了模拟平时 error 日志的输出和测试在 Kibana 中查询日志,在 newbee-mall-cloud-goods-web 工程的 NewBeeMallGoodsController 类中新增如下代码:

@GetMapping("/test1")
public Result<String> test1() throws BindException {
    throw new BindException(1,"BindException");
}

@GetMapping("/test2")
public Result<String> test2() throws NewBeeMallException {
    NewBeeMallException.fail("NewBeeMallException");
    return ResultGenerator.genSuccessResult("test2");
}

@GetMapping("/test3")
public Result<String> test3() throws Exception {
    int i=1/0;
    return ResultGenerator.genSuccessResult("test2");
}

因为已经在全局异常处理类中配置了异常的拦截和日志输出,所以在浏览器的地址栏中访问上述代码中的网址,就会直接输出 3 条 error 级别的测试日志。