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

解决日志系统未初始化完成时,apollo 的加载日志没法输出问题 #3677

Merged
merged 29 commits into from
May 23, 2021
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fe75b4d
add tech-support-qq-4.png
klboke May 16, 2019
99bf97a
Update README.md
klboke May 16, 2019
1579f41
Merge remote-tracking branch 'upstream/master'
klboke Nov 11, 2020
9f65eed
Merge remote-tracking branch 'upstream/master'
klboke Dec 9, 2020
d7d3fd9
Enhance the user experience in the scenario of submitting duplicate keys
klboke Dec 11, 2020
7329fab
Merge branch 'master' into master
nobodyiam Dec 12, 2020
5def448
Modify the key-value conflict exception prompt, adjust the code style
klboke Dec 12, 2020
6942564
Merge branch 'master' into master
nobodyiam Dec 12, 2020
0fc1f91
Merge remote-tracking branch 'upstream/master'
klboke Dec 19, 2020
61ad016
Merge remote-tracking branch 'origin/master'
klboke Dec 19, 2020
587ce33
rge remote-tracking branch 'upstream/master'
klboke Mar 1, 2021
9de6563
Merge remote-tracking branch 'upstream/master'
klboke Mar 8, 2021
9aab632
Merge remote-tracking branch 'upstream/master'
klboke Mar 25, 2021
050dd0a
Merge branch 'ctripcorp:master' into master
klboke May 10, 2021
5a64035
Merge branch 'master' of github.com:klboke/apollo
klboke May 10, 2021
d053f4a
feat[apollo-client]: Solve the problem that the log before the log sy…
klboke May 11, 2021
41acba5
Merge branch 'master' into DeferredLog
nobodyiam May 15, 2021
b1ce641
refactor(DeferredLog): Delay log refactoring
klboke May 19, 2021
6357c8f
Merge remote-tracking branch 'origin/DeferredLog' into DeferredLog
klboke May 19, 2021
93560e8
fix(DeferredLog): Fix log level definition error
klboke May 19, 2021
072c58a
feat(DeferredLog): Complete test cases
klboke May 20, 2021
ea37efc
fix(DeferredLog): Fix problems with test cases
klboke May 21, 2021
65c7714
refactor(DeferredLog): Remove useless packages
klboke May 21, 2021
f47fc44
refactor(DeferredLog): DeferredLogCache only stores logs
klboke May 21, 2021
2c4fde5
refactor(DeferredLog): AbstractConfigFile adds delay log
klboke May 21, 2021
2532a7f
refactor(DeferredLog): Improve delayed log implementation
klboke May 21, 2021
6ea77e5
Merge branch 'master' into DeferredLog
nobodyiam May 21, 2021
ee2339c
fix(DeferredLog): Fix the problem of test case compilation failure, a…
klboke May 21, 2021
4eecb14
refactor(DeferredLog): DeferredLogCache method reconstruction
klboke May 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.ctrip.framework.apollo.internals;

