Skip to content

Commit 1ba4e6f

Browse files
committed
feat(client): Add more observability in apollo config client
1 parent 6b0d4c7 commit 1ba4e6f

File tree

64 files changed

+3762
-95
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+3762
-95
lines changed

apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigService.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import com.ctrip.framework.apollo.core.ConfigConsts;
2121
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
2222
import com.ctrip.framework.apollo.internals.ConfigManager;
23+
import com.ctrip.framework.apollo.internals.ConfigMonitorInitializer;
24+
import com.ctrip.framework.apollo.monitor.api.ConfigMonitor;
2325
import com.ctrip.framework.apollo.spi.ConfigFactory;
2426
import com.ctrip.framework.apollo.spi.ConfigRegistry;
2527

@@ -30,19 +32,31 @@
3032
*/
3133
public class ConfigService {
3234
private static final ConfigService s_instance = new ConfigService();
33-
35+
private volatile ConfigMonitor m_configMonitor;
3436
private volatile ConfigManager m_configManager;
3537
private volatile ConfigRegistry m_configRegistry;
36-
38+
39+
private ConfigMonitor getMonitor() {
40+
getManager();
41+
if (m_configMonitor == null) {
42+
synchronized (this) {
43+
if (m_configMonitor == null) {
44+
m_configMonitor = ApolloInjector.getInstance(ConfigMonitor.class);
45+
}
46+
}
47+
}
48+
return m_configMonitor;
49+
}
50+
3751
private ConfigManager getManager() {
3852
if (m_configManager == null) {
3953
synchronized (this) {
4054
if (m_configManager == null) {
4155
m_configManager = ApolloInjector.getInstance(ConfigManager.class);
56+
ConfigMonitorInitializer.initialize();
4257
}
4358
}
4459
}
45-
4660
return m_configManager;
4761
}
4862

@@ -81,6 +95,10 @@ public static ConfigFile getConfigFile(String namespace, ConfigFileFormat config
8195
return s_instance.getManager().getConfigFile(namespace, configFileFormat);
8296
}
8397

98+
public static ConfigMonitor getConfigMonitor(){
99+
return s_instance.getMonitor();
100+
}
101+
84102
static void setConfig(Config config) {
85103
setConfig(ConfigConsts.NAMESPACE_APPLICATION, config);
86104
}

apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
public abstract class AbstractConfig implements Config {
5454
private static final Logger logger = LoggerFactory.getLogger(AbstractConfig.class);
5555

56-
private static final ExecutorService m_executorService;
56+
protected static final ExecutorService m_executorService;
5757

5858
private final List<ConfigChangeListener> m_listeners = Lists.newCopyOnWriteArrayList();
5959
private final Map<ConfigChangeListener, Set<String>> m_interestedKeys = Maps.newConcurrentMap();

apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigFile.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
*/
1717
package com.ctrip.framework.apollo.internals;
1818

19+
20+
import static com.ctrip.framework.apollo.monitor.internal.tracer.MessageProducerComposite.APOLLO_CLIENT_CONFIGCHANGES;
21+
1922
import com.ctrip.framework.apollo.build.ApolloInjector;
2023
import com.ctrip.framework.apollo.core.utils.DeferredLoggerFactory;
2124
import com.ctrip.framework.apollo.enums.ConfigSourceType;
@@ -43,7 +46,7 @@
4346
*/
4447
public abstract class AbstractConfigFile implements ConfigFile, RepositoryChangeListener {
4548
private static final Logger logger = DeferredLoggerFactory.getLogger(AbstractConfigFile.class);
46-
private static ExecutorService m_executorService;
49+
protected static ExecutorService m_executorService;
4750
protected final ConfigRepository m_configRepository;
4851
protected final String m_namespace;
4952
protected final AtomicReference<Properties> m_configProperties;
@@ -112,7 +115,7 @@ public synchronized void onRepositoryChange(String namespace, Properties newProp
112115

113116
this.fireConfigChange(new ConfigFileChangeEvent(m_namespace, oldValue, newValue, changeType));
114117

115-
Tracer.logEvent("Apollo.Client.ConfigChanges", m_namespace);
118+
Tracer.logEvent(APOLLO_CLIENT_CONFIGCHANGES, m_namespace);
116119
}
117120

118121
@Override

apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigRepository.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
package com.ctrip.framework.apollo.internals;
1818

19+
import static com.ctrip.framework.apollo.monitor.internal.tracer.MessageProducerComposite.APOLLO_CONFIG_EXCEPTION;
20+
1921
import com.ctrip.framework.apollo.build.ApolloInjector;
2022
import com.ctrip.framework.apollo.util.factory.PropertiesFactory;
2123
import java.util.List;
@@ -41,7 +43,7 @@ protected boolean trySync() {
4143
sync();
4244
return true;
4345
} catch (Throwable ex) {
44-
Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex));
46+
Tracer.logEvent(APOLLO_CONFIG_EXCEPTION, ExceptionUtil.getDetailMessage(ex));
4547
logger
4648
.warn("Sync config failed, will retry. Repository {}, reason: {}", this.getClass(), ExceptionUtil
4749
.getDetailMessage(ex));
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright 2022 Apollo Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
package com.ctrip.framework.apollo.internals;
18+
19+
import com.ctrip.framework.apollo.build.ApolloInjector;
20+
import com.ctrip.framework.apollo.core.utils.ClassLoaderUtil;
21+
import com.ctrip.framework.apollo.monitor.api.ConfigMonitor;
22+
import com.ctrip.framework.apollo.monitor.internal.DefaultConfigMonitor;
23+
import com.ctrip.framework.apollo.monitor.internal.collector.MetricsCollector;
24+
import com.ctrip.framework.apollo.monitor.internal.collector.MetricsCollectorManager;
25+
import com.ctrip.framework.apollo.monitor.internal.collector.internal.DefaultApolloExceptionCollector;
26+
import com.ctrip.framework.apollo.monitor.internal.collector.internal.DefaultApolloNamespaceCollector;
27+
import com.ctrip.framework.apollo.monitor.internal.collector.internal.DefaultApolloRunningParamsCollector;
28+
import com.ctrip.framework.apollo.monitor.internal.collector.internal.DefaultApolloThreadPoolCollector;
29+
import com.ctrip.framework.apollo.monitor.internal.collector.internal.DefaultMetricsCollectorManager;
30+
import com.ctrip.framework.apollo.monitor.internal.exporter.MetricsExporter;
31+
import com.ctrip.framework.apollo.monitor.internal.exporter.MetricsExporterFactory;
32+
import com.ctrip.framework.apollo.monitor.internal.tracer.MessageProducerComposite;
33+
import com.ctrip.framework.apollo.monitor.internal.tracer.MonitorMessageProducer;
34+
import com.ctrip.framework.apollo.tracer.internals.NullMessageProducer;
35+
import com.ctrip.framework.apollo.tracer.internals.cat.CatMessageProducer;
36+
import com.ctrip.framework.apollo.tracer.internals.cat.CatNames;
37+
import com.ctrip.framework.apollo.tracer.spi.MessageProducer;
38+
import com.ctrip.framework.apollo.util.ConfigUtil;
39+
import com.ctrip.framework.foundation.internals.ServiceBootstrap;
40+
import com.google.common.collect.Lists;
41+
import java.util.List;
42+
43+
/**
44+
* @author Rawven
45+
*/
46+
public class ConfigMonitorInitializer {
47+
48+
private static ConfigUtil m_configUtil = ApolloInjector.getInstance(ConfigUtil.class);
49+
private static Boolean hasInitialized = false;
50+
51+
public static void initialize() {
52+
if (m_configUtil.isClientMonitorEnabled() && !hasInitialized) {
53+
DefaultMetricsCollectorManager manager = initializeMetricsCollectorManager();
54+
List<MetricsCollector> collectors = initializeCollectors(manager);
55+
MetricsExporter metricsExporter = initializeMetricsExporter(collectors);
56+
initializeConfigMonitor(collectors, metricsExporter);
57+
hasInitialized = true;
58+
}
59+
}
60+
61+
private static DefaultMetricsCollectorManager initializeMetricsCollectorManager() {
62+
return (DefaultMetricsCollectorManager) ApolloInjector.getInstance(MetricsCollectorManager.class);
63+
}
64+
65+
private static List<MetricsCollector> initializeCollectors(DefaultMetricsCollectorManager manager) {
66+
DefaultConfigManager configManager = (DefaultConfigManager) ApolloInjector.getInstance(ConfigManager.class);
67+
DefaultApolloExceptionCollector exceptionCollector = new DefaultApolloExceptionCollector();
68+
DefaultApolloThreadPoolCollector threadPoolCollector = new DefaultApolloThreadPoolCollector(
69+
RemoteConfigRepository.m_executorService, AbstractConfig.m_executorService, AbstractConfigFile.m_executorService);
70+
DefaultApolloNamespaceCollector namespaceCollector = new DefaultApolloNamespaceCollector(
71+
configManager.m_configs, configManager.m_configLocks, configManager.m_configFiles, configManager.m_configFileLocks);
72+
DefaultApolloRunningParamsCollector startupCollector = new DefaultApolloRunningParamsCollector(m_configUtil);
73+
74+
List<MetricsCollector> collectors = Lists.newArrayList(exceptionCollector, namespaceCollector, threadPoolCollector, startupCollector);
75+
manager.setCollectors(collectors);
76+
return collectors;
77+
}
78+
79+
private static MetricsExporter initializeMetricsExporter(List<MetricsCollector> collectors) {
80+
MetricsExporterFactory reporterFactory = ApolloInjector.getInstance(MetricsExporterFactory.class);
81+
return reporterFactory.getMetricsReporter(collectors);
82+
}
83+
84+
private static void initializeConfigMonitor(List<MetricsCollector> collectors, MetricsExporter metricsExporter) {
85+
DefaultConfigMonitor defaultConfigMonitor = (DefaultConfigMonitor) ApolloInjector.getInstance(ConfigMonitor.class);
86+
DefaultApolloExceptionCollector exceptionCollector = (DefaultApolloExceptionCollector) collectors.get(0);
87+
DefaultApolloNamespaceCollector namespaceCollector = (DefaultApolloNamespaceCollector) collectors.get(1);
88+
DefaultApolloThreadPoolCollector threadPoolCollector = (DefaultApolloThreadPoolCollector) collectors.get(2);
89+
DefaultApolloRunningParamsCollector startupCollector = (DefaultApolloRunningParamsCollector) collectors.get(3);
90+
defaultConfigMonitor.init(namespaceCollector, threadPoolCollector, exceptionCollector, startupCollector, metricsExporter);
91+
}
92+
93+
public static MessageProducerComposite initializeMessageProducerComposite() {
94+
95+
// Prioritize loading user-defined producers from SPI
96+
List<MessageProducer> producers = ServiceBootstrap.loadAllOrdered(MessageProducer.class);
97+
98+
// The producer that comes with the client
99+
if (m_configUtil.isClientMonitorEnabled()) {
100+
producers.add(new MonitorMessageProducer());
101+
}
102+
103+
if (ClassLoaderUtil.isClassPresent(CatNames.CAT_CLASS)) {
104+
producers.add(new CatMessageProducer());
105+
}
106+
107+
// default logic
108+
if (producers.isEmpty()) {
109+
producers.add(new NullMessageProducer());
110+
}
111+
return new MessageProducerComposite(producers);
112+
}
113+
}

apollo-client/src/main/java/com/ctrip/framework/apollo/internals/ConfigServiceLocator.java

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,42 @@
1616
*/
1717
package com.ctrip.framework.apollo.internals;
1818

19-
import com.ctrip.framework.apollo.core.ApolloClientSystemConsts;
20-
import com.ctrip.framework.apollo.core.ServiceNameConsts;
21-
import com.ctrip.framework.apollo.core.utils.DeferredLoggerFactory;
22-
import com.ctrip.framework.apollo.core.utils.DeprecatedPropertyNotifyUtil;
23-
import com.ctrip.framework.foundation.Foundation;
24-
import com.google.common.util.concurrent.RateLimiter;
25-
import java.lang.reflect.Type;
26-
import java.util.List;
27-
import java.util.Map;
28-
import java.util.concurrent.Executors;
29-
import java.util.concurrent.ScheduledExecutorService;
30-
import java.util.concurrent.atomic.AtomicBoolean;
31-
import java.util.concurrent.atomic.AtomicReference;
32-
33-
import org.slf4j.Logger;
19+
import static com.ctrip.framework.apollo.monitor.internal.tracer.MessageProducerComposite.APOLLO_CONFIG_EXCEPTION;
20+
import static com.ctrip.framework.apollo.monitor.internal.tracer.MessageProducerComposite.APOLLO_CONFIG_SERVICES;
21+
import static com.ctrip.framework.apollo.monitor.internal.tracer.MessageProducerComposite.APOLLO_META_SERVICE;
3422

3523
import com.ctrip.framework.apollo.build.ApolloInjector;
24+
import com.ctrip.framework.apollo.core.ApolloClientSystemConsts;
25+
import com.ctrip.framework.apollo.core.ServiceNameConsts;
3626
import com.ctrip.framework.apollo.core.dto.ServiceDTO;
3727
import com.ctrip.framework.apollo.core.utils.ApolloThreadFactory;
28+
import com.ctrip.framework.apollo.core.utils.DeferredLoggerFactory;
29+
import com.ctrip.framework.apollo.core.utils.DeprecatedPropertyNotifyUtil;
3830
import com.ctrip.framework.apollo.exceptions.ApolloConfigException;
3931
import com.ctrip.framework.apollo.tracer.Tracer;
4032
import com.ctrip.framework.apollo.tracer.spi.Transaction;
4133
import com.ctrip.framework.apollo.util.ConfigUtil;
4234
import com.ctrip.framework.apollo.util.ExceptionUtil;
35+
import com.ctrip.framework.apollo.util.http.HttpClient;
4336
import com.ctrip.framework.apollo.util.http.HttpRequest;
4437
import com.ctrip.framework.apollo.util.http.HttpResponse;
45-
import com.ctrip.framework.apollo.util.http.HttpClient;
38+
import com.ctrip.framework.foundation.Foundation;
4639
import com.google.common.base.Joiner;
4740
import com.google.common.base.Strings;
4841
import com.google.common.collect.Lists;
4942
import com.google.common.collect.Maps;
5043
import com.google.common.escape.Escaper;
5144
import com.google.common.net.UrlEscapers;
45+
import com.google.common.util.concurrent.RateLimiter;
5246
import com.google.gson.reflect.TypeToken;
47+
import java.lang.reflect.Type;
48+
import java.util.List;
49+
import java.util.Map;
50+
import java.util.concurrent.Executors;
51+
import java.util.concurrent.ScheduledExecutorService;
52+
import java.util.concurrent.atomic.AtomicBoolean;
53+
import java.util.concurrent.atomic.AtomicReference;
54+
import org.slf4j.Logger;
5355

5456
public class ConfigServiceLocator {
5557
private static final Logger logger = DeferredLoggerFactory.getLogger(ConfigServiceLocator.class);
@@ -218,7 +220,7 @@ private void schedulePeriodicRefresh() {
218220
@Override
219221
public void run() {
220222
logger.debug("refresh config services");
221-
Tracer.logEvent("Apollo.MetaService", "periodicRefresh");
223+
Tracer.logEvent(APOLLO_META_SERVICE, "periodicRefresh");
222224
tryUpdateConfigServices();
223225
}
224226
}, m_configUtil.getRefreshInterval(), m_configUtil.getRefreshInterval(),
@@ -258,7 +260,7 @@ private synchronized void updateConfigServices() {
258260
setConfigServices(services);
259261
return;
260262
} catch (Throwable ex) {
261-
Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex));
263+
Tracer.logEvent(APOLLO_CONFIG_EXCEPTION, ExceptionUtil.getDetailMessage(ex));
262264
transaction.setStatus(ex);
263265
exception = ex;
264266
} finally {
@@ -302,6 +304,6 @@ private void logConfigServices(List<ServiceDTO> serviceDtos) {
302304
}
303305

304306
private void logConfigService(String serviceUrl) {
305-
Tracer.logEvent("Apollo.Config.Services", serviceUrl);
307+
Tracer.logEvent(APOLLO_CONFIG_SERVICES, serviceUrl);
306308
}
307309
}

apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfig.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*/
1717
package com.ctrip.framework.apollo.internals;
1818

19+
import static com.ctrip.framework.apollo.monitor.internal.tracer.MessageProducerComposite.APOLLO_CLIENT_CONFIGCHANGES;
20+
1921
import com.ctrip.framework.apollo.core.utils.DeferredLoggerFactory;
2022
import com.ctrip.framework.apollo.enums.ConfigSourceType;
2123
import com.google.common.collect.Maps;
@@ -236,7 +238,7 @@ public synchronized void onRepositoryChange(String namespace, Properties newProp
236238

237239
this.fireConfigChange(m_namespace, actualChanges);
238240

239-
Tracer.logEvent("Apollo.Client.ConfigChanges", m_namespace);
241+
Tracer.logEvent(APOLLO_CLIENT_CONFIGCHANGES, m_namespace);
240242
}
241243

242244
private void updateConfig(Properties newConfigProperties, ConfigSourceType sourceType) {

apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultConfigManager.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,39 @@
1616
*/
1717
package com.ctrip.framework.apollo.internals;
1818

19-
import java.util.Map;
19+
import static com.ctrip.framework.apollo.monitor.internal.collector.internal.DefaultApolloNamespaceCollector.NAMESPACE_MONITOR;
20+
import static com.ctrip.framework.apollo.monitor.internal.collector.internal.DefaultApolloNamespaceCollector.NAMESPACE_USAGE_COUNT;
2021

2122
import com.ctrip.framework.apollo.Config;
2223
import com.ctrip.framework.apollo.ConfigFile;
2324
import com.ctrip.framework.apollo.build.ApolloInjector;
2425
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat;
26+
import com.ctrip.framework.apollo.monitor.internal.MonitorConstant;
27+
import com.ctrip.framework.apollo.monitor.internal.model.MetricsEvent;
2528
import com.ctrip.framework.apollo.spi.ConfigFactory;
2629
import com.ctrip.framework.apollo.spi.ConfigFactoryManager;
2730
import com.google.common.collect.Maps;
31+
import java.util.Map;
2832

2933
/**
3034
* @author Jason Song([email protected])
3135
*/
3236
public class DefaultConfigManager implements ConfigManager {
33-
private ConfigFactoryManager m_factoryManager;
3437

35-
private Map<String, Config> m_configs = Maps.newConcurrentMap();
36-
private Map<String, Object> m_configLocks = Maps.newConcurrentMap();
37-
private Map<String, ConfigFile> m_configFiles = Maps.newConcurrentMap();
38-
private Map<String, Object> m_configFileLocks = Maps.newConcurrentMap();
38+
protected Map<String, Config> m_configs = Maps.newConcurrentMap();
39+
protected Map<String, Object> m_configLocks = Maps.newConcurrentMap();
40+
protected Map<String, ConfigFile> m_configFiles = Maps.newConcurrentMap();
41+
protected Map<String, Object> m_configFileLocks = Maps.newConcurrentMap();
42+
private ConfigFactoryManager m_factoryManager;
3943

4044
public DefaultConfigManager() {
4145
m_factoryManager = ApolloInjector.getInstance(ConfigFactoryManager.class);
46+
4247
}
4348

4449
@Override
4550
public Config getConfig(String namespace) {
4651
Config config = m_configs.get(namespace);
47-
4852
if (config == null) {
4953
Object lock = m_configLocks.computeIfAbsent(namespace, key -> new Object());
5054
synchronized (lock) {
@@ -59,11 +63,16 @@ public Config getConfig(String namespace) {
5963
}
6064
}
6165

66+
MetricsEvent.builder().withName(NAMESPACE_USAGE_COUNT)
67+
.putAttachment(MonitorConstant.NAMESPACE, namespace)
68+
.withTag(NAMESPACE_MONITOR).push();
69+
6270
return config;
6371
}
6472

6573
@Override
66-
public ConfigFile getConfigFile(String namespace, ConfigFileFormat configFileFormat) {
74+
public ConfigFile getConfigFile(String namespace,
75+
ConfigFileFormat configFileFormat) {
6776
String namespaceFileName = String.format("%s.%s", namespace, configFileFormat.getValue());
6877
ConfigFile configFile = m_configFiles.get(namespaceFileName);
6978

0 commit comments

Comments
 (0)