
# request日志
#### 实现原理
devspore-http-log打印请求日志是通过实现常见HTTP请求客户端的拦截器来完成的。拦截器可以在请求发送之前和响应返回之后对数据进行处理，从而实现日志记录。
例如，在Spring Boot中，可以通过实现ClientHttpRequestInterceptor接口并重写intercept方法来创建自定义拦截器。在拦截器中，可以添加日志记录逻辑，以打印请求和响应的详细信息。此外，还可以通过RestTemplateCustomizer将自定义拦截器注册到RestTemplate中，从而实现对HTTP请求和响应的全局日志记录。
这种实现方式的优点是通用性强、代码侵入性小，并且具有可定制性。通过拦截器，可以在不修改业务逻辑代码的情况下，轻松地添加日志记录功能。
目前支持的客户端有：httpclient、okhttp、RestTemplate和Feign。
#### 添加依赖
pom文件添加如下依赖：
```
<dependency>
    <groupId>com.huaweicloud.devspore</groupId>
    <artifactId>devspore-http-log</artifactId>
    <version>最新版本</version> 
</dependency>
```
#### 使用方式
- HttpClient **前提：需要使用httpclient进行对第三方的调用**。
  需要用户在创建CloseableHttpClient时添加com.huaweicloud.devspore.http.log.httpclient.HttpClientRequestInterceptor和com.huaweicloud.devspore.http.log.httpclient.HttpClientResponseInterceptor。
  示例：
  ```
  CloseableHttpClient httpClient = HttpClients.custom()
     .addInterceptorFirst(new HttpClientRequestInterceptor())
     .addInterceptorFirst(new HttpClientResponseInterceptor())
     .build();
  ```
  
- OkHttp **前提：需要使用okhttp进行对第三方的调用**。
  需要用户在创建OKhttpclient时添加com.huaweicloud.devspore.http.log.okhttp.OkhttpInterceptor。
  示例：
  ```
  OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new OkhttpInterceptor()).build();
  ```
  
- RestTemplate **注意：若存在使用restTemplate传输大文件或者大对象的场景，请不要使用此拦截器记录requestLog，否则极有可能引入OOM问题。**
  **前提：需要使用restTemplate进行对第三方的调用**。
  - 以bean形式注入的restTemplate。 需要在spring配置文件中添加配置项：devspore.http-log.request.rest-template.enable=true。
    当devspore.http-log.request.enable(默认值true)和devspore.http-log.request.rest-template.enable(默认值false)两个配置项同时为true时，才会自动添加RestTemplateInterceptor。
    原理：当配置条件允许使用RestTemplateInterceptor时，httplog组件会扫描服务中所有的RestTemplate类型的bean，并为其添加RestTemplateInterceptor拦截器。
    相关源码见：com.huaweicloud.devspore.http.log.config.DevsporeHttpLogAutoConfiguration.setApplicationContext()
    
  
  - 非bean形式注入的restTemplate。 需要用户在创建restTemplate时添加com.huaweicloud.devspore.http.log.resttemplate.RestTemplateInterceptor。
    ```
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.getInterceptors().add(0, new RestTemplateInterceptor());
    ```
    
   
- Feign **前提：需要使用Feign Client进行对第三方的调用。**
  当使用Feign的时候，无需做其他改动，devspore-http-log会自动打印request日志，如不想打印request日志，可以在spring配置文件中添加配置：devspore.http-log.request.enable=false来关闭request日志的打印。
  
 
#### request日志示例
```
"nenvId": "null",
"userId": "null",
"url": "http://localhost:8081/servicecall/consumer/001",
"path": "/servicecall/consumer/001",
"method": "GET",
"senvId": null,
"status": 200,
"tracId": null,
"startTime": "2023-12-28 16:59:41.218",
"duration": 33,
"clientType": "httpClient.HttpResponseProxy",
"clientIp": "169.254.174.247",
"reqBodySize": 0,
"resBodySize": 93,
"logType": "request"
}
```
 #### request日志字段说明
表1request日志字段说明 
| **字段名**     | **字段含义**     | **可选/必选**      |
|:---|:---|:---|
| logType     | 日志类型         | 必选，值固定为request |
| url         | 请求URL        | 必选             |
| path        | 请求路径         | 必选             |
| method      | 请求HTTP方法     | 必选             |
| status      | 返回状态码        | 必选             |
| startTime   | 请求开始时间       | 必选             |
| duration    | 请求时长         | 必选             |
| clientIp    | 请求方IP        | 必选             |
| clientType  | 客户端类型        | 必选             |
| userId      | 请求所属用户ID     | 必选             |
| reqBodySize | 请求体body大小    | 必选             |
| resBodySize | 返回体body大小    | 必选             |
| nenvId      | 调用方服务APM环境ID | 必选（依赖APM）      |
| senvId      | 被调用服务APM环境ID | 必选（依赖APM）      |
| tracId      | 调用链跟踪ID      | 必选（依赖APM）      |
   
