MinBox Logging

MinBox Logging是一款分布式、零侵入式的链路日志分析框架,支持SpringCloud微服务架构下配置使用,内部封装了RestTemplateOpenFeign两种方式透传链路信息。

零侵入式

MinBox Logging无需使用注解配置采集链路日志,只需要添加依赖后简单配置Minbox Loggin Admin的相关地址服务名称即可,每次在收到请求时就会把请求对应的链路日志详细信息自动上报到MinBox Logging Admin进行后续分析、告警通知等。

源码地址

https://gitee.com/minbox-projects/minbox-logging

I. 概念

1. 链路架构图

image

在一次请求中,经过的每一个服务(MicroService)链路编号(TraceId)保持一致,通过SpanIDParentSpanID进行链路上下级关系衔接。

2. 提交使用中遇到的问题

遇到你在集成使用过程中遇到了问题,请提交issues,提交地址:创建Issues

3. ApiBoot集成实践示例

ApiBoot作为MinBox开源组织的组件最佳集成方案,在第一时间会进行整合minbox-projects开源组织内新发布的组件,MinBox Logging整合实践请访问ApiBoot源码,整合源码详见org.minbox.framework.api.boot.autoconfigure.logging

II. 配置客户端

4. 启用客户端

minbox-logging-spring-context依赖内提供了@EnableLoggingClient注解来启用客户端,配置使用该注解后通过@Import自动注册Logging Client运行时所需要的Bean

@EnableLoggingClient使用示例如下所示:

@SpringBootApplication
@EnableLoggingClient
public class ApiBootLoggingApplication {
    /**
     * logger instance
     */
    static Logger logger = LoggerFactory.getLogger(ApiBootLoggingApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(ApiBootLoggingApplication.class, args);
        logger.info("{}服务启动成功.", "ApiBoot Logging Client");
    }
}

5. 透传链路信息

每发送一个请求时就会产生一条链路信息,而链路单元(Span)之前的相互访问目前则以httprpc等方式作为主要占比。

链路信息(Trace)的传递,Logging Client内部提供了提取请求header内的链路信息编号(TraceID)、上级单元编号(Parent SpanID),整条链路都通过这种方式来进行上下级单元关系、链路关系绑定。

5.1. RestTemplate透传链路信息

RestTemplateSpring Web组件提供的请求封装对象,可用于发送指定方式的请求到目标地址,可携带header信息进行传递身份认证信息、请求、响应等信息。

Logging Client则是利用RestTemplate的拦截器将链路(Trace)信息写入请求的header进行传递到下一个单元(Span)。

Logging Client已经提供了RestTemplate拦截器实现类LoggingRestTemplateInterceptor,在LoggingFactoryBean#afterPropertiesSet方法内进行实例化并且已经设置了拦截器,在Logging Client上报请求日志信息时,都是通过LoggingFactoryBean#restTemplate来执行发送请求到Admin,因此只需要实例化LoggingFactoryBean即可。

5.2. OpenFeign透传链路信息

OpenFeignSpringCloud为服务之间方法相互调用的实现方式,根据接口配置信息来发送请求并获取响应内容。

Logging Client同样是利用OpenFeign提供的拦截器将链路(Trace)信息写入服务相互调用的请求header,进行传递到下一个服务。

Logging Client内部提供了RequestInterceptor接口实现类LoggingOpenFeignInterceptor来完成链路信息透传,OpenFeign会自动检索Spring IOC容器内RequestInterceptor接口的实现类实例,每次通过OpenFeign发起请求时会调用RequestInterceptor实现类的apply方法来完成拦截业务处理。

6. 发现Admin并上报日志

Logging Client默认本地不进行持久化存储请求日志信息,而是将本地生成的请求日志详细信息上报到Logging Admin,由Admin进行存储、分析等。

Logging Client内部提供LoggingAdminDiscovery#lookup接口方法来进行发现Admin地址

6.1. 指定地址发现Admin

