集成apollo动态日志取缔logback-spring.xml配置

目录
  • 前言
  • APOLLO动态日志
    • spring日志系统热更新日志级别
    • apollo日志配置变更动态下发
    • 实现日志调整热更新
  • 消灭LOGBACK-SPRING.XML配置
    • Logback加载原理
    • javaBean加载SentryAppender

前言

动态调整线上日志级别是一个非常常见的场景,借助apollo这种配置中心组件非常容易实现。作为apollo的官方技术支持,博主经常在技术群看到有使用者询问apollo是否可以托管logback的配置文件,毕竟有了配置中心后,消灭所有的本地配置全部交给apollo管理是我们的最终目标。可是,apollo不具备直接托管logback-spring.xml配置文件能力,但是,我们可以基于spring和logback的装载机制,完全取缔logback-spring.xml配置,以apollo中的配置驱动。而且,改造后,大大提高了日志系统的灵活性和可扩展性。

APOLLO动态日志

何为apollo动态日志?直接这样说可能会有歧义,以为是apollo里的日志,其实不然。举个简单的例子,比如,我们项目很多地方使用了log.debug()打印日志,为了方便通过日志信息排查问题,但是一般情况下,生产环境的日志级别会配置成info。只有遇到需要排查线上问题的时候才会临时打开debug级别日志。这个时候只能需改配置文件,将日志级别调整成debug,然后重新打包部署验证。不仅流程繁琐耗时,还会破坏当时的"案发现场的环境",导致判断不准确。如果应用具备了apollo动态日志这种能力,就只需在apollo修改下配置然后提交,就可以热更新日志级别,马上打印debug级别日志。这就是所谓的apollo动态日志。实现这个效果,需要具备两个能力,分别由spring和apollo提供

spring日志系统热更新日志级别

spring应用中,spring适配了主流的日志框架,如logback、log4j2等,在这些日志框架之上,又抽象了自己的日志系统服务,这里我们用到了spring的LoggingSystem,用它来热更新日志级别,这个类在日志系统初始化时就添加到了spring的容器中,所以只要在spring的上下文管理范围内,就可以直接注入,以下为主要使用到的api描述:

/**
     * 设置给定日志记录器的日志级别.
     * @param loggerName 要设置的日志记录器的名称({@code null}可用于根日志记录器)。
     * @param level 日志级别
     */
    public void setLogLevel(String loggerName, LogLevel level) {
        throw new UnsupportedOperationException("Unable to set log level");
    }

apollo日志配置变更动态下发

apollo作为分布式配置中心,配置集中管理和配置热更新是其最核心的功能,此外,apollo还提供了配置变更下发监听的功能。基于这个配置监听的设计,实现动态日志就变得非常简单了。而且不仅可以实现日志动态热更,基于这个思路,连接池、数据源等都可以轻松实现。apollo实现监听配置变更有多种方式,可以通过Config实例手动添加,如:

@ApolloConfig
    public Config config;
    public void addConfigChangeListener(){
        config.addChangeListener(changeEvent->{
            System.out.println("config change keys" + changeEvent.changedKeys());
        });
    }

也可以通过注解直接驱动

@ApolloConfigChangeListener
    public void addConfigChangeListener(ConfigChangeEvent changeEvent){
            System.out.println("config change keys" + changeEvent.changedKeys());
    }

实现日志调整热更新

有了上述能力,在结合spring支持的日志加载配置方式,如:
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
可以实现如下代码完成功能,遇到需要调整日志级别时,修改apollo里的配置,即可实时生效

@Configuration
public class LogbackConfiguration {
    private static final Logger logger = LoggerFactory.getLogger(LoggerConfiguration.class);
    private static final String LOGGER_TAG = "logging.level.";
    private final LoggingSystem loggingSystem;
    public LogbackConfiguration(LoggingSystem loggingSystem) {
        this.loggingSystem = loggingSystem;
    }
    @ApolloConfigChangeListener
    private void onChange(ConfigChangeEvent changeEvent) {
        for (String key : changeEvent.changedKeys()) {
            if (this.containsIgnoreCase(key, LOGGER_TAG)) {
                String strLevel = changeEvent.getChange(key).getNewValue();
                LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
                loggingSystem.setLogLevel(key.replace(LOGGER_TAG, ""), level);
                logger.info("logging changed: {},oldValue:{},newValue:{}", key, changeEvent.getChange(key).getOldValue(), strLevel);
            }
        }
    }
    private boolean containsIgnoreCase(String str, String searchStr) {
        if (str == null || searchStr == null) {
            return false;
        }
        int len = searchStr.length();
        int max = str.length() - len;
        for (int i = 0; i <= max; i++) {
            if (str.regionMatches(true, i, searchStr, 0, len)) {
                return true;
            }
        }
        return false;
    }
}

