Skip to content

Task 2-1: Structured Audit Trail cho TriggerBatchController

Phase: 2 - Observability Priority: Medium Depends on: task-1-3 Reference: SPEC.md — xem mục 4 (ADM-F-04 Manual batch trigger) và mục 2.10 (TriggerBatchController trong System Config & Maintenance)

Background

TriggerBatchController cho phép admin trigger batch jobs thủ công. Hiện tại không có audit trail: ai trigger, lúc nào, kết quả ra sao.

Tasks

File: admin/controller/trigger_batch/TriggerBatchController.java

  • [ ] Thêm audit log cho mỗi trigger:

    @PostMapping("/trigger/{jobName}")
    public Result<?> triggerBatch(@PathVariable String jobName) {
        String adminId = getCurrentAdminId();
        LOGGER.info("[BATCH_TRIGGER] admin={} job={} time={}", adminId, jobName, Instant.now());
    
        try {
            batchJobService.trigger(jobName);
            LOGGER.info("[BATCH_TRIGGER] SUCCESS admin={} job={}", adminId, jobName);
            return Result.OK();
        } catch (Exception e) {
            LOGGER.error("[BATCH_TRIGGER] FAILED admin={} job={}", adminId, jobName, e);
            throw e;
        }
    }
    

    Injection note — batchJobService: Kiểm tra xem TriggerBatchController đã inject batchJobService chưa. Nếu chưa, cần thêm:

    @Autowired
    private BatchJobService batchJobService; // hoặc tên service thực tế trong project
    
    Xác nhận tên service/class chính xác bằng cách tìm kiếm trong admin/src hoặc common/src — có thể là TriggerBatchService, JobService, hoặc tương tự.

    Injection note — getCurrentAdminId(): Nếu TriggerBatchController không extend base controller có sẵn method này, thêm helper method:

    private String getCurrentAdminId() {
        return ((AdminUserDetails) SecurityContextHolder.getContext()
            .getAuthentication().getPrincipal()).getAdminId();
    }
    
    Import cần thiết: org.springframework.security.core.context.SecurityContextHolderAdminUserDetails (kiểm tra package trong project).

    Import Instant:

    import java.time.Instant;
    

  • [ ] Store audit record trong DB:

    CREATE TABLE admin_batch_trigger_log (
        id VARCHAR(36) PRIMARY KEY,
        admin_id VARCHAR(36),
        job_name VARCHAR(100),
        triggered_at DATETIME,
        status VARCHAR(20),   -- SUCCESS, FAILED
        error_message TEXT
    );
    

    Note về migration: Tạo file migration mới trong thư mục migration của project (thường là resources/db/migration/ với Flyway hoặc Liquibase). Đặt tên theo convention hiện tại (ví dụ: V{next_version}__add_admin_batch_trigger_log.sql). Sau khi tạo table, cần tạo thêm entity AdminBatchTriggerLog, repository AdminBatchTriggerLogRepository, và inject vào controller để persist record.

Verification / Acceptance Criteria

  • [ ] Code compiles: TriggerBatchController.java build thành công; batchJobService, getCurrentAdminId(), và Instant đều resolve đúng
  • [ ] Log xuất hiện: Gọi POST /api/admin/trigger-batch/trigger/{jobName} → server logs có dòng [BATCH_TRIGGER] với adminId và jobName đúng
  • [ ] Log SUCCESS: Job chạy xong không lỗi → log có [BATCH_TRIGGER] SUCCESS
  • [ ] Log FAILED: Job throw exception → log có [BATCH_TRIGGER] FAILED kèm stack trace; exception được re-throw để caller nhận error response
  • [ ] DB record: Sau mỗi trigger, bảng admin_batch_trigger_log có record mới với admin_id, job_name, triggered_at, status đúng
  • [ ] Test class tham khảo: TriggerBatchControllerTest — kiểm tra cả success và failure path, verify log message và DB record

Files to Modify

  • admin/controller/trigger_batch/TriggerBatchController.java
  • Migration file (new table)