配置简化开发阶段日志输出布局

介绍了如何通过简化配置以解决开发阶段日志输出布局过长导致的不易查看的问题, 提供了一种极简的配置及一种适中的配置.

目录
[隐藏]

现在的很多应用默认情况下就带了很多的日志输出, 比如下面的 java spring-boot 框架启动时的日志:

{spring.web.resources.chain.cache=false, spring.web.resources.cache.period=0}

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.0)

2020-11-28 10:54:18.418  INFO 16144 --- [  restartedMain] n.x.sample.boot.basicweb.AppApplication  : Starting AppApplication using Java 11.0.8 on DESKTOP-CGD1N1Q with PID 16144 (C:\dev\proj\my\code-sample\be\java\fw\spring-boot\basic-web\target\classes started by xiaog in C:\dev\proj\my\code-sample\be\java\fw\spring-boot\basic-web)
2020-11-28 10:54:18.423  INFO 16144 --- [  restartedMain] n.x.sample.boot.basicweb.AppApplication  : No active profile set, falling back to default profiles: default
2020-11-28 10:54:18.453  INFO 16144 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2020-11-28 10:54:18.453  INFO 16144 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2020-11-28 10:54:19.024  INFO 16144 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-11-28 10:54:19.031  INFO 16144 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-11-28 10:54:19.032  INFO 16144 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.39]
2020-11-28 10:54:19.096  INFO 16144 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-11-28 10:54:19.098  INFO 16144 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 644 ms
2020-11-28 10:54:19.208  INFO 16144 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-11-28 10:54:19.254  INFO 16144 --- [  restartedMain] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page: class path resource [static/index.html]
2020-11-28 10:54:19.314  INFO 16144 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2020-11-28 10:54:19.337  INFO 16144 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-11-28 10:54:19.346  INFO 16144 --- [  restartedMain] n.x.sample.boot.basicweb.AppApplication  : Started AppApplication in 1.216 seconds (JVM running for 1.887)

日志信息非常丰富当然是有助于我们理解应用运行的各个方面, 但经常地, 我们也不难发现一些不方便的地方, 比如就以上述的输出为例, 前面一大堆的 布局(layout) 相关的输出就极为冗长, 而真正关心的信息却被挤在了后面, 如果你的显示屏不够宽, 这些关键的信息常常反而看不到, 需要横向滚动, 非常繁琐.

下面将介绍一种极简的日志布局方案, 如下所示:

{spring.web.resources.chain.cache=false, spring.web.resources.cache.period=0}

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.0)

49:20 Starting AppApplication using Java 11.0.8 on DESKTOP-CGD1N1Q with PID 11800 (C:\dev\proj\my\code-sample\be\java\fw\spring-boot\basic-web\target\classes started by xiaog in C:\dev\proj\my\code-sample\be\java\fw\spring-boot\basic-web)
49:20 No active profile set, falling back to default profiles: default
49:20 Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
49:20 For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
49:20 Tomcat initialized with port(s): 8080 (http)
49:21 Starting service [Tomcat]
49:21 Starting Servlet engine: [Apache Tomcat/9.0.39]
49:21 Initializing Spring embedded WebApplicationContext
49:21 Root WebApplicationContext: initialization completed in 636 ms
49:21 Initializing ExecutorService 'applicationTaskExecutor'
49:21 Adding welcome page: class path resource [static/index.html]
49:21 LiveReload server is running on port 35729
49:21 Tomcat started on port(s): 8080 (http) with context path ''
49:21 Started AppApplication in 1.219 seconds (JVM running for 1.945)

可以看到, 仅仅输出了一个时间(分别是分钟数和秒数, 小时, 毫秒什么的都省略了), 然后就是关键的日志信息, 非常简洁, 一目了然, 基本不需要各种拓宽或横向拖动来显示.

下面说说怎么配置以达到上述效果.

日志的缺省布局

先分析下缺省布局的情况, 看看哪些是没有必要可以省略的信息.

当没有任何配置的情况下, 使用的是一个缺省的布局, 这个通常来说是面向生产级别的一个布局配置, 以下面的一条信息为例:

2020-11-28 10:54:18.418  INFO 16144 --- [  restartedMain] n.x.sample.boot.basicweb.AppApplication  : Starting AppApplication using Java 11.0.8 on DESKTOP-CGD1N1Q with PID 16144 (C:\dev\proj\my\code-sample\be\java\fw\spring-boot\basic-web\target\classes started by xiaog in C:\dev\proj\my\code-sample\be\java\fw\spring-boot\basic-web)

日志非常长, 先是一个很长的 时间, 年月日时分秒以及毫秒, 可是对于开发阶段来说, 年月日基本没用, 绝大部分情况就是当天, 难不成还跨天调试不成? 这种情况肯定是很少的.

甚至来说, 小时都是不必要的, 毫秒如果不是需要特别精确的情况, 通常也是没啥用的, 所以光是时间方面就可以大幅地简化其输出, 而不会对我们开发阶段查看日志造成多大影响.

其次, INFO 这块属于 日志级别, 其它的还有诸如 ERROR, WARN 之类的等等, 通常这个级别区不区分关系也不大, 因此也可以省略.

