Feign Client 请求和响应以及 URL 日志记录 [英] Feign Client request and response and URL Logging

查看:319
本文介绍了Feign Client 请求和响应以及 URL 日志记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何记录 Feign 客户端请求、响应和 URL 的负载.我必须实现拦截器吗?因为我的要求是在数据库的一个特殊表上记录请求和响应.

How I can log the payload of Feign client request, response and URL. do I have to Implement an Interceptor? Because my requirement is logging the request and response on a special table on the database.

推荐答案

Feign 有开箱即用的日志机制,可以通过简单的步骤实现.

Feign has out of box logging mechanism and it can be achieved through simple steps.

如果您使用的是 spring-cloud-starter-feign

Feign 使用 Slf4jLogger 进行日志记录.Feign 日志文档

Feign using Slf4jLogger for logging.Feign logging documentation

根据文档,可以配置以下日志记录级别,

As per doc, the below logging levels are available to configure,

  • NONE - 无日志记录(默认).
  • BASIC - 仅记录请求方法和 URL 以及响应状态代码和执行时间.
  • HEADERS - 记录基本信息以及请求和响应标头.
  • FULL - 记录请求和响应的标头、正文和元数据.
  • NONE - No logging (DEFAULT).
  • BASIC - Log only the request method and URL and the response status code and execution time.
  • HEADERS - Log the basic information along with request and response headers.
  • FULL - Log the headers, body, and metadata for both requests and responses.

注入 Logger.Level bean 就足够了.

Injecting the Logger.Level bean is enough.

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }

如果您更喜欢使用配置属性来配置所有 @FeignClient,您可以使用默认的 feign 名称创建配置属性.

If you prefer using configuration properties to configured all @FeignClient, you can create configuration properties with default feign name.

feign:
  client:
    config:
      default:
        loggerLevel: basic

如果您使用的是 'io.github.openfeign:feign-core'

如果您正在构建 Feign 构建器,那么您可以将 logLevel(Level.BASIC) 提及为

If you are constructing the Feign builder then you can mention logLevel(Level.BASIC) as

Feign.builder()
    .logger(new Slf4jLogger())
    .logLevel(Level.BASIC)
    .target(SomeFeignClient.class, url);

我们可以灵活地自定义日志消息

默认的 feign 请求和响应日志

The default feign request and response logging

请求记录

响应日志

Resopnse logging

我们可以通过覆盖 Logger#logRequestLogger#logAndRebufferResponse 方法来自定义伪装请求、响应日志记录模式.在以下示例中,我们自定义了请求日志记录模式

we can customize the feign request, response logging pattern by overriding Logger#logRequest and Logger#logAndRebufferResponse methods. In the following example, we have customized request logging pattern

log(configKey, "---> %s %s HTTP/1.1 (%s-byte body) ", request.httpMethod().name(), request.url(), bodyLength);

和响应日志记录模式

log(configKey, "<--- %s %s HTTP/1.1 %s (%sms) ", request.httpMethod().name(), request.url(), status, elapsedTime);

完整的例子是


import feign.Logger;
import feign.Request;
import feign.Response;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

import static feign.Logger.Level.HEADERS;

@Slf4j
public class CustomFeignRequestLogging extends Logger {

    @Override
    protected void logRequest(String configKey, Level logLevel, Request request) {

        if (logLevel.ordinal() >= HEADERS.ordinal()) {
            super.logRequest(configKey, logLevel, request);
        } else {
            int bodyLength = 0;
            if (request.requestBody().asBytes() != null) {
                bodyLength = request.requestBody().asBytes().length;
            }
            log(configKey, "---> %s %s HTTP/1.1 (%s-byte body) ", request.httpMethod().name(), request.url(), bodyLength);
        }
    }

    @Override
    protected Response logAndRebufferResponse(String configKey, Level logLevel, Response response, long elapsedTime)
            throws IOException {
        if (logLevel.ordinal() >= HEADERS.ordinal()) {
            super.logAndRebufferResponse(configKey, logLevel, response, elapsedTime);
        } else {
            int status = response.status();
            Request request = response.request();
            log(configKey, "<--- %s %s HTTP/1.1 %s (%sms) ", request.httpMethod().name(), request.url(), status, elapsedTime);
        }
        return response;
    }


    @Override
    protected void log(String configKey, String format, Object... args) {
        log.debug(format(configKey, format, args));
    }

    protected String format(String configKey, String format, Object... args) {
        return String.format(methodTag(configKey) + format, args);
    }
}

注意:可以轻松记录请求负载

String bodyText =
              request.charset() != null ? new String(request.body(), request.charset()) : null;

但是在读取输入流后要小心编写响应负载 Util.toByteArray(response.body().asInputStream()) 然后你必须像 一样再次构造响应response.toBuilder().body(bodyData).build().否则,你最终会得到期望.原因是响应流在返回之前被读取并且总是关闭,这就是为什么该方法被命名为 logAndRebufferResponse

but be careful writing the response payload after you are reading the input stream Util.toByteArray(response.body().asInputStream()) then you have to construct the response again like response.toBuilder().body(bodyData).build(). Otherwise, you will end up with the expection. The reason is response streams are read and always closed before returning, thats why the method is named as logAndRebufferResponse

如何使用自定义CustomFeignRequestLogging?

如果您仅使用 'io.github.openfeign:feign-core'

Feign.builder()
     .logger(new CustomFeignRequestLogging())
     .logLevel(feign.Logger.Level.BASIC);

如果您使用的是 'org.springframework.cloud:spring-cloud-starter-openfeign'

@Configuration
public class FeignLoggingConfiguration {

    @Bean
    public CustomFeignRequestLogging customFeignRequestLogging() {
        return new CustomFeignRequestLogging();
    }

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.BASIC;
    }
}

这篇关于Feign Client 请求和响应以及 URL 日志记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