Mastering BizLog SDK: Seamless Log Recording for Spring Boot Applications
This article introduces the BizLog SDK for Java, explains its Spring Boot autoconfiguration, demonstrates how to add Maven dependencies, enable logging with @EnableLogRecord, craft log messages using @LogRecordAnnotation with SpEL expressions, and extend the framework with custom parse functions and operator services.
Component Overview
The BizLog SDK provides a unified way to record who performed what action, when, and on which business entity in Java applications. It offers Spring Boot autoconfiguration and can also be manually configured for Spring MVC via XML.
Basic Usage
Maven Dependency
<dependency>
<groupId>io.github.mouzt</groupId>
<artifactId>bizlog-sdk</artifactId>
<version>1.0.1</version>
</dependency>Enable Logging in Spring Boot
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableTransactionManagement
@EnableLogRecord(tenant = "com.mzt.test")
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}The tenant parameter identifies the tenant; a single tenant identifier can be used for multiple services under the same business.
Log Recording
1. Simple Log Record
@LogRecordAnnotation(
success = "{{#order.purchaseName}} placed an order, purchased product \"{{#order.productName}}\", result:{{#_ret}}",
prefix = LogRecordType.ORDER,
bizNo = "{{#order.orderNo}}"
)
public boolean createOrder(Order order) {
log.info("【创建订单】orderNo={}", order.getOrderNo());
// db insert order
return true;
}This will output a log such as "Zhang San placed an order, purchased product \"Super Value Red Braised Pork Set\", result:true".
2. Record Failure Log
@LogRecordAnnotation(
fail = "Order creation failed, reason: \"{{#_errorMsg}}\"",
success = "{{#order.purchaseName}} placed an order, purchased product \"{{#order.productName}}\", result:{{#_ret}}",
prefix = LogRecordType.ORDER,
bizNo = "{{#order.orderNo}}"
)
public boolean createOrder(Order order) {
log.info("【创建订单】orderNo={}", order.getOrderNo());
// db insert order
return true;
}The #_errorMsg variable captures the exception message when an error occurs.
3. Log Category
@LogRecordAnnotation(
fail = "Order creation failed, reason: \"{{#_errorMsg}}\"",
category = "MANAGER",
success = "{{#order.purchaseName}} placed an order, purchased product \"{{#order.productName}}\", result:{{#_ret}}",
prefix = LogRecordType.ORDER,
bizNo = "{{#order.orderNo}}"
)
public boolean createOrder(Order order) { /* ... */ }The category field helps classify logs (e.g., user actions vs. manager operations) for easier querying.
4. Detail Field
@LogRecordAnnotation(
fail = "Order creation failed, reason: \"{{#_errorMsg}}\"",
category = "MANAGER_VIEW",
detail = "{{#order.toString()}}",
success = "{{#order.purchaseName}} placed an order, purchased product \"{{#order.productName}}\", result:{{#_ret}}",
prefix = LogRecordType.ORDER,
bizNo = "{{#order.orderNo}}"
)
public boolean createOrder(Order order) { /* ... */ }The detail field can store a JSON string or the result of order.toString() to retain full change information.
5. Specifying the Operator
Two approaches are provided:
Manually set the operator attribute in the annotation (requires an operator method parameter).
Implement IOperatorGetService to automatically obtain the current user from thread context or other sources.
@Configuration
public class LogRecordConfiguration {
@Bean
public IOperatorGetService operatorGetService() {
return () -> Optional.of(OrgUserUtils.getCurrentUser())
.map(u -> new OperatorDO(u.getMisId()))
.orElseThrow(() -> new IllegalArgumentException("user is null"));
}
}
@Service
public class DefaultOperatorGetServiceImpl implements IOperatorGetService {
@Override
public OperatorDO getUser() {
OperatorDO operatorDO = new OperatorDO();
operatorDO.setOperatorId("SYSTEM");
return operatorDO;
}
}Custom Parse Functions
Implement IParseFunction to create reusable functions used inside SpEL templates.
@Component
public class OrderParseFunction implements IParseFunction {
@Resource @Lazy private OrderQueryService orderQueryService;
@Override
public String functionName() { return "ORDER"; }
@Override
public String apply(String value) {
if (StringUtils.isEmpty(value)) return value;
Order order = orderQueryService.queryOrder(Long.parseLong(value));
return order.getProductName() + "(" + value + ")";
}
}Usage in annotation:
@LogRecordAnnotation(
success = "Updated order ORDER{#orderId}}, details...",
prefix = LogRecordType.ORDER,
bizNo = "{{#order.orderNo}}",
detail = "{{#order.toString()}}"
)
public boolean update(Long orderId, Order order) { return false; }Advanced Features
SpEL ternary expressions for conditional log messages.
Adding custom variables via LogRecordContext.putVariable(name, value) for use in templates and custom functions.
Diff list parsing to generate logs like "added X, removed Y".
@LogRecordAnnotation(
success = "{DIFF_LIST{'Document Address'}}",
bizNo = "{{#id}}",
prefix = REQUIREMENT
)
public void updateRequirementDocLink(String currentMisId, Long id, List<String> docLinks) { /* ... */ }
@Component
public class DiffListParseFunction implements IParseFunction {
@Override
public String functionName() { return "DIFF_LIST"; }
@Override
public String apply(String value) {
// compare oldList and newList stored in LogRecordContext
// build human‑readable diff string
return result;
}
}Extension Points
Custom IOperatorGetService implementation to fetch the operator from security context.
Implement ILogRecordService to persist logs to a database, Elasticsearch, or any storage.
Create additional IParseFunction implementations for domain‑specific transformations.
Change Log & TODO
Name
Status
Support Context Variable
1.0.4 supported
Support Object Diff
TODO
Support List Log Recording
TODO
Important Note
The log interceptor runs after the method execution, so SpEL expressions see the modified method parameters.
Source Code
GitHub repository: https://github.com/mouzt/mzt-biz-log
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
