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

> Discover how the ContiNew Admin operation log aspect captures HTTP requests and responses using AOP to automatically log controller data for auditing and analysis.

- Repository: [OpenContiNew/continew-admin](https://github.com/continew-org/continew-admin)
- Tags: internals
- Published: 2026-02-27

---

**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`](https://github.com/continew-org/continew-admin/blob/main/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`](https://github.com/continew-org/continew-admin/blob/main/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`](https://github.com/continew-org/continew-admin/blob/main/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`](https://github.com/continew-org/continew-admin/blob/main/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`](https://github.com/continew-org/continew-admin/blob/main/LogController.java)** – Demonstrates `@Log` annotation usage on REST endpoints.
- **[`LogDaoLocalImpl.java`](https://github.com/continew-org/continew-admin/blob/main/LogDaoLocalImpl.java)** – Concrete implementation that persists `LogRecord` objects to the database (lines 75-154).
- **[`LogDO.java`](https://github.com/continew-org/continew-admin/blob/main/LogDO.java)** – Entity class mapping the `sys_log` database table.
- **[`LogMapper.java`](https://github.com/continew-org/continew-admin/blob/main/LogMapper.java)** – MyBatis-Plus mapper interface for database operations.
- **[`LogServiceImpl.java`](https://github.com/continew-org/continew-admin/blob/main/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

```java
@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

```java
@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

```java
@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`](https://github.com/continew-org/continew-admin/blob/main/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`](https://github.com/continew-org/continew-admin/blob/main/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`](https://github.com/continew-org/continew-admin/blob/main/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.