feign如何开启日志及分析

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: feign如何开启日志及分析

1、首先需要设置属性logging.level.包名:debug。为什么要打开这个属性呢?

因为feign的logger实现类Slf4jLogger在调用log方法时,会判断是否开启了debug。

protectedvoidlog(StringconfigKey, Stringformat, Object... args) {
// Not using SLF4J's support for parameterized messages (even though it would be more efficient)// because it would// require the incoming message formats to be SLF4J-specific.if (logger.isDebugEnabled()) {
logger.debug(String.format(methodTag(configKey) +format, args));
    }
}

2、feign的日志级别

feign的日志级别包含下面几个

  • NONE:不输出日志
  • BASIC:输出请求方法及url,响应的状态码及响应时间
  • HEADERS:输出请求和响应的头信息
  • FULL:输出请求和响应的请求头,消息体及元数据

在发送请求时,会判断feign的日志级别,如果级别大于等于HEADERS,则输出请求头,如果级别大于等于FULL,则输出消息体。

protectedvoidlogRequest(StringconfigKey, LevellogLevel, Requestrequest) {
log(configKey, "---> %s %s HTTP/1.1", request.httpMethod().name(), request.url());
if (logLevel.ordinal() >=Level.HEADERS.ordinal()) {
for (Stringfield : request.headers().keySet()) {
for (Stringvalue : valuesOrEmpty(request.headers(), field)) {
log(configKey, "%s: %s", field, value);
        }
      }
intbodyLength=0;
if (request.body() !=null) {
bodyLength=request.length();
if (logLevel.ordinal() >=Level.FULL.ordinal()) {
StringbodyText=request.charset() !=null?newString(request.body(), request.charset())
                  : null;
log(configKey, ""); // CRLFlog(configKey, "%s", bodyText!=null?bodyText : "Binary data");
        }
      }
log(configKey, "---> END HTTP (%s-byte body)", bodyLength);
    }
}

在feign处理响应时,AsyncResponseHandler处理响应时判断日志级别输出日志,请求头或者消息体。

protectedResponselogAndRebufferResponse(StringconfigKey,
LevellogLevel,
Responseresponse,
longelapsedTime)
throwsIOException {
Stringreason=response.reason() !=null&&logLevel.compareTo(Level.NONE) >0?" "+response.reason()
            : "";
intstatus=response.status();
log(configKey, "<--- HTTP/1.1 %s%s (%sms)", status, reason, elapsedTime);
if (logLevel.ordinal() >=Level.HEADERS.ordinal()) {
for (Stringfield : response.headers().keySet()) {
for (Stringvalue : valuesOrEmpty(response.headers(), field)) {
log(configKey, "%s: %s", field, value);
        }
      }
intbodyLength=0;
if (response.body() !=null&&!(status==204||status==205)) {
// HTTP 204 No Content "...response MUST NOT include a message-body"// HTTP 205 Reset Content "...response MUST NOT include an entity"if (logLevel.ordinal() >=Level.FULL.ordinal()) {
log(configKey, ""); // CRLF        }
byte[] bodyData=Util.toByteArray(response.body().asInputStream());
bodyLength=bodyData.length;
if (logLevel.ordinal() >=Level.FULL.ordinal() &&bodyLength>0) {
log(configKey, "%s", decodeOrDefault(bodyData, UTF_8, "Binary data"));
        }
log(configKey, "<--- END HTTP (%s-byte body)", bodyLength);
returnresponse.toBuilder().body(bodyData).build();
      } else {
log(configKey, "<--- END HTTP (%s-byte body)", bodyLength);
      }
    }
returnresponse;
}

3、如何设置日志级别的方式

3.1 通过属性配置

即feign.client.{contextId}.loggerLeve=BASIC、HEADERS或者FULL

可以发现在配置feign时,先是使用Configuration来配置,然后使用属性中的默认配置,最后使用属性中contextId对应的配置

protectedvoidconfigureFeign(FeignContextcontext, Feign.Builderbuilder) {
FeignClientPropertiesproperties=applicationContext            .getBean(FeignClientProperties.class);
FeignClientConfigurerfeignClientConfigurer=getOptional(context,
FeignClientConfigurer.class);
setInheritParentContext(feignClientConfigurer.inheritParentConfiguration());
if (properties!=null&&inheritParentContext) {
if (properties.isDefaultToProperties()) {
configureUsingConfiguration(context, builder);
configureUsingProperties(
properties.getConfig().get(properties.getDefaultConfig()),
builder);
configureUsingProperties(properties.getConfig().get(contextId), builder);
        }
else {
configureUsingProperties(
properties.getConfig().get(properties.getDefaultConfig()),
builder);
configureUsingProperties(properties.getConfig().get(contextId), builder);
configureUsingConfiguration(context, builder);
        }
    }
else {
configureUsingConfiguration(context, builder);
    }
}

3.2 @Configuration配置

@ConfigurationpublicclassFeignClientConfig {
@BeanLogger.LevelfeignLoggerLevel() {
returnLogger.Level.FULL;
    }
}

此时是通过父子BeanFactory中查找Logger.Level,因为在子BeanFactory中没有,实际上是在父BeanFactory查找得到Logger.Level。

3.3 @FeignClient注解中的configuration来指定配置类。

此时是通过在子BeanFactory中查找得到Logger.Level。

配置的优先级为从高到低

配置文件中的contextId对应的属性->配置文件中的default对应的属性->FeignClient注解通过configuration指定的配置类->全局配置

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
20天前
|
监控 应用服务中间件 定位技术
要统计Nginx的客户端IP,可以通过分析Nginx的访问日志文件来实现
要统计Nginx的客户端IP,可以通过分析Nginx的访问日志文件来实现
|
1月前
|
存储 SQL 监控
|
1月前
|
运维 监控 安全
|
1月前
|
监控 关系型数据库 MySQL
分析慢查询日志
【10月更文挑战第29天】分析慢查询日志
43 3
|
1月前
|
监控 关系型数据库 数据库
怎样分析慢查询日志?
【10月更文挑战第29天】怎样分析慢查询日志?
43 2
|
2月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1699 14
|
2月前
|
存储 消息中间件 大数据
大数据-69 Kafka 高级特性 物理存储 实机查看分析 日志存储一篇详解
大数据-69 Kafka 高级特性 物理存储 实机查看分析 日志存储一篇详解
49 4
|
2月前
|
SQL 分布式计算 Hadoop
Hadoop-19 Flume Agent批量采集数据到HDFS集群 监听Hive的日志 操作则把记录写入到HDFS 方便后续分析
Hadoop-19 Flume Agent批量采集数据到HDFS集群 监听Hive的日志 操作则把记录写入到HDFS 方便后续分析
53 2
|
3月前
|
缓存 监控 算法
分析慢日志文件来优化 PHP 脚本的性能
分析慢日志文件来优化 PHP 脚本的性能
|
4月前
|
SQL 监控 关系型数据库
使用 pt-query-digest 工具分析 MySQL 慢日志
【8月更文挑战第5天】使用 pt-query-digest 工具分析 MySQL 慢日志
101 3
使用 pt-query-digest 工具分析 MySQL 慢日志