Logging Client获取指定Admin地址是通过LoggingAdminDiscovery其中一个实现类LoggingAppointAdminDiscovery来进行获取。

下面是ApiBoot配置使用LoggingAppointAdminDiscovery实践示例,

详见源码,ApiBootLoggingAdminAppointAutoConfiguration

/**
* ApiBoot Logging Admin Config Discovery
* Multiple Use "," Separation
*
* @return LoggingAdminDiscovery
*/
@Bean
@ConditionalOnMissingBean
public LoggingAppointAdminDiscovery loggingConfigAdminDiscovery() {
  String[] adminAddressArray = apiBootLoggingProperties.getAdmin().getServerAddress().split(",");
  LoggingAppointAdminDiscovery appointAdminDiscovery = new LoggingAppointAdminDiscovery(adminAddressArray);
  return appointAdminDiscovery;
}

LoggingAppointAdminDiscovery构造函数需提供Logging Admin地址数组,格式为:ip(IP地址):port(端口号),并不需要添加任何httphttps前缀。

6.1.1. 多Admin地址负载均衡配置

如果我们在创建LoggingAppointAdminDiscovery对象时传递了多个Logging Admin地址,比如:

@Bean
@ConditionalOnMissingBean
public LoggingAppointAdminDiscovery loggingConfigAdminDiscovery() {
  // 初始化Logging Admin地址列表
  String[] adminAddressArray = {"127.0.0.1:8080,127.0.0.1:9090"};
  LoggingAppointAdminDiscovery appointAdminDiscovery = new LoggingAppointAdminDiscovery(adminAddressArray);
  return appointAdminDiscovery;
}

如上所示,我启动了两个Logging Admin来进行接收Logging Client采集到的请求日志信息后执行存储,而Logging Client具体使用什么LoadBlanace(负载均衡)策略来进行选择上报的Logging Admin节点?

Logging Client提供了LoadBalanceStrategy负载均衡策略接口,而内部提供了两种策略的实现,分别是:RandomWeightedStrategySmoothWeightedRoundRobinStrategy

Logging Client默认采用SmoothWeightedRoundRobinStrategy(平滑轮询权重)负载均衡策略。

6.1.2. 随机权重负载策略

虽然LoggingAppointAdminDiscovery在构造函数内默认实例化了平滑轮询负载策略,我们当然可以通过LoggingAppointAdminDiscovery#setLoadBalanceStrategy方法来进行设置具体的策略,随机权重策略设置方式如下所示:

@Bean
@ConditionalOnMissingBean
public LoggingAppointAdminDiscovery loggingConfigAdminDiscovery() {
  // 初始化Logging Admin地址列表
  String[] adminAddressArray = {"127.0.0.1:8080,127.0.0.1:9090"};
  LoggingAppointAdminDiscovery appointAdminDiscovery = new LoggingAppointAdminDiscovery(adminAddressArray);
  // 实例化随机权重策略
  RandomWeightedStrategy randomWeightedStrategy = new RandomWeightedStrategy();
  // 设置负载均衡策略
  appointAdminDiscovery.setLoadBalanceStrategy(randomWeightedStrategy);
  return appointAdminDiscovery;
}

RandomWeightedStrategy(随机权重负载策略)是随机分配选择指定的Logging Admin地址,在上面示例中,随机权重的结果可能为:

随机权重获取到的 Logging Admin 地址:
127.0.0.1:8080
127.0.0.1:8080
127.0.0.1:9090
127.0.0.1:8080
127.0.0.1:9090
127.0.0.1:9090
127.0.0.1:9090
6.1.3. 平滑轮询权重负载策略

SmoothWeightedRoundRobinStrategy(平滑轮询权重负载策略)是平滑分配指定的Logging Admin地址,在上面示例中,平滑轮询权重的结果为:

平滑轮询权重获取到的 Logging Admin 地址:
127.0.0.1:8080
127.0.0.1:9090
127.0.0.1:8080
127.0.0.1:9090
127.0.0.1:8080
127.0.0.1:9090

