15.3.1 Đóng góp thông tin cho endpoint /info
Như bạn đã thấy trong phần 15.2.1, endpoint /info ban đầu trống và không có thông tin gì hữu ích. Nhưng bạn có thể dễ dàng thêm dữ liệu vào đó bằng cách tạo các thuộc tính được tiền tố bằng info.
Mặc dù việc thêm tiền tố info. vào các thuộc tính là cách rất dễ dàng để đưa dữ liệu tuỳ chỉnh vào endpoint /info, nhưng đó không phải là cách duy nhất. Spring Boot cung cấp một interface tên là InfoContributor cho phép bạn lập trình để thêm bất kỳ thông tin nào bạn muốn vào phản hồi của endpoint /info. Spring Boot thậm chí còn cung cấp sẵn một vài triển khai hữu ích của InfoContributor mà chắc chắn bạn sẽ thấy tiện lợi.
Hãy cùng xem cách bạn có thể viết InfoContributor của riêng mình để thêm thông tin tuỳ chỉnh vào endpoint /info.
TẠO MỘT INFOCONTRIBUTOR TUỲ CHỈNH
Giả sử bạn muốn thêm một vài thống kê đơn giản về Taco Cloud vào endpoint /info. Ví dụ, bạn muốn bao gồm thông tin về số lượng taco đã được tạo. Để làm điều đó, bạn có thể viết một lớp triển khai InfoContributor, inject nó với TacoRepository, sau đó công bố bất kỳ số liệu nào mà TacoRepository cung cấp dưới dạng thông tin cho endpoint /info. Danh sách dưới đây cho thấy bạn có thể triển khai contributor như thế nào.
Danh sách 15.3 Một triển khai tuỳ chỉnh của InfoContributor
package tacos.tacos;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.actuate.info.Info.Builder;
@Component
public class TacoCountInfoContributor implements InfoContributor {
private TacoRepository tacoRepo;
public TacoCountInfoContributor(TacoRepository tacoRepo) {
this.tacoRepo = tacoRepo;
}
@Override
public void contribute(Builder builder) {
long tacoCount = tacoRepo.count();
Map<String, Object> tacoMap = new HashMap<String, Object>();
tacoMap.put("count", tacoCount);
builder.withDetail("taco-stats", tacoMap);
}
}Bằng cách triển khai InfoContributor, TacoCountInfoContributor buộc phải triển khai phương thức contribute(). Phương thức này được truyền vào một đối tượng Builder mà trong đó contribute() gọi đến withDetail() để thêm chi tiết thông tin. Trong phần triển khai của bạn, bạn sử dụng TacoRepository bằng cách gọi phương thức count() của nó để xác định số lượng taco đã được tạo. Trong trường hợp cụ thể này, bạn đang làm việc với một reactive repository, vì vậy bạn cần gọi block() để lấy số lượng từ Mono<Long> trả về. Sau đó, bạn đưa số lượng này vào một Map, rồi truyền map đó cho builder với nhãn taco-stats. Kết quả của endpoint /info sẽ bao gồm số lượng đó, như minh hoạ dưới đây:
{
"taco-stats": {
"count": 44
}
}Như bạn thấy, một triển khai của InfoContributor có thể sử dụng bất kỳ cách nào cần thiết để đóng góp thông tin. Điều này trái ngược với việc chỉ đơn giản tiền tố một thuộc tính bằng info., vốn tuy đơn giản nhưng bị giới hạn ở các giá trị tĩnh.
CHÈN THÔNG TIN BUILD VÀO ENDPOINT /INFO
Spring Boot đi kèm với một vài triển khai InfoContributor tích hợp sẵn, tự động thêm thông tin vào kết quả của endpoint /info. Trong số đó có BuildInfoContributor, cung cấp thông tin từ file build của dự án vào kết quả /info. Thông tin cơ bản bao gồm phiên bản dự án, dấu thời gian build, máy và người dùng thực hiện build.
Để kích hoạt việc bao gồm thông tin build trong kết quả của endpoint /info, hãy thêm mục tiêu build-info vào phần executions của Spring Boot Maven Plugin như sau:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>Nếu bạn đang sử dụng Gradle để build dự án, bạn có thể đơn giản thêm dòng sau vào file build.gradle:
springBoot {
buildInfo()
}In either event, the build will produce a file named build-info.properties in the distributable JAR or WAR file that BuildInfoContributor will consume and contribute to the /info endpoint. The following snippet from the /info endpoint response shows the build information that’s contributed:
{
"build": {
"artifact": "tacocloud",
"name": "taco-cloud",
"time": "2021-08-08T23:55:16.379Z",
"version": "0.0.15-SNAPSHOT",
"group": "sia"
},
}Trong cả hai trường hợp, quá trình build sẽ tạo ra một file tên là build-info.properties trong file JAR hoặc WAR được phân phối, và BuildInfoContributor sẽ sử dụng file này để đóng góp thông tin vào endpoint /info. Đoạn trích dưới đây từ phản hồi của /info cho thấy thông tin build được đóng góp:
CÔNG BỐ THÔNG TIN GIT COMMIT
Giả sử dự án của bạn được lưu trữ trong Git để kiểm soát mã nguồn, bạn có thể muốn bao gồm thông tin Git commit trong endpoint /info. Để làm điều đó, bạn cần thêm plugin sau vào file pom.xml của dự án Maven:
<build>
<plugins>
...
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
</plugin>
</plugins>
</build>Nếu bạn đang sử dụng Gradle, đừng lo. Có một plugin tương đương để bạn thêm vào file build.gradle, như hiển thị dưới đây:
plugins {
id "com.gorylenko.gradle-git-properties" version "2.3.1"
}Cả hai plugin này về cơ bản đều làm cùng một việc: chúng tạo ra một artifact trong quá trình build tên là git.properties chứa toàn bộ metadata Git cho dự án. Một triển khai đặc biệt của InfoContributor sẽ phát hiện file đó khi chạy và công bố nội dung của nó như một phần của endpoint /info.
Tất nhiên, để tạo được file git.properties, dự án cần có metadata commit Git. Tức là nó phải là một bản clone từ repository Git hoặc là một repository Git cục bộ mới được khởi tạo với ít nhất một commit. Nếu không, các plugin trên sẽ gặp lỗi. Tuy nhiên, bạn có thể cấu hình chúng để bỏ qua việc thiếu metadata Git. Với plugin Maven, bạn thiết lập thuộc tính failOnNoGitDirectory thành false như sau:
<build>
<plugins>
...
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<configuration>
<failOnNoGitDirectory>false</failOnNoGitDirectory>
</configuration>
</plugin>
</plugins>
</build>Tương tự, bạn có thể thiết lập thuộc tính failOnNoGitDirectory trong Gradle bằng cách chỉ định dưới phần gitProperties như sau:
gitProperties {
failOnNoGitDirectory = false
}Ở dạng đơn giản nhất, thông tin Git được hiển thị trong endpoint /info bao gồm nhánh Git, mã hash commit và dấu thời gian mà ứng dụng được build từ đó, như minh hoạ dưới đây:
{
"git": {
"branch": "main",
"commit": {
"id": "df45505",
"time": "2021-08-08T21:51:12Z"
}
},
...
}Thông tin này khá chính xác trong việc mô tả trạng thái mã nguồn khi dự án được build. Nhưng bằng cách thiết lập thuộc tính management.info.git.mode thành full, bạn có thể lấy thông tin rất chi tiết về Git commit được sử dụng khi dự án được build, như hiển thị trong đoạn mã sau:
management:
info:
git:
mode: fullThe following listing shows a sample of what the full Git info might look like.
Danh sách 15.4 Thông tin Git đầy đủ được công bố qua endpoint /info
"git":{
"local":{
"branch":{
"ahead":"8",
"behind":"0"
}
},
"commit":{
"id":{
"describe-short":"df45505-dirty",
"abbrev":"df45505",
"full":"df455055daaf3b1347b0ad1d9dca4ebbc6067810",
"describe":"df45505-dirty"
},
"message":{
"short":"Apply chapter 18 edits",
"full":"Apply chapter 18 edits"
},
"user":{
"name":"Craig Walls",
"email":"craig@habuma.com"
},
"author":{
"time":"2021-08-08T15:51:12-0600"
},
"committer":{
"time":"2021-08-08T15:51:12-0600"
},
"time":"2021-08-08T21:51:12Z"
},
"branch":"master",
"build":{
"time":"2021-08-09T00:13:37Z",
"version":"0.0.15-SNAPSHOT",
"host":"Craigs-MacBook-Pro.local",
"user":{
"name":"Craig Walls",
"email":"craig@habuma.com"
}
},
"tags":"",
"total":{
"commit":{
"count":"196"
}
},
"closest":{
"tag":{
"commit":{
"count":""
},
"name":""
}
},
"remote":{
"origin":{
"url":"git@github.com:habuma/spring-in-action-6-samples.git"
}
},
"dirty":"true"
},Ngoài dấu thời gian và mã hash commit rút gọn, phiên bản đầy đủ bao gồm tên và email của người đã commit mã nguồn cũng như nội dung commit message và các thông tin khác, cho phép bạn xác định chính xác đoạn mã nào được sử dụng để build dự án. Thậm chí, bạn có thể thấy trường dirty trong danh sách 15.4 là true, cho biết có những thay đổi chưa được commit tồn tại trong thư mục build khi dự án được build. Không thể rõ ràng hơn thế nữa!
