Backend Development 14 min read

Using the BizLog SDK in Spring Boot: Configuration, Annotations, and Custom Extensions

This article introduces the BizLog SDK for Spring Boot, explains how to add the Maven dependency, enable the @EnableLogRecord switch, use @LogRecordAnnotation for various logging scenarios, customize operators, details, categories, and parse functions, and shows how to extend the framework with custom services and implementations.

Architecture Digest
Architecture Digest
Architecture Digest
Using the BizLog SDK in Spring Boot: Configuration, Annotations, and Custom Extensions

Usage

Basic Usage

Maven Dependency

<dependency>
    <groupId>io.github.mouzt</groupId>
    <artifactId>bizlog-sdk</artifactId>
    <version>1.0.4</version>
</dependency>

SpringBoot Entry – Enable Switch

Add @EnableLogRecord annotation to the SpringBoot application class and optionally exclude the default datasource configuration:

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableTransactionManagement
@EnableLogRecord(tenant = "com.mzt.test")
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}

Log Recording

Define log templates with @LogRecordAnnotation . The template can include prefix , bizNo , success , fail , detail , category , and operator fields.

1. Simple success log

@LogRecordAnnotation(success = "{{#order.purchaseName}}下了一个订单,购买商品「{{#order.productName}}」,下单结果:{{#_ret}}",
    prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order) {
    log.info("【创建订单】orderNo={}", order.getOrderNo());
    // db insert order
    return true;
}

Resulting log example: "张三下了一个订单, 购买商品「超值优惠红烧肉套餐」, 下单结果: true".

2. Failure log

@LogRecordAnnotation(
    fail = "创建订单失败,失败原因:「{{#_errorMsg}}」",
    success = "{{#order.purchaseName}}下了一个订单,购买商品「{{#order.productName}}」,下单结果:{{#_ret}}",
    prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order) { ... }

3. Category for operator distinction

@LogRecordAnnotation(
    fail = "创建订单失败,失败原因:「{{#_errorMsg}}」",
    category = "MANAGER",
    success = "{{#order.purchaseName}}下了一个订单,购买商品「{{#order.productName}}」,下单结果:{{#_ret}}",
    prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order) { ... }

4. Recording detailed information

@LogRecordAnnotation(
    fail = "创建订单失败,失败原因:「{{#_errorMsg}}」",
    category = "MANAGER_VIEW",
    detail = "{{#order.toString()}}",
    success = "{{#order.purchaseName}}下了一个订单,购买商品「{{#order.productName}}」,下单结果:{{#_ret}}",
    prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order) { ... }

5. Specifying the operator

Two ways:

Manually set operator in the annotation (method must have a corresponding parameter).

Implement IOperatorGetService to obtain the current user automatically from thread context.

@Configuration
public class LogRecordConfiguration {
    @Bean
    public IOperatorGetService operatorGetService() {
        return () -> Optional.of(OrgUserUtils.getCurrentUser())
            .map(a -> new OperatorDO(a.getMisId()))
            .orElseThrow(() -> new IllegalArgumentException("user is null"));
    }
}

6. Custom log text with functions

Define a custom parse function by implementing IParseFunction and register it as a Spring bean.

@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 + ")";
    }
}

7. Using SpEL ternary expressions

@LogRecordAnnotation(prefix = LogRecordTypeConstant.CUSTOM_ATTRIBUTE,
    bizNo = "{{#businessLineId}}",
    success = "{{#disable ? '停用' : '启用'}}了自定义属性{ATTRIBUTE{#attributeId}}")
public CustomAttributeVO disableAttribute(Long businessLineId, Long attributeId, boolean disable) { ... }

8. Using external variables in templates

Put variables into LogRecordContext and reference them in the annotation.

@LogRecordAnnotation(success = "{{#order.purchaseName}}下了一个订单,购买商品「{{#order.productName}}」,测试变量「{{#innerOrder.productName}}」,下单结果:{{#_ret}}",
    prefix = LogRecordType.ORDER, bizNo = "{{#order.orderNo}}")
public boolean createOrder(Order order) {
    Order inner = new Order();
    inner.setProductName("内部变量测试");
    LogRecordContext.putVariable("innerOrder", inner);
    return true;
}

9. Diff list parsing function

Example of a function that compares old and new lists and generates a readable diff.

@Component
public class DiffListParseFunction implements IParseFunction {
    @Override public String functionName() { return "DIFF_LIST"; }
    @Override public String apply(String value) {
        if (StringUtils.isBlank(value)) return value;
        List
oldList = (List
) LogRecordContext.getVariable("oldList");
        List
newList = (List
) LogRecordContext.getVariable("newList");
        // compute added and deleted items and build result string
        ...
    }
}

Framework Extension Points

Override IOperatorGetService to customize operator retrieval.

Implement ILogRecordService to store logs in a database, Elasticsearch, etc.

Implement IParseFunction for custom placeholder functions (e.g., USER, ORDER).

Source Code

Repository: https://github.com/mouzt/mzt-biz-log

JavaSPELmavenLoggingSpring BootAnnotationBizLog
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.