How the Operation Log Aspect Captures Requests and Responses in ContiNew Admin

The ContiNew Admin operation log aspect uses an AOP interceptor from the ContiNew-Starter-Log module to automatically capture HTTP requests and responses by wrapping annotated controller methods, storing the data in thread-local LogRecord objects, and persisting them via LogDaoLocalImpl to the sys_log table.

The continew-org/continew-admin repository implements automatic operation logging through a clean aspect-oriented architecture. By leveraging the external ContiNew-Starter-Log dependency combined with a local persistence implementation, the system records full request-response cycles without cluttering business logic.

How the Operation Log Aspect Works

The logging mechanism relies on the LogAspect class provided by the continew-starter-log Maven dependency. This aspect intercepts any controller method marked with the @Log annotation, creating a complete audit trail through three distinct phases.

Intercepting Methods with the @Log Annotation

Controllers declare logging requirements through the @Log annotation imported from top.continew.starter.log.annotation.Log. In continew-system/src/main/java/top/continew/admin/system/controller/LogController.java at line 39, methods like list() use @Log(module = "系统日志") to trigger interception, while the exportOperationLog method uses @Log(ignore = true) to skip logging for high-volume export endpoints.

Capturing Request Data Before Execution

Before the target method executes, the aspect constructs a LogRequest object containing the HTTP method, URI, query parameters, request body, and current user details. This data is stored in a thread-local LogRecord context, ensuring isolation between concurrent requests.

Recording Responses and Exceptions

After method completion—whether successful or exceptional—the aspect builds a LogResponse object capturing the HTTP status code, response body, and execution duration. The aspect updates the existing LogRecord with this response data, creating a complete entry ready for persistence.

Persisting Operation Logs to the Database

The concrete persistence logic resides in continew-server/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java (lines 75-154). This bean implements the LogDao interface and handles the final database write.

Converting LogRecord to LogDO

The LogDaoLocalImpl#add(LogRecord) method transforms the aspect's LogRecord into a LogDO entity defined in continew-system/src/main/java/top/continew/admin/system/model/entity/LogDO.java. The implementation extracts request metadata from LogRequest and response details from LogResponse, setting the type field to LogTypeEnum.OPERATION for operation-specific logs.

Database Storage via MyBatis-Plus

The converted LogDO entity is inserted into the sys_log table using LogMapper from continew-system/src/main/java/top/continew/admin/system/mapper/LogMapper.java. This MyBatis-Plus mapper handles the actual SQL execution, storing fields including request method, URI, status code, response body, and execution time.

Key Source Files and Components

  • LogController.java – Demonstrates @Log annotation usage on REST endpoints.
  • LogDaoLocalImpl.java – Concrete implementation that persists LogRecord objects to the database (lines 75-154).
  • LogDO.java – Entity class mapping the sys_log database table.
  • LogMapper.java – MyBatis-Plus mapper interface for database operations.
  • LogServiceImpl.java – Contains exportOperationLog method for Excel export functionality.
  • LogAspect – Provided by the external starter module; handles AOP interception and LogRecord assembly.

Implementation Examples

Annotating Controller Methods

@RestController
@RequestMapping("/system/log")
public class LogController {

    @Log(module = "系统日志")
    @SaCheckPermission("monitor:log:list")
    @GetMapping("/list")
    public PageResult<LogResp> list(@Valid LogQuery query, @Valid SortQuery sort) {
        return baseService.list(query, sort);
    }

    @Log(ignore = true)   // Skip logging for exports
    @GetMapping("/export/operation")
    public void exportOperationLog(@Valid LogQuery query,
                                   @Valid SortQuery sortQuery,
                                   HttpServletResponse response) {
        baseService.exportOperationLog(query, sortQuery, response);
    }
}

Aspect Execution Flow

@Aspect
@Component
public class LogAspect {

    @Around("@annotation(logAnnotation)")
    public Object around(ProceedingJoinPoint pjp, Log logAnnotation) throws Throwable {
        // Build LogRequest from HttpServletRequest
        LogRequest request = LogRequestBuilder.build();
        
        // Execute target method
        Object result = pjp.proceed();
        
        // Build LogResponse with status and timing
        LogResponse response = LogResponseBuilder.build();
        
        // Assemble and persist LogRecord
        LogRecord record = new LogRecord()
                .setRequest(request)
                .setResponse(response)
                .setModule(logAnnotation.module())
                .setIgnore(logAnnotation.ignore());
        
        logDao.add(record);
        return result;
    }
}

Persistence Layer Implementation

@Component
public class LogDaoLocalImpl implements LogDao {

    private final LogMapper logMapper;

    @Override
    public void add(LogRecord logRecord) {
        LogDO logDO = new LogDO();
        
        // Copy request data
        LogRequest req = logRecord.getRequest();
        logDO.setRequestMethod(req.getMethod());
        logDO.setRequestUri(req.getUri());
        
        // Copy response data
        LogResponse resp = logRecord.getResponse();
        logDO.setStatus(resp.getStatus());
        logDO.setResponseBody(resp.getBody());
        
        // Mark as operation type log
        logDO.setType(LogTypeEnum.OPERATION);
        
        // Insert to database
        logMapper.insert(logDO);
    }
}

Summary

  • The ContiNew-Starter-Log module provides the LogAspect that intercepts @Log annotated methods.
  • LogRequest and LogResponse objects capture complete HTTP request and response data in a thread-local context.
  • LogDaoLocalImpl in continew-server/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java handles the conversion from LogRecord to LogDO and persists to the sys_log table.
  • The @Log annotation supports configuration options like module naming and ignore flags to control logging behavior.
  • Operation logs are automatically categorized with LogTypeEnum.OPERATION for proper filtering and export via LogServiceImpl.exportOperationLog.

Frequently Asked Questions

What triggers the operation log aspect in ContiNew Admin?

The aspect triggers when a controller method is annotated with @Log from top.continew.starter.log.annotation.Log. The LogAspect class from the ContiNew-Starter-Log dependency uses Spring AOP to wrap these methods, executing advice before and after the method invocation to capture request and response data.

How does the operation log aspect handle concurrent requests?

The aspect stores log data in a thread-local LogRecord context, ensuring that each HTTP request maintains isolated logging state. This prevents cross-thread contamination when multiple users simultaneously access annotated endpoints, maintaining accurate request-to-response correlation for each individual thread.

Where is the operation log data physically stored?

The LogDaoLocalImpl class in continew-server/src/main/java/top/continew/admin/config/log/LogDaoLocalImpl.java persists logs to the sys_log database table via MyBatis-Plus. This implementation converts the aspect's LogRecord into LogDO entities, setting the type to LogTypeEnum.OPERATION before insertion through LogMapper.

Can I disable operation logging for specific endpoints?

Yes. The @Log annotation accepts an ignore parameter that bypasses the logging aspect when set to true. For example, in LogController.java, the exportOperationLog method uses @Log(ignore = true) to prevent generating log entries during large data exports, reducing database overhead for high-volume operations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →