Есть ли способ записать время отклика симулированного клиента

@FeignClient(...)
public interface SomeClient {
@RequestMapping(value = "/someUrl", method = POST, consumes = "application/json")
    ResponseEntity<String> createItem(...);

}

Есть ли способ найти время отклика для вызова API createItem? Мы используем пружинный чехол, привод, прометей.

4 ответа

У нас есть простой, а также индивидуальный способ регистрации запросов и ответов фиктивных клиентов (включая время ответа). Мы должны внедрить bean-компонент feign.Logger.Level, вот и все.

  1. ПО УМОЛЧАНИЮ / ПРЯМОЙ ПУТЬ
@Bean
Logger.Level feignLoggerLevel() {
  return Logger.Level.BASIC;
}

для более подробной информации доступны уровни ведения журнала BASIC,FULL,HEADERS,NONE(по умолчанию)

Вышеупомянутая инъекция bean-компонента даст вам регистрацию симулируемого запроса и ответа в следующем формате:

ЗАПРОС:

ссылаться

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

ex:2019-09-26 12:50:12.163 [DEBUG] [http-nio-4200-exec-5] [com.sample.FeignClient:72] [FeignClient#getUser] ---> END HTTP (0-byte body)

где configkey означает FeignClientClassName#FeignClientCallingMethodName пример: ApiClient#apiMethod.

ОТВЕТ

ссылаться

log(configKey, "<--- HTTP/1.1 %s%s (%sms)", status, reason, elapsedTime);

ex:2019-09-26 12:50:12.163 [DEBUG] [http-nio-4200-exec-5] [com.sample.FeignClient:72] [FeignClient#getUser] <--- HTTP/1.1 200 OK (341ms)

то elapsedTime время ответа на вызов API.

ПРИМЕЧАНИЕ. Если вы предпочитаете способ фиктивного ведения журнала клиента по умолчанию, тогда мы должны также учитывать уровень ведения журнала базового приложения, посколькуfeign.Slf4jLogger ведение журнала класса с симулированными деталями запроса и ответа с DEBUGуровень ( см.). Если базовый уровень ведения журнала выше DEBUG, вам может потребоваться указать явное средство ведения журнала дляfeign ведение журнала пакета / класса, иначе это не сработает.

  1. ИНДИВИДУАЛЬНЫЙ СПОСОБ Если вы предпочитаете вести журнал в своем индивидуальном формате, вы можете расширитьfeign.Loggerкласс и настроить ведение журнала. В качестве типичного примера, если я хочу записать данные заголовка запроса и ответа в одну строку в виде списка (по умолчанию Logger.Level.HEADERS печатает заголовок в несколько строк):
package com.test.logging.feign;

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 customFeignLogger 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) %s", request.httpMethod().name(), request.url(), bodyLength, request.headers());
        }
    }

    @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) %s", request.httpMethod().name(), request.url(), status, elapsedTime, response.headers());
        }
        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);
    }
}

также мы должны ввести bean-компонент класса customFeignLogger

  @Bean
    public customFeignLogger customFeignLogging() {
        return new customFeignLogger();
    }

Если вы создаете FeignClient самостоятельно, вы можете создать его с помощью настраиваемого регистратора:

 Feign.builder().logger(new customFeignLogger()).logLevel(Level.BASIC).target(SomeFeignClient.class,"http://localhost:8080");

Добавьте следующую аннотацию к вашему проекту.

package com.example.annotation

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DebugTracking {
    @Aspect
    @Component
    public static class DebugTrackingAspect {
        @Around("@annotation(com.example.annotation.DebugTracking)")
        public Object trackExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start(joinPoint.toShortString());

            Exception exceptionThrown = null;

            try {
                // Execute the joint point as usual
                return joinPoint.proceed();

            } catch (Exception ex) {
                exceptionThrown = ex;
                throw ex;

            } finally {
                stopWatch.stop();

                System.out.println(String.format("%s took %dms.", stopWatch.getLastTaskName(), stopWatch.getLastTaskTimeMillis()));

                if (exceptionThrown != null) {
                    System.out.println(String.format("Exception thrown: %s", exceptionThrown.getMessage()));
                    exceptionThrown.printStackTrace();

                }
            }
        }
    }
}

Затем аннотируйте методы, которые вы хотите отслеживать в вашем @FeignClient с @DebugTracking,

правильный способ сделать это - использовать пользовательский регистратор, как указано выше. Использование @Aspect неправильно. При этом вы создаете дополнительную оболочку вокруг сервиса. Feign уже записывает этот показатель. Получите эту метрику от притворства.

Я использую следующее (с Spring и Lombok):

      @Configuration // from Spring
@Slf4j // from Lombok
public class MyFeignConfiguration {
    @Bean // from Spring
    public MyFeignClient myFeignClient() {
        return Feign.builder()
            .logger(new Logger() {
                @Override
                protected void log(String configKey, String format, Object... args) {
                    LOG.info( String.format(methodTag(configKey) + format, args)); // LOG is the Lombok Slf4j object
                }
            })
            .logLevel(Logger.Level.BASIC) // see https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html#_feign_logging
            .target(MyFeignClient.class,"http://localhost:8080");
    }
}
Другие вопросы по тегам