接下来的一个数字 16144, 这是个 进程 ID(PID), 这个作用也不大, 反正至少对于我来说, 我几乎从未怎么关注过这个信息.

接下来的 [ restartedMain] 这个是 线程名称, 这个几乎在多数情况下也用处不大, 通常也可以省略.

如果你调试多线程情况就另说, 或许可以起到一些帮助.

接下来的 n.x.sample.boot.basicweb.AppApplication类名简化的包名, 虽然包名已经是简化的, 但无奈现在很多框架包括我们自己的工程, 包的层次都是蛮多的, 所以即便是简化的, 也通常也还蛮长的, 加上类名, 整个长度通常也还是非常可观.

这些信息怎么说呢, 看你自己的需要, 你也许不需要这些类和包名, 也许需要, 有时候, 必须承认它们还是有点用的, 至少可以让我们知道, 日志是在哪里打印出来的. 所以是否保留这个信息就看你自己的决定了.

后面除了极简的配置外, 还将给出一个适中的配置, 可以作为参考.

在以上的信息输出完之后, 才是我们最关心的日志信息了, 而这个最关键的信息常常被挤到看不到, 则是由于前面的布局相关的信息实在是太长了.

日志布局极简配置

为输出前上述极简的布局, 可以在你的项目的开发环境的配置文件比如 application-dev.properties 中这样去配置:

logging.pattern.console=%date{mm:ss} %message%n

注意: 请配置在开发环境中, 在测试及生产环境就不建议这样去配置了. 关于 spring-boot 的 分环境配置profile 机制, 如不熟悉请自行查阅网络了解.

在以上配置中, %date 表示时间, {mm:ss} 表示仅输出 分钟 和 秒; %message 这个是关键的日志信息; 最后的 %n 是换行.

在上述配置下, 就能输出开头那种极简的风格了:

49:20 Starting AppApplication using Java 11.0.8 on DESKTOP-CGD1N1Q with PID 11800 (C:\dev\proj\my\code-sample\be\java\fw\spring-boot\basic-web\target\classes started by xiaog in C:\dev\proj\my\code-sample\be\java\fw\spring-boot\basic-web)

一个简单的时间, 然后就是日志信息, 没有其它太多的不实用的信息.

日志布局适中配置

当然有些人可能觉得上述配置也太简陋了, 那么下面是一个较为适中一点的配置:

logging.pattern.console=%date{HH:mm:ss} %logger{0}.%method - %message%n

上述配置中, 加上了小时数, 这样看上去更加符合我们的习惯; 另外, 类名(%logger{0}) 也同样输出了, 但忽略了包名; 还有一个改进是增加输出了 方法名(%method), 这样能更清楚知道日志是哪里打印出来的, 缺省的情况是没有输出这个的.

最终的输出效果如下:

{spring.web.resources.chain.cache=false, spring.web.resources.cache.period=0}

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.0)

12:13:12 AppApplication.logStarting - Starting AppApplication using Java 11.0.8 on DESKTOP-CGD1N1Q with PID 20788 (C:\dev\proj\my\code-sample\be\java\fw\spring-boot\basic-web\target\classes started by xiaog in C:\dev\proj\my\code-sample\be\java\fw\spring-boot\basic-web)
12:13:12 AppApplication.logStartupProfileInfo - No active profile set, falling back to default profiles: default
12:13:12 DevToolsPropertyDefaultsPostProcessor.logTo - Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
12:13:12 DevToolsPropertyDefaultsPostProcessor.logTo - For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
12:13:13 TomcatWebServer.initialize - Tomcat initialized with port(s): 8080 (http)
12:13:13 StandardService.log - Starting service [Tomcat]
12:13:13 StandardEngine.log - Starting Servlet engine: [Apache Tomcat/9.0.39]
12:13:13 [/].log - Initializing Spring embedded WebApplicationContext
12:13:13 ServletWebServerApplicationContext.prepareWebApplicationContext - Root WebApplicationContext: initialization completed in 653 ms
12:13:13 ThreadPoolTaskExecutor.initialize - Initializing ExecutorService 'applicationTaskExecutor'
12:13:13 WelcomePageHandlerMapping.<init> - Adding welcome page: class path resource [static/index.html]
12:13:13 OptionalLiveReloadServer.startServer - LiveReload server is running on port 35729
12:13:13 TomcatWebServer.start - Tomcat started on port(s): 8080 (http) with context path ''
12:13:13 AppApplication.logStarted - Started AppApplication in 1.248 seconds (JVM running for 1.921)

以上输出比缺省要简洁, 但比起极简风格又多了一些输出, 具体的取舍就看你自己的需要了.

日志布局更多配置参考

最后, 如果你需要更加详细更多的配置, 请参考: https://logback.qos.ch/manual/layouts.html, 里面有完整的配置项介绍.

注: spring-boot 默认使用的日志框架是 logback, 所以上面给的是 logback 的参考, 如果你使用的是其它日志框架, 请参考相应的框架说明.

当然, 很多日志框架的配置是大同小异的.

你可以多配置几种风格, 一次启用一种, 然后试试自己适合喜欢哪种风格; 同时, 保留的其它几种风格可以在你有需要时进行切换.

关于配置简化开发阶段日志输出布局的介绍就到这里.