6.2. 服务注册中心发现Admin

SpringCloud MicroService部署方式下使用时,可以将Logging Admin作为一个单独的服务进行注册到Service Registry Center(服务注册中心,如:EurekaZookeeperConsulNacos Discovery等),这样在Logging Client通过服务注册的发现接口即可完成Logging Admin的发现,获取地址后进行上报请求日志

Logging Client内部提供了集成服务注册中心的服务发现实现LoggingRegistryCenterAdminDiscovery,通过配置实例化该类并放入Spring IOC即可完成自动从服务注册中心内获取Logging Admin信息。

ApiBoot配置使用LoggingRegistryCenterAdminDiscovery实践示例,详见源码,ApiBootLoggingAdminDiscoveryAutoConfiguration

/**
* ApiBoot Logging Admin Registry Center Discovery
* @param loadBalancerClient LoadBalance Client
* @return LoggingRegistryCenterAdminDiscovery
*/
@Bean
@ConditionalOnMissingBean
public LoggingRegistryCenterAdminDiscovery loggingRegistryCenterAdminDiscovery(LoadBalancerClient loadBalancerClient) {
  LoggingRegistryCenterAdminDiscovery registryCenterAdminDiscovery =
    new LoggingRegistryCenterAdminDiscovery(apiBootLoggingProperties.getDiscovery().getServiceId(), loadBalancerClient);
  return registryCenterAdminDiscovery;
}

LoadBalancerClientSpringCloud负载均衡客户端对象,通过SpringCloud依赖的自动配置并且放入Spring IOC,注入该对象后即可负载均衡的发现一个可用的指定serviceID的服务对象ServiceInstance

7. 延迟上报日志

Logging Client默认采用了just(直接上报)的方式来上报采集到的请求日志,每产生一条请求日志都会实时上报到Logging Admin,而有些时候需求往往变化比较大,比如:降低Logging Admin压力,这时可能每次上报20条请求日志Logging Admin

针对这种业务情况,Logging Client提供了定时上报方式。

7.1. 配置上报方式

上报方式通过LoggingFactoryBean#setReportAway方法来修改默认值,参数为org.minbox.framework.logging.core.ReportAway枚举,修改如下所示:

// 设置上报方式为:timing
factoryBean.setReportAway(ReportAway.timing);

7.2. 设置单次上报的日志数量

单次上报请求日志数量默认值为:10

通过LoggingFactoryBean#setNumberOfRequestLog方法来修改默认值,如下所示:

// 设置每次上报的请求日志数量
factoryBean.setNumberOfRequestLog(20);

7.3. 设置上报日志间隔时间

上报日志默认间隔时间为:5秒

通过LoggingFactoryBean#setReportIntervalSecond方法来修改默认值,如下所示:

// 设备上报间隔时间,单位:秒
factoryBean.setReportIntervalSecond(5);

8. 自定义TraceID生成规则

Logging Client默认使用UUID生成的字符串作为TraceId(链路编号),通过LoggingFactoryBean#setTraceGenerator方法来修改默认的生成规则,自定义策略需要实现LoggingTraceGenerator接口,如下所示:

/**
 * 自定义链路编号(TraceID){@link LoggingTraceGenerator}
 *
 * @author 恒宇少年
 */
public class CustomerTraceIdGenerator implements LoggingTraceGenerator {
    @Override
    public String createTraceId() throws MinBoxLoggingException {
        return UUID.randomUUID().toString().replace("-", "");
    }
}

设置使用自定义的策略如下所示:

// 创建自定义策略对象
CustomerTraceIdGenerator customerTraceIdGenerator = new CustomerTraceIdGenerator();
// 设置使用自定义生成TraceID的策略
factoryBean.setTraceGenerator(customerTraceIdGenerator);

9. 自定义SpanID生成规则

