Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spring boot用logback做日志,logback-spring.xml中<springProperty>属性无法替换 #1243

Closed
gudegg opened this issue Jul 11, 2018 · 27 comments
Labels
feature request Categorizes issue as related to a new feature.

Comments

@gudegg
Copy link

gudegg commented Jul 11, 2018

我是在Spring Boot初始bootstrap阶段注入配置 apollo.bootstrap.enabled = true
跟了下代码
class SpringApplication

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
                      //<springProperty>属性在这步就会从environment获取
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			//ApolloApplicationContextInitializer在这里才会初始化,因此导致<springProperty>获取不到配置中心的属性
                        prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
@nobodyiam
Copy link
Member

log这块一般是在加载完远端配置后重新刷新实现的,你的placeholder是放什么配置?

如果是logging level的话,可以参考 https://github.com/ctripcorp/apollo-use-cases/tree/master/spring-cloud-logger

@gudegg
Copy link
Author

gudegg commented Jul 12, 2018

我是配置日志路径 不使用apollo的话 配置文件写入custom.logging.logpath=xxxx是能生效,使用后无法生效
logback-spring.xml:

 <springProperty name="LOG_PATH" scope="context" source="custom.logging.logpath"  defaultValue="/opt/logs/"/>

    <appender name="RootRollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/root.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>10</maxHistory>
        </rollingPolicy>
    </appender>

@gudegg
Copy link
Author

gudegg commented Jul 12, 2018

看了下spring cloud config ,他会对日志重新初始化,你们也可以修复下 @nobodyiam

public class PropertySourceBootstrapConfiguration implements
		ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered 
	@Override
	public void initialize(ConfigurableApplicationContext applicationContext) {
		CompositePropertySource composite = new CompositePropertySource(
				BOOTSTRAP_PROPERTY_SOURCE_NAME);
		AnnotationAwareOrderComparator.sort(this.propertySourceLocators);
		boolean empty = true;
		ConfigurableEnvironment environment = applicationContext.getEnvironment();
		for (PropertySourceLocator locator : this.propertySourceLocators) {
			PropertySource<?> source = null;
			source = locator.locate(environment);
			if (source == null) {
				continue;
			}
			logger.info("Located property source: " + source);
			composite.addPropertySource(source);
			empty = false;
		}
		if (!empty) {
			MutablePropertySources propertySources = environment.getPropertySources();
			String logConfig = environment.resolvePlaceholders("${logging.config:}");
			LogFile logFile = LogFile.get(environment);
			if (propertySources.contains(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
				propertySources.remove(BOOTSTRAP_PROPERTY_SOURCE_NAME);
			}
			insertPropertySources(propertySources, composite);
                        //重新初始化
			reinitializeLoggingSystem(environment, logConfig, logFile);
			setLogLevels(applicationContext, environment);
			handleIncludedProfiles(environment);
		}
	}

	private void reinitializeLoggingSystem(ConfigurableEnvironment environment,
			String oldLogConfig, LogFile oldLogFile) {
		Map<String, Object> props = Binder.get(environment)
				.bind("logging", Bindable.mapOf(String.class, Object.class)).orElseGet(Collections::emptyMap);
		if (!props.isEmpty()) {
			String logConfig = environment.resolvePlaceholders("${logging.config:}");
			LogFile logFile = LogFile.get(environment);
			LoggingSystem system = LoggingSystem
					.get(LoggingSystem.class.getClassLoader());
			try {
				ResourceUtils.getURL(logConfig).openStream().close();
				// Three step initialization that accounts for the clean up of the logging
				// context before initialization. Spring Boot doesn't initialize a logging
				// system that hasn't had this sequence applied (since 1.4.1).
				system.cleanUp();
				system.beforeInitialize();
				system.initialize(new LoggingInitializationContext(environment),
						logConfig, logFile);
			}
			catch (Exception ex) {
				PropertySourceBootstrapConfiguration.logger
						.warn("Logging config file location '" + logConfig
								+ "' cannot be opened and will be ignored");
			}
		}
	}
}

@nobodyiam
Copy link
Member

多谢建议,这块其实之前也有讨论过的,详见 #1211

@gudegg
Copy link
Author

gudegg commented Jul 12, 2018

spring cloud 只会当包含有logging前缀的属性才会刷新日志配置,这样是否有问题 如果自定义参数不是logging开头就无法刷新替换掉

@nobodyiam
Copy link
Member

