Spring Boot中Logback无法读取git-commit-id插件生成的git.properties
已配置git-commit-id-maven-plugin生成git.properties文件,且通过自定义PropertySourcesPlaceholderConfigurer能在控制器中用@Value注解获取到属性值,但在logback-spring.xml中尝试读取git.commit.id.abbrev时,始终显示默认值unknown,而spring.application.name和application.properties中的project.version均可正常读取。
相关配置
git-commit-id-maven-plugin配置
<plugin> <groupId>io.github.git-commit-id</groupId> <artifactId>git-commit-id-maven-plugin</artifactId> <version>6.0.0</version> <executions> <execution> <id>get-the-git-infos</id> <goals> <goal>revision</goal> </goals> <phase>initialize</phase> </execution> </executions> <configuration> <generateGitPropertiesFile>true</generateGitPropertiesFile> <includeOnlyProperties> <generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename> <includeOnlyProperty>^git.build.(time|version)$</includeOnlyProperty> <includeOnlyProperty>^git.commit.id.(abbrev|full)$</includeOnlyProperty> <includeOnlyProperty>^git.dirty$</includeOnlyProperty> </includeOnlyProperties> <commitIdGenerationMode>full</commitIdGenerationMode> </configuration> </plugin>
生成的git.properties
#Generated by Git-Commit-Id-Plugin git.build.time=2023-07-13T14\:04\:21+0200 git.build.version=5.0-SNAPSHOT git.commit.id.abbrev=753455c git.commit.id.full=753455c7ae51f231cefda280e0508feeb3655f59 git.dirty=true
自定义PropertySourceConfig
package com.my.app.metrics; import org.springframework.context.annotation.Bean; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Component; /** * Generates beans with access to properties required for metrics */ @Component public class PropertySourceConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { PropertySourcesPlaceholderConfigurer propsConfig = new PropertySourcesPlaceholderConfigurer(); propsConfig.setLocation(new ClassPathResource("git.properties")); propsConfig.setIgnoreResourceNotFound(true); propsConfig.setIgnoreUnresolvablePlaceholders(true); return propsConfig; } }
logback-spring.xml配置
<configuration> <springProperty scope="context" name="applicationName" source="spring.application.name" defaultValue="unknown" /> <springProperty scope="context" name="applicationVersion" source="project.version" defaultValue="unknown" /> <springProperty scope="context" name="commitId" source="git.commit.id.abbrev" defaultValue="unknown" /> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="net.logstash.logback.encoder.LogstashEncoder"> </encoder> </appender> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> </configuration>
问题原因
你的猜测完全正确:Logback的初始化时机早于PropertySourcesPlaceholderConfigurer加载git.properties的时机。Spring Boot启动时会优先初始化日志系统,此时自定义的属性源还未被加载到Spring环境中,因此Logback无法获取到git相关的属性值。
修复方案
方案一:移除自定义配置,依赖Spring Boot自动加载
Spring Boot默认会自动扫描并加载classpath下的git.properties文件,无需手动配置PropertySourcesPlaceholderConfigurer。直接删除PropertySourceConfig类即可,Spring会在更早的启动阶段加载这些属性,Logback就能正常读取git.commit.id.abbrev。
方案二:在Logback中直接加载git.properties
如果需要保留自定义配置,可以让Logback直接读取git.properties文件,不依赖Spring的属性源:
<configuration> <!-- 直接加载git.properties文件 --> <property resource="git.properties" /> <springProperty scope="context" name="applicationName" source="spring.application.name" defaultValue="unknown" /> <springProperty scope="context" name="applicationVersion" source="project.version" defaultValue="unknown" /> <!-- 直接使用git.properties中的属性,指定默认值 --> <property name="commitId" value="${git.commit.id.abbrev:-unknown}" /> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="net.logstash.logback.encoder.LogstashEncoder"> </encoder> </appender> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> </configuration>
方案三:调整属性加载时机(不推荐)
虽然你已经将PropertySourcesPlaceholderConfigurer定义为静态Bean,但由于日志初始化在Spring上下文刷新之前,这种方式依然无法保证属性提前加载。因此更推荐使用前两种方案。
关于CloudWatch的建议
将Git信息作为单独指标推送到CloudWatch是个很好的补充方案,但和日志中包含这些信息并不冲突:
- 日志中携带commit ID可以快速将日志与代码版本关联,方便问题排查;
- 作为指标推送则可以追踪部署版本的分布情况,监控不同版本的运行状态。
两者可以同时实施,提升可观测性。
内容的提问来源于stack exchange,提问作者mal