Logging Client默认使用UUID生成的字符串作为SpanId(单元编号),通过LoggingFactoryBean#setSpanGenerator方法来修改默认的生成规则,自定义策略需要实现LoggingSpanGenerator接口,如下所示:

/**
 * 自定义单元编号(SpanID){@link LoggingSpanGenerator}
 *
 * @author 恒宇少年
 */
public class CustomerSpanIdGenerator implements LoggingSpanGenerator {
    @Override
    public String createSpanId() throws MinBoxLoggingException {
        String currentTime = String.valueOf(System.currentTimeMillis());
        return String.format("%s-%s", "span", currentTime);
    }
}

设置使用自定义策略如下所示:

// 创建自定义策略对象
CustomerSpanIdGenerator customerSpanIdGenerator = new CustomerSpanIdGenerator();
// 设置使用自定义生成SpanID的策略
factoryBean.setSpanGenerator(customerSpanIdGenerator);

10. 排除部分路径不进行上报日志

Logging Client内默认排除了/error路径不进行上报日志,如果业务服务存在一些访问比较频繁的接口,而且接口并不涉及业务请求,那么建议将这些请求进行排除,比如:集成SpringBootAdmin后会频繁访问/actuator/health来检查服务的健康程度。

通过LoggingFactoryBean#setIgnorePaths方法进行追加排除路径,这里注意是追加而不是替换,所以/error始终是在排除的列表内,配置排除路径如下所示:

// 需要排除的路径列表
String[] ignorePaths = new String[]{
  "/actuator/health",
  "/index",
  "/test"
};
// 设置排除的路径列表
factoryBean.setIgnorePaths(ignorePaths);

11. 安全上报日志

分布式的日志采集与日志存储定然会存在安全性问题,那么在Logging Admin服务端已经解决了这个问题,Logging Admin通过集成Spring Security配置用户名、密码来完成Basic Auth认证。

Logging Client发起上报请求时,会提取Logging Admin路径内的Basic Auth认证信息,通过header形式进行传递认证信息。

11.1. 指定Admin地址方式配置

如果采用的是LoggingAppointAdminDiscovery方式配置Logging Admin服务地址发现,那么在构造函数初始化Logging Admin地址时,需要携带Basic Auth的用户名、密码信息,如下所示:

@Bean
@ConditionalOnMissingBean
public LoggingAppointAdminDiscovery loggingConfigAdminDiscovery() {
  // 初始化Logging Admin地址列表
  String[] adminAddressArray = {"user:123@127.0.0.1:8080,user:123@127.0.0.1:9090"};
  LoggingAppointAdminDiscovery appointAdminDiscovery = new LoggingAppointAdminDiscovery(adminAddressArray);
  return appointAdminDiscovery;
}

在上面示例中可以看到Basic Auth是通过username:password@IP:Port格式来进行配置,其中user为用户名,而123则是该用户的密码。

11.2. 服务注册中心配置

如果采用LoggingRegistryCenterAdminDiscovery方式配置Logging Admin服务地址发现,配置如下所示:

/**
* ApiBoot Logging Admin Registry Center Discovery
* setting basic auth username if not empty {@link LoggingRegistryCenterAdminDiscovery#setUsername(String)}
* setting basic auth password if not empty {@link LoggingRegistryCenterAdminDiscovery#setPassword(String)}
*
* @param loadBalancerClient LoadBalance Client
* @return LoggingRegistryCenterAdminDiscovery
*/
@Bean
@ConditionalOnMissingBean
public LoggingRegistryCenterAdminDiscovery loggingRegistryCenterAdminDiscovery(LoadBalancerClient loadBalancerClient) {
  LoggingRegistryCenterAdminDiscovery registryCenterAdminDiscovery =
    new LoggingRegistryCenterAdminDiscovery(apiBootLoggingProperties.getDiscovery().getServiceId(), loadBalancerClient);
  // 用户名
  String basicAuthUserName = apiBootLoggingProperties.getDiscovery().getUsername();
  if (ObjectUtils.isEmpty(basicAuthUserName)) {
    registryCenterAdminDiscovery.setUsername(basicAuthUserName);
  }
  // 密码
  String basicAuthPassword = apiBootLoggingProperties.getDiscovery().getPassword();
  if (!ObjectUtils.isEmpty(basicAuthPassword)) {
    registryCenterAdminDiscovery.setPassword(basicAuthPassword);
  }
  return registryCenterAdminDiscovery;
}

