软件版本:
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搭建分布式日志分析平台】 在复杂的IT环境中,日志管理和分析对于诊断问题、优化性能以及确保系统稳定性至关重要。ELK栈(Elasticsearch、Logstash、Kibana)正是...
SSM+Lucene+logback+Druid开发的Java开源博客系统源码 项目描述 网站面向有撰写博客习惯的用户,个人可注册成为网站用户(博主),在系统中创建自己的博文类别、标签,使用Markdown语法创作博文,创作好后将博文...
通过自动配置、内嵌服务器、起步依赖等特性,SpringBoot 可以帮助开发者快速构建可独立运行的Java应用。在“SpringBoot+tk.Mybatis整合+yml配置+logback配置”这个主题中,我们将探讨以下几个关键知识点: 1. **...
只要里面的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源码修改整合 经测试有效,内附数据库文件及测试账号数据,在项目/doc文件夹中
"timber+logback+CashHandler"的组合提供了一种高效、可定制的日志管理系统,让我们来深入了解一下这个组合的各个部分。 **Timber** Timber是一个轻量级的日志库,由Square公司开发。它扩展了Android原生的Log类,...
在提供的"Logback+web项目Demo"中,你可以看到如何将Logback集成到一个Web应用程序中,并进行日志输出。这个Demo应该包含了一个简单的Web应用,以及配置好的 `logback.xml` 文件。通过导入Eclipse,你可以直接运行和...
总结来说,Logback+SLF4J提供了强大的日志管理能力,不仅能够方便地替换已有的日志系统,还支持动态配置更新和自定义过滤规则,满足各种复杂场景下的日志需求。在实际开发中,灵活运用这些特性有助于优化日志记录,...
在这个“slf4j+logback+springmvc+maven小例子”中,我们看到的是一个结合了这些技术的简单应用。Spring MVC是一个基于Spring框架的轻量级Web MVC框架,它简化了构建交互式、RESTful的Web应用的流程。Maven则是一个...
而日志系统作为任何应用的重要组成部分,Logback作为SLF4J(Simple Logging Facade for Java)的实现,以其高效、可配置性著称,常被用于SpringBoot项目中。本文将详细介绍如何在SpringBoot项目中集成和使用Logback...
在这个"Spring boot+ES+logback+maven"的框架空工程中,开发者可以快速开始编写业务逻辑,因为所有基础架构组件已经配置好。Elasticsearch 用于存储和搜索日志,Logback 提供日志记录,Spring Boot 管理整个应用生命...
以下是使用logback+slf4j自定义Appender的详细步骤: 1. **创建Appender类**:首先,你需要创建一个继承自`ch.qos.logback.core.AppenderBase<ILoggingEvent>`的类。在这个类中,你需要覆盖`append()`方法,该方法...
** 当程序运行时,SLF4J会自动查找`logback-test.xml`并应用其中的配置。通过控制台或指定的日志文件,我们可以看到按照配置输出的日志信息。 总结来说,理解并正确配置`logback-test.xml`是实现高效日志记录的关键...
本项目采用了一种常见的技术栈:“Maven+SpringMVC+MyBatis+Logback+WebSocket”,这是一套强大的组合,适合快速开发中大型企业级应用。接下来,我们将详细探讨这些技术及其相互间的协同工作。 1. Maven: Maven是...
标题 "struts+spring+mybatis+logback+easyui" 暗示了这是一个基于Java的Web开发框架集成方案,常用于构建企业级应用。这个组合包括了四个主要组件和一个前端UI库: 1. **Struts**:Struts是Apache软件基金会的一个...
总结来说,"logback+slf4j打印工具类"是一种在Java项目中实现日志记录的有效方式,通过SLF4J的简洁API和Logback的强大功能,可以轻松地定制日志记录策略,例如每天生成一个日志文件。这种工具类的使用,不仅提高了...
配置Logback以使用我们的自定义过滤器,我们需要在`logback-spring.xml`配置文件中添加相应的配置。这里,我们可以设置一个特殊的`appender`,并将我们的过滤器附加到这个appender上。同时,为了保证不影响其他日志...
Logback 是为了提供更高效、更灵活的日志记录解决方案而设计的,它不仅继承了 Log4j 的优点,还解决了一些性能和可扩展性问题。在Java应用程序中,日志系统扮演着至关重要的角色,它帮助开发者调试代码,记录错误,...
Logback 提供了比 log4j 更高的性能,并且设计上更注重可配置性和可扩展性。它分为三个主要组件:`ch.qos.logback.core`(核心模块),`ch.qos.logback.classic`(提供了log4j API的实现),以及`ch.qos.logback-...
在SpringBoot项目中,我们可以通过配置logback-spring.xml文件来定制日志输出格式、路径、级别等,确保日志管理和分析的便利性。 4. **动态定时任务**,通常我们使用SpringBoot的`@Scheduled`注解来定义定时任务,...