Ver Fonte

fix: 移除Feign客户端调用日志功能

lixuesong há 3 semanas atrás
pai
commit
1a757ee7ae

+ 0 - 152
yyc-common-log/src/main/java/net/yyc/common/log/FeignDefaultRequestLogging.java

@@ -1,152 +0,0 @@
-package net.yyc.common.log;
-
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.net.NetUtil;
-import cn.hutool.core.util.CharsetUtil;
-import net.yyc.common.log.config.LogConfig;
-import net.yyc.common.log.vo.LogMessage;
-import feign.Client;
-import feign.Request;
-import feign.Response;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.CollectionUtils;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Feign客户端调用日志输出
- * <p>
- * 由 {@link LogAutoConfiguration#feignClient} 包装为 LoadBalancerFeignClient 注册,
- * 保留负载均衡能力;关闭开关(log.feign.enable=false)时行为与 Client.Default 完全一致。
- */
-@Slf4j
-public class FeignDefaultRequestLogging extends Client.Default {
-
-    /**
-     * 请求EVENT
-     */
-    private static final String LOG_EVENT = "FEIGN";
-
-    /**
-     * 调用失败时 LogMessage.httpStatus 的占位状态码(无响应可取)
-     */
-    private static final int HTTP_STATUS_ERROR = -1;
-
-    /**
-     * 打印日志开关
-     */
-    private boolean enable;
-
-    /**
-     * body最大长度
-     */
-    private int maxLength;
-
-    public FeignDefaultRequestLogging(LogConfig logConfig) {
-        super(null, null);
-        this.enable = logConfig.isRequestFeignEnable();
-        this.maxLength = logConfig.getRequestMaxLength();
-    }
-
-    @Override
-    public Response execute(Request request, Request.Options options) throws IOException {
-        if (!enable) {
-            return super.execute(request, options);
-        }
-
-        long startTime = System.currentTimeMillis();
-
-        Response response;
-        try {
-            response = super.execute(request, options);
-        }
-        catch (IOException e) {
-            // 连接超时/读超时等调用失败也要留痕:状态码置 -1,记录异常摘要后原样抛出
-            LogMessage logMsg = new LogMessage();
-            logMsg.setEvent(LOG_EVENT);
-            logMsg.setMethod(request.httpMethod().name());
-            logMsg.setRequestUri(request.url());
-            logMsg.setIp(NetUtil.getLocalhostStr());
-            logMsg.setReqHeaders(assembleHeaders(request.headers()));
-            byte[] reqBody = request.body();
-            if (Objects.nonNull(reqBody)) {
-                logMsg.setReqBody(buildBodyText(reqBody));
-            }
-            logMsg.setHttpStatus(HTTP_STATUS_ERROR);
-            logMsg.setRespBody("ERROR: " + e.getClass().getSimpleName() + ": " + e.getMessage());
-            logMsg.setDuration(System.currentTimeMillis() - startTime);
-            log.info(logMsg.buildJson());
-            throw e;
-        }
-
-        //拼接日志
-        LogMessage logMsg = new LogMessage();
-        logMsg.setEvent(LOG_EVENT);
-        logMsg.setMethod(request.httpMethod().name());
-        logMsg.setRequestUri(request.url());
-        logMsg.setIp(NetUtil.getLocalhostStr());
-        logMsg.setReqHeaders(assembleHeaders(request.headers()));
-
-        byte[] reqBody = request.body();
-        if (Objects.nonNull(reqBody)) {
-            logMsg.setReqBody(buildBodyText(reqBody));
-        }
-        logMsg.setHttpStatus(response.status());
-        logMsg.setRespHeaders(assembleHeaders(response.headers()));
-
-        // 响应体必须完整读取并回填(业务方依赖完整 body),仅日志字符串截断;
-        // 读取失败时流已损坏无法恢复,记录告警并继续(调用方会得到读流异常)
-        Response.Body responseBody = response.body();
-        if (responseBody != null) {
-            try {
-                byte[] respBody = readBody(responseBody);
-                response = response.toBuilder().body(respBody).build();
-                logMsg.setRespBody(buildBodyText(respBody));
-            }
-            catch (IOException e) {
-                log.warn("FEIGN 响应体读取失败, uri: {}", request.url(), e);
-            }
-        }
-        logMsg.setDuration(System.currentTimeMillis() - startTime);
-        log.info(logMsg.buildJson());
-        return response;
-    }
-
-    /**
-     * 读取响应体:Content-Length 已知时按长度一次性分配,避免 ByteArrayOutputStream 动态扩容放大内存占用
-     */
-    private byte[] readBody(Response.Body body) throws IOException {
-        long length = body.length();
-        return length > 0 && length <= Integer.MAX_VALUE
-                ? IoUtil.readBytes(body.asInputStream(), (int) length)
-                : IoUtil.readBytes(body.asInputStream());
-    }
-
-    /**
-     * body 转日志文本:超过 maxLength 截断并追加总长度标记,防止超大响应撑爆日志
-     */
-    private String buildBodyText(byte[] body) {
-        if (body.length > maxLength) {
-            return new String(body, 0, maxLength, CharsetUtil.CHARSET_UTF_8)
-                    + String.format("...[TRUNCATED,total=%d]", body.length);
-        }
-        return new String(body, CharsetUtil.CHARSET_UTF_8);
-    }
-
-    private String assembleHeaders(Map<String, Collection<String>> headers) {
-        if (CollectionUtils.isEmpty(headers)) {
-            return null;
-        }
-        StringBuilder sb = new StringBuilder();
-
-        for (Map.Entry<String, Collection<String>> entrySet : headers.entrySet()) {
-            String key = entrySet.getKey();
-            Collection<String> values = entrySet.getValue();
-            sb.append(key).append("=").append(String.join(";", values)).append(LogMessage.DEFAULT_LOG_FIELD_SEPARATOR_2);
-        }
-        return sb.substring(0, sb.length() - 1);
-    }
-}

+ 0 - 31
yyc-common-log/src/main/java/net/yyc/common/log/LogAutoConfiguration.java

@@ -23,16 +23,9 @@ import net.yyc.common.log.aspect.SysLogAspect;
 import net.yyc.common.log.aspect.SysLogHandler;
 import net.yyc.common.log.config.LogConfig;
 import net.yyc.common.log.event.SysLogListener;
-import feign.Client;
 import lombok.AllArgsConstructor;
-import org.springframework.boot.autoconfigure.AutoConfigureBefore;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
-import org.springframework.cloud.openfeign.FeignAutoConfiguration;
-import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
-import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -50,9 +43,6 @@ import org.springframework.scheduling.annotation.EnableAsync;
 @AllArgsConstructor
 @ConditionalOnWebApplication
 @Import(LogConfig.class)
-// 必须先于 FeignAutoConfiguration 处理:其负载均衡 Client(RibbonFeignLoadBalancedConfiguration)
-// 为 @ConditionalOnMissingBean(Client.class),若其先注册,下方日志客户端会静默退位(feign 日志失效)
-@AutoConfigureBefore(FeignAutoConfiguration.class)
 public class LogAutoConfiguration {
 
     private final LogConfig logConfig;
@@ -67,27 +57,6 @@ public class LogAutoConfiguration {
         return new SysLogListener(handler);
     }
 
-    /**
-     * Feign 客户端:在保留负载均衡能力的前提下追加调用日志输出。
-     *
-     * <p>不能用裸的 {@link FeignDefaultRequestLogging}(继承 Client.Default)直接注册:
-     * 会顶掉 Spring Cloud 的 {@link LoadBalancerFeignClient},按服务名(http://service-name/xx)
-     * 的 Feign 调用会被当作域名解析,直接 UnknownHostException。因此包装为
-     * {@link LoadBalancerFeignClient},负载均衡行为与默认完全一致。</p>
-     *
-     * <p>若项目自行注册了 Client(okhttp / httpclient 等),本 Bean 自动退位,feign 日志随之失效,
-     * 届时需在自定义 Client 内自行包装日志逻辑。</p>
-     *
-     * @param cachingFactory ribbon 负载均衡工厂(FeignRibbonClientAutoConfiguration 提供)
-     * @param clientFactory  ribbon 客户端工厂(FeignRibbonClientAutoConfiguration 提供)
-     * @return 日志增强的负载均衡 Feign 客户端
-     */
-    @Bean
-    @ConditionalOnMissingBean(Client.class)
-    public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
-        return new LoadBalancerFeignClient(new FeignDefaultRequestLogging(logConfig), cachingFactory, clientFactory);
-    }
-
     @Bean
     public FilterRegistrationBean<RequestLoggingFilter> requestLoggingFilter() {
         RequestLoggingFilter filter = new RequestLoggingFilter(logConfig);

+ 0 - 6
yyc-common-log/src/main/java/net/yyc/common/log/config/LogConfig.java

@@ -13,12 +13,6 @@ public class LogConfig {
 	@Value("${log.request.enable:true}")
 	private boolean requestEnable;
 
-	/**
-	 * 配置关键字:Feign请求日志开关
-	 */
-	@Value("${log.feign.enable:true}")
-	private boolean requestFeignEnable;
-
 	/**
 	 * 配置关键字:请求日志输出长度
 	 */

+ 0 - 6
yyc-common-log/src/main/resources/net/yyc/common/log/request-logging-file-appender.xml

@@ -34,10 +34,4 @@
         <appender-ref ref="console" />
         <appender-ref ref="REQUEST_LOGGING_FILE" />
     </logger>
-
-    <!-- Feign 调用日志(EVENT=FEIGN,格式同 REQ),与请求日志同文件,便于 SLS 统一采集 -->
-    <logger name="net.yyc.common.log.FeignDefaultRequestLogging" level="INFO" additivity="false">
-        <appender-ref ref="console" />
-        <appender-ref ref="REQUEST_LOGGING_FILE" />
-    </logger>
 </included>