背景:
线上部署的jar包(不管是直接运行jar包,还是通过容器运行的jar)有时出现问题时需要查看源代码,需要知道该jar包是从哪个分支、哪个commit、哪个时间打包的。 有了这些信息能更好辅助我们分析判断问题。 这里以gradle工程为例子,给出一种简单添加构建信息的例子。 go工程可以参看k8s的源码中的构建脚本
具体步骤
这里是一个springboot工程,使用gradle. 只有运行打包好的jar请求api才有信息,直接在IDE中启动时,请求时没有构建信息返回,因为这些信息读取的jar包中的资源文件。所以必须是jar启动的才行
1, 在build.gradle中添加如下内容
备注:内容简单,就不添加注释了,就是执行gradle bootJar进行打包时,将这些git-branch、git-commit、git-commit-time.
// 将Git信息和构建时间等元数据注入MANIFEST.MF文件manifest {attributes('Implementation-Title': project.name,'Implementation-Version': project.version,'Built-By': System.getProperty('user.name'),'Built-Time': new Date(),'Git-Branch': getGitBranch(),'Git-Commit': getGitCommit(),'Git-Commit-Time': getGitCommitTime())}
}// 获取当前分支名称
static def getGitBranch() {try {def branch = 'git rev-parse --abbrev-ref HEAD'.execute().text.trim()return branch ?: 'unknown'} catch (Exception e) {System.err.println("fail to get branch, errMsg:" + e.getMessage())return 'unknown'}
}// 获取当前提交的记录的commitId
static def getGitCommit() {try {def commit = 'git rev-parse HEAD'.execute().text.trim()return commit ?: 'unknown'} catch (Exception e) {System.err.println("fail to get commit id, errMsg:" + e.getMessage())return 'unknown'}
}// 获取当前Git提交的时间
static def getGitCommitTime() {try {def commitTime = 'git show -s --format=%ct HEAD'.execute().text.trim()return commitTime ? new Date(Long.parseLong(commitTime) * 1000L) : 'unknown'} catch (Exception e) {System.err.println("fail to get commit time, errMsg:" + e.getMessage())return 'unknown'}
}
2, 增加一个MyBuildInfo类
@Getter
@Accessors(fluent = true)
@FieldDefaults(level = AccessLevel.PRIVATE)
@JsonIgnoreProperties(ignoreUnknown = true)
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor
public class MyBuildInfo
{String gitBranch;String gitCommitId;String gitCommitTime;String builtTime;
}
3, 在service层提供构建信息
在对对应的service类方法中添加如下代码
static final String GIT_BRANCH = "Git-Branch";static final String GIT_COMMIT_ID = "Git-Commit";static final String GIT_COMMIT_TIME = "Git-Commit-Time";static final String BUILD_TIME = "Built-Time";@Overridepublic Response<MyBuildInfo> getBuildInfo(){String gitBranch = BuildUtils.getManifestAttribute(GIT_BRANCH);String gitCommitId = BuildUtils.getManifestAttribute(GIT_COMMIT_ID);String gitCommitTime = BuildUtils.getManifestAttribute(GIT_COMMIT_TIME);String builtTime = BuildUtils.getManifestAttribute(BUILD_TIME);gitBranch = StringUtils.isNoneBlank(gitBranch) ? gitBranch : UNKNOWN;gitCommitId = StringUtils.isNoneBlank(gitCommitId) ? gitCommitId : UNKNOWN;gitCommitTime = StringUtils.isNoneBlank(gitCommitTime) ? gitCommitTime : UNKNOWN;builtTime = StringUtils.isNoneBlank(builtTime) ? builtTime : UNKNOWN;MyBuildInfo buildInfo = new MyBuildInfo(gitBranch, gitCommitId, gitCommitTime, builtTime);// 这里的new Response(buildInfo, "buildInfo done");以每个具体项目为准,这里这是实例返回符合工程规范的resp格式信息return new Response(buildInfo, "buildInfo done");}
其中BuildUtils是读取jar中资源的文件的具体类
import lombok.extern.slf4j.Slf4j;import java.io.IOException;
import java.util.jar.Attributes;
import java.util.jar.Manifest;@Slf4j
public class BuildUtils
{public static String getManifestAttribute(String attributeName){try {Manifest manifest = new Manifest(BuildUtils.class.getResourceAsStream("/META-INF/MANIFEST.MF"));Attributes attributes = manifest.getMainAttributes();return attributes.getValue(attributeName);} catch (IOException e) {log.warn("fail to get info from manifest file, errMsg:{}", e.getMessage(), e);return "unknown";}}
}
jar包中资源文件实际是构建的这个文件
4, 在controller中暴露构建信息
在某个controller中添加可以查询构建信息的api。 其中@Operation是swagger的注解信息,如果没有使用swagger, 需要删除。
@Operation(summary = "查询具体构建信息")@GetMapping("/buildInfo")public Response<MyBuildInfo> getBuildInfo(){Response res = xxxService.getBuildInfo();return res;}