上面示例所示,根据LoggingRegistryCenterAdminDiscovery#setUsername方法来设置用户名,根据LoggingRegistryCenterAdminDiscovery#setPassword方法来设置密码。

12. 控制台显示上报日志

Logging Client默认不会在控制台打印即将要上报的请求日志信息,可以通过LoggingFactiory#setShowConsoleLog方法进行设置,如下所示:

// 设置在控制台输出上报的日志
factoryBean.setShowConsoleLog(true);

13. 格式化控制台显示上报日志

Logging Client在控制台打印上报的请求日志时,默认不进行格式化json字符串,根据LoggingFactoryBean#setFormatConsoleLog方法来进行设置,如下所示:

// 设置格式化输出上报的日志
factoryBean.setFormatConsoleLog(true);

14. 自定义日志上报通知

Logging Client提供日志上报通知功能,只需要实现LoggingNotice接口即可获取每次上报的请求日志详细对象,进行日志的自定义处理,如下所示:

/**
 * 自定义日志通知
 * @author 恒宇少年
 */
@Component
public class CustomerLoggingNotice implements LoggingNotice {
    /**
     * 通知方法
     * 处理自定义的业务逻辑
     * @param minBoxLog
     */
    @Override
    public void notice(MinBoxLog minBoxLog) {
        System.out.println(minBoxLog.getTraceId());
        // 自定义业务处理...
    }

    /**
     * 通知执行优先级
     * {@link #getOrder()}方法返回值值越小优先级越高
     *
     * @return
     */
    @Override
    public int getOrder() {
        return 1;
    }
}

14.1. 内置的日志通知

Logging Client内部提供了日志通知的具体实现,分别是:LoggingLocalNoticeLoggingAdminNotice

日志通知实现类 功能作用
LoggingLocalNotice LoggingLocalNotice日志通知用于在控制台显示、格式化日志对象详细信息,优先级为Integer.MIN_VALUE,源码详见org.minbox.framework.logging.client.notice.support.LoggingLocalNotice
LoggingAdminNotice LoggingAdminNotice日志通知用于上报日志信息到Logging Admin,优先级为Integer.MIN_VALUE + 1,源码详见:org.minbox.framework.logging.client.notice.support.LoggingAdminNotice

14.2. 自定义多个日志上报通知

Logging Client内部通过ApplicationContextSpring IOC内获取指定LoggingNotice类型的实例列表,正因为这样也就支持了多日志通知的方式。

注意:日志通知实现类的优先级值建议不要重复。

III. 配置服务端

15. 启用服务端

minbox-logging-spring-context依赖内提供了@EnableLoggingAdmin注解来启用服务端,配置使用该注解后通过@Import自动注册Logging Admin运行时所需要的Bean

@EnableLoggingAdmin使用示例如下所示:

@SpringBootApplication
@EnableLoggingAdmin
public class ApiBootLoggingAdminApplication {
    /**
     * logger instance
     */
    static Logger logger = LoggerFactory.getLogger(ApiBootLoggingAdminApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(ApiBootLoggingAdminApplication.class, args);
        logger.info("{}服务启动成功.", "Logging Admin");
    }
}

16. 初始化数据库

Logging Admin支持将Logging Client上报的请求日志保存到数据库,而且提供了固定的表结构,如下所示:

SET NAMES utf8mb4 ;
--
-- Table structure for table `logging_service_details`
--

