服务方接口调用记录持久化标准沉淀
一、引言
最近又在写一个对外接口,需要将调用记录持久化下来,正好借此机会把接口调用记录持久化的标准规范写一套出来,以后其他系统也可以参考,框架用的是响应式开发spring webflux + r2dbc + oracle。
二、具体内容
1.设计接口调用记录表结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
create table API_CALL_RECORD
(ID NUMBER(19) GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
REQUEST_ID VARCHAR2 (500) not null,
REQUEST_TIME TIMESTAMP (6) not null,
SYSTEM_ID VARCHAR2 (100) not null,
API_PATH VARCHAR2 (500),
API_NAME VARCHAR2 (500),
REQUEST_DATA CLOB,
IS_SUCCESS VARCHAR2(5),
ERROR_MSG CLOB,
RESPONSE_DATA CLOB,
RESPONSE_TIME TIMESTAMP(6),
DURATION_MS INTEGER
);
comment on table API_CALL_RECORD IS '接口调用记录表';
comment on column API_CALL_RECORD.ID IS '唯一标识';
comment on column API_CALL_RECORD.REQUEST_ID IS '请求id';
comment on column API_CALL_RECORD.REQUEST_IIME IS '请求时间';
comment on column API_CALL_RECORD.SYSTEM_ID IS '系统标识';
comment on column API_CALL_RECORD.API_PATH IS '接口路径';
comment on column API_CALL_RECORD.API_NAME IS '接口名称';
comment on column API_CALL_RECORD.REQUEST_DATA IS '请求参数';
comment on column API_CALL_RECORD.IS_SUCCESS IS '是否成功Y-成功';
comment on column API_CALL_RECORD.ERROR_MSG IS '错误信息';
comment on column API_CALL_RECORD.RESPONSE_DATA IS '返回数据';
comment on column API_CALL_RECORD.RESPONSE_TIME IS '返回时间';
comment on column API_CALL_RECORD.DURATION_MS IS '请求耗时(毫秒)';
2.创建数据库表对应的实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table("API_CALL_RECORD")
public class ApiCallRecord {
@Id
@Column("ID")
private Long id;
@Column("REQUEST_ID")
private String requestId;
@Column("REQUEST_TIME")
private LocalDateTime requestTime;
@Column("SYSTEM_ID")
private String systemId;
@Column("API_PATH")
private String apiPath;
@Column("API_NAME")
private String apiName;
@Column("REQUEST_DATA")
private String requestData; // CLOB类型映射为String
@Column("IS_SUCCESS")
private String isSuccess; // Y-成功, N-失败
@Column("ERROR_MSG")
private String errorMsg; // CLOB类型映射为String
@Column("RESPONSE_DATA")
private String responseData; // CLOB类型映射为String
@Column("RESPONSE_TIME")
private LocalDateTime responseTime;
@Column("DURATION_MS")
private Integer durationMs;
}
3.编写业务逻辑层代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface ApiCallRecordService {
Mono<Void> saveApiCallRecord(ApiCallRecord apiCallRecord);
}
@Slf4j
@Service
@RequiredArgsConstructor
public class ApiCallRecordServiceImpl implements ApiCallRecordService {
@Autowired
private R2dbcEntityTemplate r2dbcEntityTemplate;
@Override
public Mono<Void> saveApiCallRecord(ApiCallRecord apiCallRecord); {
return r2dbcEntityTemplate.insert(ApiCallRecord.class).using(apiCallRecord).then;
}
}
4.调用接口记录持久化方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 记录请求开始时间
LocalDateTime startTime = LocalDateTime.now();
// 调用登录接口
...
//记录调用接口返回时间
LocalDateTime endTime = LocalDateTime.now();
// 记录请求耗时
long processingTime = Duration.between(startTime, endTime).toMillis();
// 链式调用创建调用记录对象
ApiCallRecord apiCallRecord = ApiCallRecord.builder()
.requestId(request.getRequestId())
.requestTime(startTime)
.systemId(request.getSystemId())
.apiPath("/user/login")
.apiName("登录接口")
.requestData(request == null ? "" : (request.toString().length() > 1000 ? request.toString().subString(0,1000) : request.toString());
.isSuccess(response.isSuccess() ? "Y" : "N"
.errorMsg(response.getError() == null ? "" : response.getError().getMessage())
.responseData(response.getData() == null ? "" : response.getData().getText())
.responseTime(endTime)
.durationMs((int) processingTime)
.build();
// 调用业务层记录持久化方法
apicallRecordservice.saveApiCallRecord(apiCallRecord)
.doonsuccess(v -> {log.info("保存调用记录成功");})
.do0nError(e -> {log.error("保存调用记录失败",e);})
.subscribe();
}
三、总结
这是一个简易版调用记录持久化的过程,需要方法首先必须拿到response(即便发生exception也要封装好response传回来)。
作者:吴银双
日期:2026年6月16日
平台:GitHub Pages / 技术博客
本文由作者按照 CC BY 4.0 进行授权