可以测试一下,不过logging这块感觉是耦合比较重的,代码不太好写,包括spring cloud config这块也是打了个补丁。

@gudegg
Copy link
Author

gudegg commented Jul 13, 2018

我认为应该把日志刷新加到ApolloApplicationContextInitializer里去,ApolloApplicationContextInitializer本来就是专门为spring boot提供,spring boot具备这个能力,可能要考虑到的问题就是对于spring boot低版本的兼容问题,看了下LoggingInitializationContext最低需要1.3.0.RELEASE,我们直接捕获这个异常,之后的版本没问题。
apollo

@nobodyiam
Copy link
Member

这个建议不错

@chwwww
Copy link

chwwww commented Jul 15, 2018

您好请教一下:想要将logback.xml放入apollo中,开启apollo.bootstrap.enabled = true,就可以了吗?

@nobodyiam
Copy link
Member

@chwwww spring boot应该是放logback-spring.xml,或者可以放spring boot的配置,如logging.level.xx=error,具体参考一下 https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html

另外,如果有些配置如logging level需要通过apollo动态刷新的话,可以参考下 https://github.com/ctripcorp/apollo-use-cases/tree/master/spring-cloud-logger,后续我们可能会支持动态默认刷新。

@chwwww
Copy link

chwwww commented Jul 16, 2018

@nobodyiam 您好,我将整个logback-spring.xml作为namespace放入apollo。目前效果是读取不到apollo上的日志相关配置。已经开启了apollo.bootstrap.enabled = true

@taccisum
Copy link

@nobodyiam @gudegg 我也碰到了这个问题,想请问下目前有相对简单的解决方案吗

@gudegg
Copy link
Author

gudegg commented Aug 22, 2018

@taccisum 自己改了下源码编译gudegg@8f82906

@taccisum
Copy link

@gudegg 有点小问题,这样做的话logging system会加载两次,每次启动应用第一次加载都会报一大堆错... 强迫症看着难受

@gudegg
Copy link
Author

gudegg commented Aug 22, 2018

@taccisum 你logback改的是什么内容?

@taccisum
Copy link

@gudegg 一个写redis的appender,连接不上redis时就会抛异常

@gudegg
Copy link
Author

gudegg commented Aug 22, 2018

@taccisum 不知道有没有更前置的加载Apollo方法,目前spring cloud config也只支持logging前缀的配置重刷 ,你这个应该是加载redis地址,我这么改确实会有挺多问题。 spring-cloud/spring-cloud-commons#392

@nobodyiam
Copy link
Member

一般日志需要动态调整的是logging level,针对这个我们提供了一个sample:https://github.com/ctripcorp/apollo-use-cases/tree/master/spring-cloud-logger

@nobodyiam
Copy link
Member

1.2.0版本已经支持Spring Boot中Apollo的加载顺序放到日志系统加载之前,从而可以支持日志配置放在Apollo管理(如logging.level.root=info或logback-spring.xml中的参数),可以尝试一下。

@wangnanyang
Copy link

只升级apollo-client好像不可以,是需要同时升级配置中心服务吗?

@wangnanyang
Copy link

配置中心与客户端都升级了,还是不行,请问有使用的示例吗?

@nobodyiam
Copy link
Member

@wangnanyang 只要升级apollo-client就可以了,有一个新的配置项apollo.bootstrap.eagerLoad.enabled=true,具体看下java客户端使用文档

@shuliu8
Copy link

shuliu8 commented Dec 17, 2018

@nobodyiam 你好,打算通过apollo动态修改日志级别,但是没起到作用; 我总共改的地方三块:
一、是在apollo 配置中心加logging.level
二 、apollo 各个服务都升级到1.2.0了
三、就是在application.yml 里加了上面apollo.bootstrap.eagerLoad.enabled=true 的配置
还有哪里需要改的吗

@nobodyiam
Copy link
Member

apollo.bootstrap.enabled=true这个也要配置的

@shuliu8
Copy link

shuliu8 commented Dec 18, 2018

配置好了起作用了;但是好像改了日志级别之后必须重启应用才能生效是吗

@nobodyiam
Copy link
Member

@nobodyiam
Copy link
Member

case先关闭了,如还有问题,可以提供更多信息,或进群交流。

@nobodyiam nobodyiam added feature request Categorizes issue as related to a new feature. and removed enhancement labels Nov 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Categorizes issue as related to a new feature.
Projects
None yet
Development

No branches or pull requests

6 participants