`
pzx888
  • 浏览: 13748 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Logback+Osgi配置自动更新问题

    博客分类:
  • OSGI
阅读更多
软件版本
Logback-core-0.9.30
Logback-classic-0.9.30
Osgi equinox
Eclipse 3.7.2
存在问题
logback.xml配置文件,设置自动检测配置更新,<configuration scan="true"  debug="true">,但是启动后,修改配置文件没有自动更新。比如:
<logger name="com.company.server.main" >
		<level value="DEBUG" />
</logger>

level修改为INFO,debug级别日志继续输出
问题分析
经阅读源码,跟踪调试,反复验证,确认是logback与osgi配合使用时,存在的缺陷,将配置文件放在类路径下,比如放在src下,logback会自动在classpath中找到该文件,但是自动检测更新不起作用。(当然是有解决办法的,请看下文)
当把<configuration scan="true"  debug="true">,debug设置为true时,会输出logback内部的一些调试信息。项目启动时会输出:
14:06:35,846 |-INFO in ReconfigureOnChangeFilter{invocationCounter=0} - Will scan for changes in [[D:\workspace\fileaccess\src\test\resources\logback.xml]] every 60 seconds. 
14:06:35,846 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - Adding ReconfigureOnChangeFilter as a turbo filter

很明显,这段日志指的是,每60s会检测指定路径下的配置文件是否有变化,该路径就是你配置文件的绝对路径。
而osgi启动时,会怎么样呢?
14:32:58,509 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [bundleresource://62.fwk918077175/logback.xml]
14:32:58,510 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs multiple times on the classpath.
14:32:58,510 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [bundleresource://62.fwk918077175/logback.xml]
14:32:58,510 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [bundleresource://62.fwk918077175:38/logback.xml]
14:32:58,530 |-INFO in ch.qos.logback.core.joran.spi.ConfigurationWatchList@239a029e - URL [bundleresource://62.fwk918077175/logback.xml] is not of type file
14:32:58,579 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
14:32:58,579 |-INFO in ReconfigureOnChangeFilter{invocationCounter=0} - Will scan for changes in [[]] every 60 seconds. 

请注意以上日志,自动检测的目标是空的,先说结果,就是不能再侦测到任何更新了。原因是osgi自动给配置文件一个URL[bundleresource://62.fwk918077175:38/logback.xml],这导致logback在将该URL放入WatchList时,解析为NULL。而正常的URL应该是这种格式:file://D:\workspace\fileaccess\src\test\resources\logback.xml。 更具体的分析,在本文最后,有兴趣的同学可以继续看看。
先来说说解决办法
问题的原因,是解析文件URL出错,那么如何避免这个问题,办法就是logback的显式指定配置文件路径的办法。
在java启动参数中,加上-Dlogback.configurationFile=D:\eclipse-64bit\*\logback.xml(你自己的配置文件路径),这样配置文件就能被logback成功的加到watchlist中去了。就可以自动检测配置更新了。

详细分析
分析涉及logback源码,可以去官网http://logback.qos.ch/下载。
只提几个启动过程中,配置初始化的关键类,按调用先后顺序。
classic包ContextInitializer类
public void autoConfig() throws JoranException {
    StatusListenerConfigHelper.installIfAsked(loggerContext);
    URL url = findURLOfDefaultConfigurationFile(true);
    if (url != null) {
      configureByResource(url);
    } else {
      BasicConfigurator.configure(loggerContext);
    }
  }
public void configureByResource(URL url) throws JoranException {
    if (url == null) {
      throw new IllegalArgumentException("URL argument cannot be null");
    }
    if (url.toString().endsWith("groovy")) {
      if (EnvUtil.isGroovyAvailable()) {
        // avoid directly referring to GafferConfigurator so as to avoid
        // loading  groovy.lang.GroovyObject . See also http://jira.qos.ch/browse/LBCLASSIC-214
        GafferUtil.runGafferConfiguratorOn(loggerContext, this, url);
      } else {
        StatusManager sm = loggerContext.getStatusManager();
        sm.add(new ErrorStatus("Groovy classes are not available on the class path. ABORTING INITIALIZATION.",
                loggerContext));
      }
    }
    if (url.toString().endsWith("xml")) {
      JoranConfigurator configurator = new JoranConfigurator();
      configurator.setContext(loggerContext);
      configurator.doConfigure(url);
    }
  }

Core包GenericConfigurator类
f
inal public void doConfigure(URL url) throws JoranException {
    try {
      informContextOfURLUsedForConfiguration(getContext(), url);
      URLConnection urlConnection = url.openConnection();
      // per http://jira.qos.ch/browse/LBCORE-105
      // per http://jira.qos.ch/browse/LBCORE-127
      urlConnection.setUseCaches(false);

      InputStream in = urlConnection.getInputStream();
      doConfigure(in);
      in.close();
    } catch (IOException ioe) {
      String errMsg = "Could not open URL [" + url + "].";
      addError(errMsg, ioe);
      throw new JoranException(errMsg, ioe);
    }
  }
static public void informContextOfURLUsedForConfiguration(Context context, URL url) {
    ConfigurationWatchListUtil.setMainWatchURL(context, url);
  }

Core包ConfigurationWatchListUtil类
public static void setMainWatchURL(Context context, URL url) {
    ConfigurationWatchList cwl = getConfigurationWatchList(context);
    if (cwl == null) {
      cwl = new ConfigurationWatchList();
      cwl.setContext(context);
      context.putObject(CoreConstants.CONFIGURATION_WATCH_LIST, cwl);
    } else {
      cwl.clear();
    }
    setConfigurationWatchListResetFlag(context, true);
    cwl.setMainURL(url);
  }

Core包ConfigurationWatchList类
public void setMainURL(URL mainURL) {
    // main url can be null
    this.mainURL = mainURL;
    if (mainURL != null)
      addAsFileToWatch(mainURL);
  }
private void addAsFileToWatch(URL url) {
    File file = convertToFile(url);
    if (file != null) {
      fileWatchList.add(file);
      lastModifiedList.add(file.lastModified());
    }
  }
@SuppressWarnings("deprecation")
  File convertToFile(URL url) {
    String protocol = url.getProtocol();
    if ("file".equals(protocol)) {
      File file = new File(URLDecoder.decode(url.getFile()));
      return file;
    } else {
      addInfo("URL [" + url + "] is not of type file");
      return null;
    }
  }

解析就是convertToFile这里出的问题,URL[bundleresource://62.fwk918077175:38/logback.xml],会返回NULL。所以就没有加入到fileWatchList里面。

ReconfigureOnChangeFilter是检测配置更新的关键类,文章最初提到的日志里,输出每60s检测一次,就是它输出的,它取的watchList就是fileWatchList。
所以,问题已经很明显了。
更多的,请阅读源码。
分享到:
评论

相关推荐

    linux平台centos7系统 - ELK+logback+kafka+nginx 搭建分布式日志分析平台.doc

    【Linux平台CentOS7系统 - ELK+logback+kafka+nginx搭建分布式日志分析平台】 在复杂的IT环境中,日志管理和分析对于诊断问题、优化性能以及确保系统稳定性至关重要。ELK栈(Elasticsearch、Logstash、Kibana)正是...

    SSM+Lucene+logback+Druid开发的开源博客系统

    SSM+Lucene+logback+Druid开发的Java开源博客系统源码 项目描述 网站面向有撰写博客习惯的用户,个人可注册成为网站用户(博主),在系统中创建自己的博文类别、标签,使用Markdown语法创作博文,创作好后将博文...

    SpringBoot+tk.Mybatis整合+yml配置+logback配置

    通过自动配置、内嵌服务器、起步依赖等特性,SpringBoot 可以帮助开发者快速构建可独立运行的Java应用。在“SpringBoot+tk.Mybatis整合+yml配置+logback配置”这个主题中,我们将探讨以下几个关键知识点: 1. **...

    logback+slf4j的JAR包和源码

    只要里面的logback-classic-1.1.7,logback-core-1.1.7,slf4j-api-1.7.21的JAR就可以打印出日志信息,而带有source表示对应的JAR包的源代码。可以要也可以不要

    springboot+springMVC+tk.mybatis+lombook+yml配置+logback-spring日志配置+ueditor源码修改整合

    springboot+springMVC+tk.mybatis+lombook+yml配置+logback-spring日志配置+ueditor源码修改整合 经测试有效,内附数据库文件及测试账号数据,在项目/doc文件夹中

    timber+logback+CashHandler

    "timber+logback+CashHandler"的组合提供了一种高效、可定制的日志管理系统,让我们来深入了解一下这个组合的各个部分。 **Timber** Timber是一个轻量级的日志库,由Square公司开发。它扩展了Android原生的Log类,...

    logback+web项目Demo

    在提供的"Logback+web项目Demo"中,你可以看到如何将Logback集成到一个Web应用程序中,并进行日志输出。这个Demo应该包含了一个简单的Web应用,以及配置好的 `logback.xml` 文件。通过导入Eclipse,你可以直接运行和...

    Logback+slf4j【进阶】【实例】.docx

    总结来说,Logback+SLF4J提供了强大的日志管理能力,不仅能够方便地替换已有的日志系统,还支持动态配置更新和自定义过滤规则,满足各种复杂场景下的日志需求。在实际开发中,灵活运用这些特性有助于优化日志记录,...

    slf4j+logback+springmvc+maven小例子

    在这个“slf4j+logback+springmvc+maven小例子”中,我们看到的是一个结合了这些技术的简单应用。Spring MVC是一个基于Spring框架的轻量级Web MVC框架,它简化了构建交互式、RESTful的Web应用的流程。Maven则是一个...

    logback+springboot的基本使用方式.zip

    而日志系统作为任何应用的重要组成部分,Logback作为SLF4J(Simple Logging Facade for Java)的实现,以其高效、可配置性著称,常被用于SpringBoot项目中。本文将详细介绍如何在SpringBoot项目中集成和使用Logback...

    Spring boot+ES5.4+logback+maven 一个框架空工程

    在这个"Spring boot+ES+logback+maven"的框架空工程中,开发者可以快速开始编写业务逻辑,因为所有基础架构组件已经配置好。Elasticsearch 用于存储和搜索日志,Logback 提供日志记录,Spring Boot 管理整个应用生命...

    logback+slf4j使用

    以下是使用logback+slf4j自定义Appender的详细步骤: 1. **创建Appender类**:首先,你需要创建一个继承自`ch.qos.logback.core.AppenderBase&lt;ILoggingEvent&gt;`的类。在这个类中,你需要覆盖`append()`方法,该方法...

    logback+self4j 进行日志记录

    ** 当程序运行时,SLF4J会自动查找`logback-test.xml`并应用其中的配置。通过控制台或指定的日志文件,我们可以看到按照配置输出的日志信息。 总结来说,理解并正确配置`logback-test.xml`是实现高效日志记录的关键...

    Maven+SpringMVC+MyBatis+Logback+WebSocket

    本项目采用了一种常见的技术栈:“Maven+SpringMVC+MyBatis+Logback+WebSocket”,这是一套强大的组合,适合快速开发中大型企业级应用。接下来,我们将详细探讨这些技术及其相互间的协同工作。 1. Maven: Maven是...

    struts+spring+mybatis+logback+easyui

    标题 "struts+spring+mybatis+logback+easyui" 暗示了这是一个基于Java的Web开发框架集成方案,常用于构建企业级应用。这个组合包括了四个主要组件和一个前端UI库: 1. **Struts**:Struts是Apache软件基金会的一个...

    logback+slf4j打印工具类

    总结来说,"logback+slf4j打印工具类"是一种在Java项目中实现日志记录的有效方式,通过SLF4J的简洁API和Logback的强大功能,可以轻松地定制日志记录策略,例如每天生成一个日志文件。这种工具类的使用,不仅提高了...

    Logback+Slf4j,基于SpringBoot实现日志脱敏.zip

    配置Logback以使用我们的自定义过滤器,我们需要在`logback-spring.xml`配置文件中添加相应的配置。这里,我们可以设置一个特殊的`appender`,并将我们的过滤器附加到这个appender上。同时,为了保证不影响其他日志...

    Logback类库含logback.xml配置文件

    Logback 是为了提供更高效、更灵活的日志记录解决方案而设计的,它不仅继承了 Log4j 的优点,还解决了一些性能和可扩展性问题。在Java应用程序中,日志系统扮演着至关重要的角色,它帮助开发者调试代码,记录错误,...

    logback + slf4j web项目源码

    Logback 提供了比 log4j 更高的性能,并且设计上更注重可配置性和可扩展性。它分为三个主要组件:`ch.qos.logback.core`(核心模块),`ch.qos.logback.classic`(提供了log4j API的实现),以及`ch.qos.logback-...

    springboot+swagger-ui+PageHelper分页+logback+动态定时

    在SpringBoot项目中,我们可以通过配置logback-spring.xml文件来定制日志输出格式、路径、级别等,确保日志管理和分析的便利性。 4. **动态定时任务**,通常我们使用SpringBoot的`@Scheduled`注解来定义定时任务,...

Global site tag (gtag.js) - Google Analytics