伪装客户端请求和响应以及URL记录 [英] Feign Client request and response and URL Logging

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

问题描述

我如何记录伪装客户请求,响应和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

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

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;
    }

OR

如果您希望使用配置属性来配置所有@FeignClient,则可以使用默认伪名称创建配置属性.

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'

If you are using '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);

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

默认的伪装请求和响应日志记录

The default feign request and response 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

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

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