消灭LOGBACK-SPRING.XML配置

在"消灭"logback-xml配置之前,先看下这个配置文件有哪些配置信息,起到了哪些作用,下面贴出一个典型的配置文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
  <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
  <appender name="Sentry" class="io.sentry.logback.SentryAppender">
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>ERROR</level>
    </filter>
  </appender>
  <root level="INFO">
    <appender-ref ref="CONSOLE"/>
    <appender-ref ref="Sentry"/>
  </root>
  <logger name="org.apache.ibatis.session" level="WARN"/>
  <springProfile name="dev">
    <logger name="com.taptap.server" level="DEBUG"/>
    <logger name="com.taptap.commons" level="DEBUG"/>
  </springProfile>
  <springProfile name="prod">
    <logger name="com.taptap.server" level="WARN"/>
    <logger name="com.taptap.commons" level="WARN"/>
  </springProfile>
</configuration>

一个典型的logback配置文件里包含了Appender和日志级别设置的信息,Appender可以理解为日志的输出源。如上贴出的这个配置,添加了两个Appender信息,一个是spring中内置的,将日志输出到控制台的Appender。一个是将error日志信息发送到Sentry应用监控平台的Appender。其他的配置描述了每个包路径不同的日志级别信息。到这里,我们很容易想到,上文已经说过,spring已经支持以logging.level.包名=info这种配置来设置日志系统的日志级别。那么剩下的只要解决Appender的配置就ok了。在这里,其实只需要解决SentryAppender的加载就行,因为consoleAppender spring自己会处理。有了目标和方向,就好办了。以logback-spring.xml配置的信息,最终都会加载成class对象。就和spring.xml配置一样。所以研究的方向就变成了Logback的加载原理的问题。

Logback加载原理

在java的日志生态里,除了响当当的logback、log4j2、apache common log外,还有一个日志框架不得不提,就是sl4j。正因为java生态强大,日志框架层出不穷,所以sl4j出来了,不干实事,专门定义日志标准、规范定义接口。而且,在我们平时的编码过程中,也建议使用sl4j的api,这样,无论底层日志框架实现怎么切换,都不会影响。主流的日志框架都有实现sl4j的接口,spring中日志系统的加载也是面向的sl4j,而不是直接面向日志实现,加载过程是一个自动化的过程,系统会自动扫描实现了sl4j的接口实现,如:

public interface ILoggerFactory {
    public Logger getLogger(String name);
}

每个日志框架都会实现这个接口,如Logback中的LoggerContext。Logback所有的功能都集成在了这个Context中,logback-spring.xml的配置也是为了配置LoggerContext中的属性信息,所有我们只要拿到了LoggerContext实例,问题就解决了一大半。这涉及到sl4j的另一个接口,获取ILoggerFactory实例的接口:

public interface LoggerFactoryBinder {
    public ILoggerFactory getLoggerFactory();
    public String getLoggerFactoryClassStr();
}

Logback的实现类为StaticLoggerBinder,也就是说,我们可以通过StaticLoggerBinder的getLoggerFactory方法拿到LoggerContext实例了。

javaBean加载SentryAppender

拿到Logback的LoggerContext后,就好办了,见代码:

@Configuration
public class LogbackConfiguration {
    private final LoggerContext ctx = (LoggerContext) StaticLoggerBinder.getSingleton().getLoggerFactory();
    @Bean
    @Profile(PROD_ENV)
    public void initSenTry() {
        SentryAppender sentryAppender = new SentryAppender();
        sentryAppender.setContext(ctx);
        ThresholdFilter filter = new ThresholdFilter();
        filter.setLevel(Level.ERROR.levelStr);
        filter.start();
        sentryAppender.addFilter(filter);
        sentryAppender.start();
        ctx.addTurboFilter(new TurboFilter() {
            @Override
            public FilterReply decide(Marker marker, ch.qos.logback.classic.Logger logger, Level level, String format, Object[] params, Throwable t) {
                logger.addAppender(sentryAppender);
                return FilterReply.NEUTRAL;
            }
        });
    }
}

看到这种代码就非常有感觉了,配置文件中的xml其实就是描述了日志组成对象以及对象的属性。在使用java bean的方式配置时需要注意,Logback的设计里,每个日志系统组成实例都有一个start状态属性,上面的start()方法其实不是动作,只是标记了这个属性为true。而在xml里这个属性只要配置了就自动激活为true了,这里必须显示的start()一下。解决了日志级别配置和Appender配置后,Logback-spring.xml文件就可以彻底的删除了

以上就是集成apollo动态日志取缔logback-spring.xml配置的详细内容,更多关于apollo动取缔logback-spring.xml配置的资料请关注我们其它相关文章!

(0)