import com.ctrip.framework.apollo.core.utils.DeferredLoggerFactory;
import com.ctrip.framework.apollo.enums.ConfigSourceType;
import java.io.IOException;
import java.io.InputStream;
Expand All @@ -13,7 +14,6 @@
import java.util.concurrent.atomic.AtomicReference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ctrip.framework.apollo.core.utils.ClassLoaderUtil;
import com.ctrip.framework.apollo.enums.PropertyChangeType;
Expand All @@ -29,7 +29,8 @@
* @author Jason Song(song_s@ctrip.com)
*/
public class DefaultConfig extends AbstractConfig implements RepositoryChangeListener {
private static final Logger logger = LoggerFactory.getLogger(DefaultConfig.class);

private static final Logger logger = DeferredLoggerFactory.getLogger(DefaultConfig.class);
klboke marked this conversation as resolved.
Show resolved Hide resolved
klboke marked this conversation as resolved.
Show resolved Hide resolved
private final String m_namespace;
private final Properties m_resourceProperties;
private final AtomicReference<Properties> m_configProperties;
Expand Down Expand Up @@ -92,7 +93,9 @@ public String getProperty(String key, String defaultValue) {
}

if (value == null && m_configProperties.get() == null && m_warnLogRateLimiter.tryAcquire()) {
logger.warn("Could not load config for namespace {} from Apollo, please check whether the configs are released in Apollo! Return default value now!", m_namespace);
logger.warn(
"Could not load config for namespace {} from Apollo, please check whether the configs are released in Apollo! Return default value now!",
m_namespace);
}

return value == null ? defaultValue : value;
Expand Down Expand Up @@ -136,7 +139,8 @@ public synchronized void onRepositoryChange(String namespace, Properties newProp
Properties newConfigProperties = propertiesFactory.getPropertiesInstance();
newConfigProperties.putAll(newProperties);

Map<String, ConfigChange> actualChanges = updateAndCalcConfigChanges(newConfigProperties, sourceType);
Map<String, ConfigChange> actualChanges = updateAndCalcConfigChanges(newConfigProperties,
sourceType);

//check double checked result
if (actualChanges.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.core.enums.Env;
import com.ctrip.framework.apollo.core.spi.MetaServerProvider;
import com.ctrip.framework.apollo.core.utils.DeferredLoggerFactory;
import com.ctrip.framework.foundation.Foundation;
import com.google.common.base.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DefaultMetaServerProvider implements MetaServerProvider {

public static final int ORDER = 0;
private static final Logger logger = LoggerFactory.getLogger(DefaultMetaServerProvider.class);
private static final Logger logger = DeferredLoggerFactory
.getLogger(DefaultMetaServerProvider.class);

private final String metaServerAddress;

Expand All @@ -36,7 +37,8 @@ private String initMetaServerAddress() {
}

if (Strings.isNullOrEmpty(metaAddress)) {
logger.warn("Could not find meta server address, because it is not available in neither (1) JVM system property 'apollo.meta', (2) OS env variable 'APOLLO_META' (3) property 'apollo.meta' from server.properties nor (4) property 'apollo.meta' from app.properties");
logger.warn(
"Could not find meta server address, because it is not available in neither (1) JVM system property 'apollo.meta', (2) OS env variable 'APOLLO_META' (3) property 'apollo.meta' from server.properties nor (4) property 'apollo.meta' from app.properties");
} else {
metaAddress = metaAddress.trim();
logger.info("Located meta services from apollo.meta configuration: {}!", metaAddress);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.core.utils.DeferredLogger;
import com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory;
import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants;
import com.ctrip.framework.apollo.spring.util.SpringInjector;
Expand Down Expand Up @@ -91,7 +92,8 @@ public void initialize(ConfigurableApplicationContext context) {
protected void initialize(ConfigurableEnvironment environment) {

if (environment.getPropertySources().contains(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME)) {
//already initialized
//already initialized, replay the logs that were printed before the logging system was initialized
DeferredLogger.replayTo();
return;
}

Expand Down Expand Up @@ -160,6 +162,7 @@ public void postProcessEnvironment(ConfigurableEnvironment configurableEnvironme
Boolean bootstrapEnabled = configurableEnvironment.getProperty(PropertySourcesConstants.APOLLO_BOOTSTRAP_ENABLED, Boolean.class, false);

if (bootstrapEnabled) {
DeferredLogger.enable();
initialize(configurableEnvironment);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import com.ctrip.framework.apollo.core.utils.DeferredLoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ctrip.framework.apollo.core.spi.MetaServerProvider;
import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;
Expand All @@ -25,36 +25,39 @@
import com.google.common.collect.Maps;

/**
* The meta domain will try to load the meta server address from MetaServerProviders, the default ones are:
* The meta domain will try to load the meta server address from MetaServerProviders, the default
* ones are:
*
* <ul>
* <li>com.ctrip.framework.apollo.core.internals.LegacyMetaServerProvider</li>
* </ul>
*
* <p>
* If no provider could provide the meta server url, the default meta url will be used(http://apollo.meta).
* <br />
*
* <p>
* 3rd party MetaServerProvider could be injected by typical Java Service Loader pattern.
*
* @see com.ctrip.framework.apollo.core.internals.LegacyMetaServerProvider
*/
public class MetaDomainConsts {

public static final String DEFAULT_META_URL = "http://apollo.meta";

// env -> meta server address cache
private static final Map<Env, String> metaServerAddressCache = Maps.newConcurrentMap();
private static volatile List<MetaServerProvider> metaServerProviders = null;

private static final long REFRESH_INTERVAL_IN_SECOND = 60;// 1 min
private static final Logger logger = LoggerFactory.getLogger(MetaDomainConsts.class);
private static final Logger logger = DeferredLoggerFactory.getLogger(MetaDomainConsts.class);
// comma separated meta server address -> selected single meta server address cache
private static final Map<String, String> selectedMetaServerAddressCache = Maps.newConcurrentMap();
private static final AtomicBoolean periodicRefreshStarted = new AtomicBoolean(false);

private static final Object LOCK = new Object();

/**
* Return one meta server address. If multiple meta server addresses are configured, will select one.
* Return one meta server address. If multiple meta server addresses are configured, will select
* one.
*/
public static String getDomain(Env env) {
String metaServerAddress = getMetaServerAddress(env);
Expand All @@ -66,7 +69,8 @@ public static String getDomain(Env env) {
}

/**
* Return meta server address. If multiple meta server addresses are configured, will return the comma separated string.
* Return meta server address. If multiple meta server addresses are configured, will return the
* comma separated string.
*/
public static String getMetaServerAddress(Env env) {
if (!metaServerAddressCache.containsKey(env)) {
Expand Down Expand Up @@ -108,7 +112,8 @@ private static void initMetaServerAddress(Env env) {
}

private static List<MetaServerProvider> initMetaServerProviders() {
Iterator<MetaServerProvider> metaServerProviderIterator = ServiceBootstrap.loadAll(MetaServerProvider.class);
Iterator<MetaServerProvider> metaServerProviderIterator = ServiceBootstrap
.loadAll(MetaServerProvider.class);

List<MetaServerProvider> metaServerProviders = Lists.newArrayList(metaServerProviderIterator);

Expand All @@ -126,11 +131,12 @@ public int compare(MetaServerProvider o1, MetaServerProvider o2) {
/**
* Select one available meta server from the comma separated meta server addresses, e.g.
* http://1.2.3.4:8080,http://2.3.4.5:8080
*
* <p>
* <br />
*
* In production environment, we still suggest using one single domain like http://config.xxx.com(backed by software
* load balancers like nginx) instead of multiple ip addresses
* <p>
* In production environment, we still suggest using one single domain like
* http://config.xxx.com(backed by software load balancers like nginx) instead of multiple ip
* addresses
*/
private static String selectMetaServerAddress(String metaServerAddresses) {
String metaAddressSelected = selectedMetaServerAddressCache.get(metaServerAddresses);
Expand All @@ -149,7 +155,8 @@ private static String selectMetaServerAddress(String metaServerAddresses) {
private static void updateMetaServerAddresses(String metaServerAddresses) {
logger.debug("Selecting meta server address for: {}", metaServerAddresses);

Transaction transaction = Tracer.newTransaction("Apollo.MetaService", "refreshMetaServerAddress");
Transaction transaction = Tracer
.newTransaction("Apollo.MetaService", "refreshMetaServerAddress");
transaction.addData("Url", metaServerAddresses);

try {
Expand Down Expand Up @@ -177,7 +184,8 @@ private static void updateMetaServerAddresses(String metaServerAddresses) {
}

if (!serverAvailable) {
logger.warn("Could not find available meta server for configured meta server addresses: {}, fallback to: {}",
logger.warn(
"Could not find available meta server for configured meta server addresses: {}, fallback to: {}",
metaServerAddresses, selectedMetaServerAddressCache.get(metaServerAddresses));
}

Expand All @@ -202,8 +210,9 @@ public void run() {
updateMetaServerAddresses(metaServerAddresses);
}
} catch (Throwable ex) {
logger.warn(String.format("Refreshing meta server address failed, will retry in %d seconds",
REFRESH_INTERVAL_IN_SECOND), ex);
logger
.warn(String.format("Refreshing meta server address failed, will retry in %d seconds",
REFRESH_INTERVAL_IN_SECOND), ex);
}
}
}, REFRESH_INTERVAL_IN_SECOND, REFRESH_INTERVAL_IN_SECOND, TimeUnit.SECONDS);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package com.ctrip.framework.apollo.core.utils;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.slf4j.Logger;
import org.slf4j.event.Level;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
* Delayed log printing utility class, used only for logging when Apollo is initialized
*
* @author kl (http://kailing.pub)
* @since 2021/5/11
*/
final class DeferredLogCache {

public static final int MAX_LOG_SIZE = 1000;
private static final AtomicInteger LOG_INDEX = new AtomicInteger(0);
private static final Cache<Integer, Line> LOG_CACHE = CacheBuilder.newBuilder()
.maximumSize(MAX_LOG_SIZE)
.expireAfterWrite(1, TimeUnit.MINUTES)
.build();

private DeferredLogCache() {
}


public static void debug(Logger logger, String message, Object... objects) {
add(logger, Level.DEBUG, message, objects, null);
}

public static void info(Logger logger, String message, Object... objects) {
add(logger, Level.INFO, message, objects, null);
}

public static void warn(Logger logger, String message, Object... objects) {
add(logger, Level.WARN, message, objects, null);
}

public static void error(Logger logger, String message, Throwable throwable) {
add(logger, Level.ERROR, message, null, throwable);
}

private static void add(Logger logger, Level level, String message, Object[] objects,
Throwable throwable) {
Line logLine = new Line(level, message, objects, throwable, logger);
LOG_CACHE.put(LOG_INDEX.incrementAndGet(), logLine);
}

public static void replayTo() {
for (int i = 1; i <= LOG_INDEX.get(); i++) {
Line logLine = LOG_CACHE.getIfPresent(i);
assert logLine != null;
Logger logger = logLine.getLogger();
Level level = logLine.getLevel();
String message = logLine.getMessage();
Object[] objects = logLine.getObjects();
Throwable throwable = logLine.getThrowable();
logTo(logger, level, message, objects, throwable);
}
clear();
}

public static void clear() {
klboke marked this conversation as resolved.
Show resolved Hide resolved
LOG_CACHE.invalidateAll();
LOG_INDEX.set(0);
}

public static long logSize() {
klboke marked this conversation as resolved.
Show resolved Hide resolved
return LOG_CACHE.size();
}

static void logTo(Logger logger, Level level, String message, Object[] objects,
klboke marked this conversation as resolved.
Show resolved Hide resolved
Throwable throwable) {
switch (level) {
case DEBUG:
logger.debug(message, objects);
return;
case INFO:
logger.info(message, objects);
return;
case WARN:
logger.warn(message, objects);
return;
case ERROR:
logger.error(message, throwable);
break;
default:
throw new IllegalStateException("Unexpected value: " + level);
}
}

static class Line {
klboke marked this conversation as resolved.
Show resolved Hide resolved

private final Level level;

private final String message;

private final Object[] objects;

private final Throwable throwable;

private final Logger logger;

Line(Level level, String message, Object[] objects, Throwable throwable, Logger logger) {
this.level = level;
this.message = message;
this.objects = objects;
this.throwable = throwable;
this.logger = logger;
}

public Object[] getObjects() {
return objects;
}

public Logger getLogger() {
return logger;
}

Level getLevel() {
return this.level;
}

String getMessage() {
return this.message;
}

Throwable getThrowable() {
return this.throwable;
}

}
}
Loading