增加请求日志记录provider, 学府Request序列化的BUG

This commit is contained in:
白茶清欢 2025-06-07 22:08:40 +08:00
parent 327099e963
commit b8f0c3cb92
5 changed files with 170 additions and 1 deletions

View File

@ -63,6 +63,12 @@
<artifactId>spring-boot-starter-web</artifactId>
<version>3.4.7-SNAPSHOT</version>
</dependency>
<!-- 支持日志json格式 -->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.4</version> <!-- 使用最新版本 -->
</dependency>
</dependencies>
<repositories>

View File

@ -4,17 +4,20 @@ import cn.zhangdeman.consts.RecordField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.Map;
// 请求相关数据
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true) // 忽略未知属性字段
public class Request {
public class Request implements Serializable {
@JsonProperty(RecordField.REQUEST_UA)
private String userAgent; // 客户端ua
@JsonProperty(RecordField.REQUEST_CLIENT_IP)
@ -37,4 +40,14 @@ public class Request {
private byte[] requestBodyRaw; // 原始请求body
@JsonProperty(RecordField.REQUEST_URI)
private String requestUri; // 请求接口
// 序列化
@Override
public String toString() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,111 @@
package cn.zhangdeman.logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.status.Status;
import cn.zhangdeman.consts.RecordField;
import cn.zhangdeman.context.RuntimeContext;
import com.fasterxml.jackson.core.JsonGenerator;
import jakarta.servlet.http.HttpServletRequest;
import net.logstash.logback.composite.JsonProvider;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.io.IOException;
// 基础provider, 简化真正provider逻辑 + 实现公共方法
public abstract class BaseProvider implements JsonProvider<ILoggingEvent> {
// 获取请求上下文
protected RuntimeContext getCurrentRequest() {
try {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (null == requestAttributes) {
return null;
}
HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest();
return (RuntimeContext) httpServletRequest.getAttribute(RecordField.RUNTIME_THREAD_CONTEXT);
} catch (Exception e) {
return null; // HTTP 请求环境
}
}
// 写入公共字段
protected void writeCommonField(RuntimeContext runtimeContext, JsonGenerator gen, String logType) throws IOException {
gen.writeStringField(RecordField.REQUEST_ID, runtimeContext.getRequestId());
gen.writeStringField(RecordField.TRACE_ID, runtimeContext.getTraceId());
gen.writeStringField(RecordField.SERVER_IP, runtimeContext.getServerIp());
gen.writeStringField(RecordField.SERVER_HOSTNAME, runtimeContext.getServerHostname());
gen.writeStringField(RecordField.LOGGER_TYPE, logType);
gen.writeStringField(RecordField.REQUEST_METHOD, runtimeContext.getRequestInfo().getRequestMethod());
gen.writeStringField(RecordField.REQUEST_URI, runtimeContext.getRequestInfo().getRequestUri());
gen.writeStringField(RecordField.REQUEST_CLIENT_IP, runtimeContext.getRequestInfo().getClientIp());
gen.writeNumberField(RecordField.COST, System.currentTimeMillis() - runtimeContext.getStartTimeStamp()); // 代表的是从请求开始, 到打印日志这一刻, 花费了多长时间
gen.writeStringField(RecordField.REQUEST_CONTENT_TYPE, runtimeContext.getRequestInfo().getRequestContentType() == null ? "" : runtimeContext.getRequestInfo().getRequestContentType());
}
@Override
public void prepareForDeferredProcessing(ILoggingEvent iLoggingEvent) {
}
@Override
public void start() {
}
@Override
public void stop() {
}
@Override
public boolean isStarted() {
return false;
}
@Override
public void setContext(Context context) {
}
@Override
public Context getContext() {
return null;
}
@Override
public void addStatus(Status status) {
}
@Override
public void addInfo(String s) {
}
@Override
public void addInfo(String s, Throwable throwable) {
}
@Override
public void addWarn(String s) {
}
@Override
public void addWarn(String s, Throwable throwable) {
}
@Override
public void addError(String s) {
}
@Override
public void addError(String s, Throwable throwable) {
}
}

View File

@ -0,0 +1,16 @@
package cn.zhangdeman.logger;
import lombok.Getter;
@Getter
public enum LogTypeEnum {
REQUEST_INPUT("input", "请求输入信息"),
REQUEST_OUTPUT("output", "请求响应信息"),
;
private final String logType;
private final String description;
LogTypeEnum(String logType, String description) {
this.logType = logType;
this.description = description;
}
}

View File

@ -0,0 +1,23 @@
package cn.zhangdeman.logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import cn.zhangdeman.consts.RecordField;
import cn.zhangdeman.context.RuntimeContext;
import com.fasterxml.jackson.core.JsonGenerator;
import java.io.IOException;
// 记录请求信息
public class RequestInfoLogProvider extends BaseProvider {
@Override
public void writeTo(JsonGenerator gen, ILoggingEvent event) throws IOException {
RuntimeContext runtimeContext = getCurrentRequest();
if (null == runtimeContext) {
// http 请求不应该用到这个provider
return;
}
// 请求输入日志
writeCommonField(runtimeContext, gen, LogTypeEnum.REQUEST_INPUT.getLogType());
gen.writeStringField(RecordField.REQUEST_INFO, runtimeContext.getRequestInfo().toString());
}
}