From b8f0c3cb92342f1325cf5a9615e3053f5567c31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Sat, 7 Jun 2025 22:08:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AF=B7=E6=B1=82=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=AE=B0=E5=BD=95provider,=20=E5=AD=A6=E5=BA=9CReques?= =?UTF-8?q?t=E5=BA=8F=E5=88=97=E5=8C=96=E7=9A=84BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 + .../java/cn/zhangdeman/context/Request.java | 15 ++- .../cn/zhangdeman/logger/BaseProvider.java | 111 ++++++++++++++++++ .../cn/zhangdeman/logger/LogTypeEnum.java | 16 +++ .../logger/RequestInfoLogProvider.java | 23 ++++ 5 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 src/main/java/cn/zhangdeman/logger/BaseProvider.java create mode 100644 src/main/java/cn/zhangdeman/logger/LogTypeEnum.java create mode 100644 src/main/java/cn/zhangdeman/logger/RequestInfoLogProvider.java diff --git a/pom.xml b/pom.xml index 89155a8..47b526c 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,12 @@ spring-boot-starter-web 3.4.7-SNAPSHOT + + + net.logstash.logback + logstash-logback-encoder + 7.4 + diff --git a/src/main/java/cn/zhangdeman/context/Request.java b/src/main/java/cn/zhangdeman/context/Request.java index f55d63a..b794271 100644 --- a/src/main/java/cn/zhangdeman/context/Request.java +++ b/src/main/java/cn/zhangdeman/context/Request.java @@ -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); + } + } } diff --git a/src/main/java/cn/zhangdeman/logger/BaseProvider.java b/src/main/java/cn/zhangdeman/logger/BaseProvider.java new file mode 100644 index 0000000..6ad2a58 --- /dev/null +++ b/src/main/java/cn/zhangdeman/logger/BaseProvider.java @@ -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 { + // 获取请求上下文 + 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) { + + } +} diff --git a/src/main/java/cn/zhangdeman/logger/LogTypeEnum.java b/src/main/java/cn/zhangdeman/logger/LogTypeEnum.java new file mode 100644 index 0000000..11195fb --- /dev/null +++ b/src/main/java/cn/zhangdeman/logger/LogTypeEnum.java @@ -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; + } +} diff --git a/src/main/java/cn/zhangdeman/logger/RequestInfoLogProvider.java b/src/main/java/cn/zhangdeman/logger/RequestInfoLogProvider.java new file mode 100644 index 0000000..4fe4d9b --- /dev/null +++ b/src/main/java/cn/zhangdeman/logger/RequestInfoLogProvider.java @@ -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()); + } +}