相关推荐

  • 使用Springboot整合Apollo配置中心

    Apollo简介 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置管理场景. 官方网站 https://github.com/ctripcorp/apollo Apollo 环境搭建 详细步骤参见: https://github.com/ctripcorp/apollo/wiki/Quick-Start 官网已经很详细的说明了操作步骤.但是有很多前置条件才能完

  • SpringBoot配置Apollo代码实例

    这篇文章主要介绍了SpringBoot配置Apollo代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Windows环境安装下载,参考:https://github.com/ctripcorp/apollo 项目引用 <dependency> <groupId>com.ctrip.framework.apollo</groupId> <artifactId>apollo-client</art

  • apollo与springboot集成实现动态刷新配置的教程详解

    分布式apollo简介 Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性. 本文主要介绍如何使用apollo与springboot实现动态刷新配置,如果之前不了解apollo可以查看如下文档 https://github.com/ctripcorp/apollo 学习了解一下apollo,再来查看本文 正文 apollo与spring实现动态刷新配置本文主要演示2种刷新,一种

  • springboot logback如何从apollo配置中心读取变量

    目录 springboot logback 从apollo配置中心读取变量 1.在apollo配置中心添加 2.项目的application.yml配置文件配置如下 3.在logback.xml配置springProperty标签 SpringBoot Logback无法获取配置中心属性 如何解决 解决方案 springboot logback 从apollo配置中心读取变量 1.在apollo配置中心添加 logback-config.properties配置文件 2.项目的applicati

  • SpringBoot整合Apollo配置中心快速使用详解

    目录 一.简介 二.使用 1. 测试项目搭建 2. Apollo配置中心的配置 3. 项目启动与测试 4.常见整合问题 附录 一.简介 1.Apollo 是什么?Apollo(阿波罗)是携程框架部门研发的分布式配置中心.服务端基于Spring Boot和Spring Cloud开发. 2.为什么要使用Apollo? 安全性:配置跟随源代码保存在代码库中,容易造成配置泄漏 时效性:普通方式配置,修改配置,需要重启服务才能生效 局限性:无法支持动态调整:例如日志开关.功能开关 二.使用 1. 测试项

  • 集成apollo动态日志取缔logback-spring.xml配置

    目录 前言 APOLLO动态日志 spring日志系统热更新日志级别 apollo日志配置变更动态下发 实现日志调整热更新 消灭LOGBACK-SPRING.XML配置 Logback加载原理 javaBean加载SentryAppender 前言 动态调整线上日志级别是一个非常常见的场景,借助apollo这种配置中心组件非常容易实现.作为apollo的官方技术支持,博主经常在技术群看到有使用者询问apollo是否可以托管logback的配置文件,毕竟有了配置中心后,消灭所有的本地配置全部交给a

  • Spring Boot日志技术logback原理及配置解析

    一.logback日志技术介绍 Spring Boot中使用的日志技术为logback.其与Log4J都出自同一人,性能要优于Log4J,是Log4J的替代者. 在Spring Boot中若要使用logback,则需要具有spring-boot-starter-logging依赖,而该依赖被spring-boot-starter-web所依赖,即不用直接导入spring-boot-starter-logging依赖. 二.添加配置属性 该文件名为logback.xml,且必须要放在src/mai

  • 使用log4j2自定义配置文件位置和文件名(附log4j2.xml配置实例)

    目录 log4j2自定义配置文件位置和文件名 web.xml配置 生效配置文件 日志配置文件实例 log4j2.xml配置及例子 1.使用log4j2需要下载包 2.配置文件可以有三种格式 3.日志记录有两种方法 4.我用的xml的配置 log4j2自定义配置文件位置和文件名 我们使用log4j2一般做法是将log4j2.xml文件放在资源文件夹根目录.对于有强迫症的开发者来说,我更喜欢在资源文件夹下新建包或文件夹,然后把配置文件放在里面.本博客将介绍如何自定义log4j2.xml文件的位置和文

  • 详解Spring Boot配置使用Logback进行日志记录的实战

    spring Boot实战之配置使用Logback进行日志记录 ,分享给大家 在这篇文章中我们将讨论在Spring Boot中使用Logback,在Spring Boot中使用Logback很简单 1.为了测试我们新建两个类 package com.xiaofangtech.sunt.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.an

  • 如何修改覆盖spring boot默认日志策略logback详解

    背景 Spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如:Java Util Logging,Log4J, Log4J2和Logback.每种Logger都可以通过配置使用控制台或者文件输出日志内容. 默认日志Logback SLF4J--Simple Logging Facade For Java,它是一个针对于各类Java日志框架的统一Facade抽象.Java日志框架众多--常用的有java.util.logging, log

  • spring+apollo动态获取yaml格式的配置方式

    默认spring装载的都是.properties格式的配置文件,但是有时我们需要定义list或者map类型的配置,那么yaml就具有优势. 以下演示利用apollo来完成自动更新ip白名单的功能 1.重写配置工厂 public class YmlPropertySourceFactory extends DefaultPropertySourceFactory { public PropertySource<?> createPropertySource(String name, Encode

  • Java接口测试之日志框架Logback的具体使用

    目录 一.引言 二.前言 三.LogBack.Slf4j和Log4j之间的关系 四.默认日志Logback 五.配置详解 1.添加日志依赖 2.配置文件 六.多环境日志输出 七.单元测试 八.工程目录 九.总结 一.引言 对于一个成熟的接口测试框架,日志管理这个是必不可少的.在开发和调试阶段,日志可以帮助我们更快的定位问题:而在测试的运维过程中,日志系统又可以帮助我们记录大部分的异常信息,通 二.前言 Spring Boot 在所有内部日志中使用Commons Logging,但是默认配置也提供

  • 通过Spring Boot配置动态数据源访问多个数据库的实现代码

    之前写过一篇博客<Spring+Mybatis+Mysql搭建分布式数据库访问框架>描述如何通过Spring+Mybatis配置动态数据源访问多个数据库.但是之前的方案有一些限制(原博客中也描述了):只适用于数据库数量不多且固定的情况.针对数据库动态增加的情况无能为力. 下面讲的方案能支持数据库动态增删,数量不限. 数据库环境准备 下面一Mysql为例,先在本地建3个数据库用于测试.需要说明的是本方案不限数据库数量,支持不同的数据库部署在不同的服务器上.如图所示db_project_001.d

  • 浅谈SpringBoot集成Quartz动态定时任务

    SpringBoot自带schedule 沿用的springboot少xml配置的优良传统,本身支持表达式等多种定时任务 注意在程序启动的时候加上@EnableScheduling @Scheduled(cron="0/5 * * * * ?") public void job(){ System.out.println("每五秒执行一次"); } 为什么要使用Quartz 多任务情况下,quartz更容易管理,可以实现动态配置 执行时间表达式: 表达式示例: 集成

  • Spring使用AspectJ注解和XML配置实现AOP

    本文演示的是Spring中使用AspectJ注解和XML配置两种方式实现AOP 下面是使用AspectJ注解实现AOP的Java Project 首先是位于classpath下的applicationContext.xml文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmln

随机推荐