DROP TABLE IF EXISTS `logging_service_details`;
SET character_set_client = utf8mb4 ;
CREATE TABLE `logging_service_details` (
  `lsd_id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL,
  `lsd_service_id` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上报服务的ID,对应spring.application.name配置值',
  `lsd_service_ip` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上报服务的IP地址',
  `lsd_service_port` int(11) DEFAULT NULL COMMENT '上报服务的端口号',
  `lsd_last_report_time` timestamp NULL DEFAULT NULL COMMENT '最后一次上报时间,每次上报更新',
  `lsd_create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '首次上报时创建时间',
  PRIMARY KEY (`lsd_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='上报日志的客户端服务详情';

--
-- Table structure for table `logging_request_logs`
--

DROP TABLE IF EXISTS `logging_request_logs`;
SET character_set_client = utf8mb4 ;
CREATE TABLE `logging_request_logs` (
  `lrl_id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键,UUID',
  `lrl_service_detail_id` varchar(36) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '服务详情编号,关联logging_service_details主键',
  `lrl_trace_id` varchar(36) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '链路ID',
  `lrl_parent_span_id` varchar(36) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '上级跨度ID',
  `lrl_span_id` varchar(36) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '跨度ID',
  `lrl_start_time` mediumtext COLLATE utf8mb4_general_ci COMMENT '请求开始时间',
  `lrl_end_time` mediumtext COLLATE utf8mb4_general_ci COMMENT '请求结束时间',
  `lrl_http_status` int(11) DEFAULT NULL COMMENT '请求响应状态码',
  `lrl_request_body` longtext COLLATE utf8mb4_general_ci COMMENT '请求主体内容',
  `lrl_request_headers` text COLLATE utf8mb4_general_ci COMMENT '请求头信息',
  `lrl_request_ip` varchar(30) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '发起请求客户端的IP地址',
  `lrl_request_method` varchar(10) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求方式',
  `lrl_request_uri` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '请求路径',
  `lrl_response_body` longtext COLLATE utf8mb4_general_ci COMMENT '响应内容',
  `lrl_response_headers` text COLLATE utf8mb4_general_ci COMMENT '响应头信息',
  `lrl_time_consuming` int(11) DEFAULT NULL COMMENT '请求耗时',
  `lrl_create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '日志保存时间',
  `lrl_request_params` text COLLATE utf8mb4_general_ci,
  `lrl_exception_stack` text COLLATE utf8mb4_general_ci,
  PRIMARY KEY (`lrl_id`),
  KEY `logging_request_logs_LRL_SERVICE_DETAIL_ID_index` (`lrl_service_detail_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='请求日志信息表';

16.1. 将日志持久化到数据库

初始化Logging Admin所需要的表结构之后,我们在集成Logging Admin的项目中添加数据源数据库驱动持久化框架等依赖,然后进行配置数据源相关数据库参数,下面以SpringBoot项目示例。

16.1.1 添加所需依赖

pom.xml新增依赖如下所示:

<!--ApiBoot提供的持久化框架-->
<dependency>
  <groupId>org.minbox.framework</groupId>
  <artifactId>api-boot-starter-mybatis-enhance</artifactId>
  <version>{ApiBoot最新版本}</version>
</dependency>
<!--MySQL数据库驱动-->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.17</version>
</dependency>
<!--Hikari数据源-->
<dependency>
  <groupId>com.zaxxer</groupId>
  <artifactId>HikariCP</artifactId>
  <version>3.2.0</version>
</dependency>

Logging Admin并不固定依赖ApiBoot提供的持久化框架,可以使用任意框架依赖,Logging Admin内部只是需要DataSource的实例,也可以自定义创建DataSource对象放入Spring IOC

16.1.2. 配置数据源参数
spring:
  # 数据源参数
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/test

17. 将Admin注册到SpringCloud

Logging Admin作为一个依赖添加到SpringBoot项目内,我们只需要考虑如何将SpringBoot项目注册到服务注册中心(SpringCloud Service Register Center),如果你使用的Eureka作为服务注册中心,请访问我之前编写的文章查看将微服务提供者注册到Eureka服务中心

18. 启用安全配置

Logging Admin的安全采用的是Spring Security提供的Basic Auth来完成。

18.1. 添加支持Spring Security

在项目的pom.xml内添加如下依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

18.2. 配置安全用户

建议采用Spring Security提供的内存方式来配置Logging Adminapplication.yml配置文件如下所示:

spring:
  security:
    user:
      # 用户名
      name: user
      # 密码
      password: 123

19. 监听日志上报事件

Logging Admin支持自定义处理监听到Logging Client上报的日志信息,可进行自定义的存储,格式化处理,分组归类等,自定义事件监听沿用了Spring Event/Listener方式,如下所示:

/**
 * 自定义上报日志事件{@link ReportLogEvent}监听
 *
 * @author 恒宇少年
 */
@Component
public class CustomerReportEventListener implements SmartApplicationListener {
    /**
     * 判断事件类型为{@link ReportLogEvent}
     *
     * @param eventType
     * @return
     */
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return ReportLogEvent.class == eventType;
    }

    /**
     * 自定义处理业务
     *
     * @param event
     */
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        ReportLogEvent reportLogEvent = (ReportLogEvent) event;
        LoggingClientNotice loggingClientNotice = reportLogEvent.getLogClientNotice();
        System.out.println("上报日志的服务Id:" + loggingClientNotice.getClientServiceId());
        // 自定义业务处理...
    }
}

