Backend Development 18 min read

Designing Business Operation Logging: From AOP Annotations to Binlog‑Based Solutions

This article explores the motivations, benefits, and step‑by‑step implementations of business operation logging, starting with a simple AOP‑annotation approach, advancing to AOP combined with Spring Expression Language for richer context, and finally leveraging MySQL binlog and time‑window techniques for low‑level, reliable change capture.

Top Architect
Top Architect
Top Architect
Designing Business Operation Logging: From AOP Annotations to Binlog‑Based Solutions

In a recent project the system sits at the core of a business data pipeline, receiving upstream data and forwarding user‑generated operation data downstream; to improve issue resolution efficiency and provide richer tooling, a full‑lifecycle business operation log is planned.

Benefits of business operation logs include audit and compliance, security (intrusion detection and post‑incident analysis), error diagnosis and system monitoring, user behavior analysis (business insights and customer service), data recovery, and process improvement.

Goal : enhance traceability and transparency of business data, ensuring smooth and monitorable processes.

Solution 1.0 – AOP + Annotation

Define a simple annotation to mark methods that need logging:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Loggable {
String value() default "";
// additional attributes such as operation type, level, etc.
}

Create an AOP aspect that records execution time and logs the method signature:

@Aspect
@Component
public class LoggingAspect {
@Around("@annotation(loggable)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint, Loggable loggable) throws Throwable {
long start = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long executionTime = System.currentTimeMillis() - start;
logger.info(joinPoint.getSignature() + " executed in " + executionTime + "ms");
return proceed;
}
}

Enable AOP in Spring configuration and annotate business methods:

@Configuration
@EnableAspectJAutoProxy
public class AopConfig {}
public class SomeService {
@Loggable
public void someBusinessMethod(Object param) {
// business logic
}
}

While functional, this approach suffers from limited context capture, difficulty handling multi‑table cascades, and invasive code.

Solution 2.0 – AOP + SpEL

Introduce a richer annotation that can embed SpEL expressions to extract arbitrary method parameters and context:

@Repeatable(LogRecords.class)
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface LogRecord {
String success();
String fail() default "";
String operator() default "";
String type();
String subType() default "";
String bizNo();
String extra() default "";
String actionType();
}

Parse the SpEL expressions at runtime to build detailed log messages:

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
public class LogRecordParser {
public static Map
parseLogRecord(Annotation logRecordAnnotation) {
// iterate over annotation attributes, evaluate each SpEL expression
}
}

Example usage of @Value with SpEL demonstrates the same principle:

@Value("#{mq.topic}")
public String mqTopic;
@Value("#{T(java.lang.Math).random() * 100.0}")
private double randomNumber;

This method greatly expands the amount of business data captured while keeping the implementation relatively lightweight.

Solution 3.0 – Binlog + Time Window

Leverage MySQL binary logs to capture every data change at the storage layer, then apply a sliding time‑window (similar to Flink) to group related events and reconstruct multi‑table transactions.

Define data structures for binlog parsing:

@Data
public static class RowChange {
private int tableId;
private List
rowDatas;
private String eventType;
private boolean isDdl;
}
@Data
public static class RowDatas {
private List
afterColumns;
private List
beforeColumns;
}
@Data
public static class DataColumn {
private int sqlType;
private boolean isNull;
private String mysqlType;
private String name;
private boolean isKey;
private int index;
private boolean updated;
private String value;
}

Combine the binlog stream with a 1‑minute rolling window to correlate operations across tables; additional logic can link rows via foreign‑key fields to resolve cascading updates.

Architecture diagram (illustrative) shows the flow from MySQL binlog → parser → window aggregator → unified business operation log service.

Pros and Cons

Solution 1: simple but limited context and invasive.

Solution 2: richer data, still requires annotation management.

Solution 3: low‑level capture, high reliability, but may miss fine‑grained business semantics and requires complex correlation.

Overall, the evolution demonstrates how logging requirements drive architectural choices, and the final design balances ease of integration with completeness of captured information.

backendarchitectureAOPSpringSPELLoggingbinlog
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.