19.1. 多监听事件实现

Logging Admin由于采用的是Spring内部提供的SmartApplicationListener方式来监听ReportLogEvent事件,所以只需要添加多个自定义监听实现SmartApplicationListener接口即可。

SmartApplicationListener由于实现了Ordered接口,所以提供优先级配置方法getOrder,与LoggingNotice接口优先级策略一致,值越小优先级越高

详细了解Spring提供的Event/Listener可以访问SpringBoot使用ApplicationEvent&Listener完成业务解耦

20. LoggingAdminFactoryBean

LoggingAdminFactoryBean是配置Logging Admin的必要途径,通过该类可以对Logging Admin进行全方面的配置。

ApiBoot集成Logging Admin FactoryBean示例如下所示:

/**
* instantiation {@link LoggingAdminFactoryBean}
*
* @param dataSource {@link DataSource}
* @return LoggingAdminFactoryBean
*/
@Bean
public LoggingAdminFactoryBean loggingAdminFactoryBean(DataSource dataSource) {
  LoggingAdminFactoryBean factoryBean = new LoggingAdminFactoryBean();
  factoryBean.setDataSource(dataSource);
  factoryBean.setShowConsoleReportLog(apiBootLoggingAdminProperties.isShowConsoleReportLog());
  factoryBean.setFormatConsoleLogJson(apiBootLoggingAdminProperties.isFormatConsoleLogJson());
  logger.info("【LoggingAdminFactoryBean】init successfully.");
  return factoryBean;
}

ApiBoot 集成LoggingAdminFactoryBean详细源码请访问ApiBootLoggingAdminAutoConfiguration

20.1. 设置数据源

通过LoggingAdminFactoryBean#setDataSource方法来设置Logging Admin所需要操作日志数据的数据源,如下所示:

// 设置数据源 
factoryBean.setDataSource(dataSource);

20.2. 控制台输出上报的日志

通过LoggingAdminFactoryBean#setShowConsoleReportLog方法来控制是否在控制台打印Logging Client上报的日志信息,如下所示:

// 设置在控制台输出Logging Client 上报的日志
factoryBean.setShowConsoleReportLog(true);

20.3. 格式化控制台输出日志

通过LoggingAdminFactoryBean#setFormatConsoleLogJson方法来格式化控制台输出的日志,如下所示:

// 格式化控制台输出的日志
factoryBean.setFormatConsoleLogJson(true);
本文由博客一文多发平台 OpenWrite 发布!

恒宇少年
395 声望220 粉丝