diff --git a/doc/images/apollo-client-monitor-jmx.png b/doc/images/apollo-client-monitor-jmx.png new file mode 100644 index 00000000000..703b055e001 Binary files /dev/null and b/doc/images/apollo-client-monitor-jmx.png differ diff --git a/doc/images/apollo-client-monitor-prometheus.png b/doc/images/apollo-client-monitor-prometheus.png new file mode 100644 index 00000000000..f709bb57d23 Binary files /dev/null and b/doc/images/apollo-client-monitor-prometheus.png differ diff --git a/docs/en/client/java-sdk-user-guide.md b/docs/en/client/java-sdk-user-guide.md index 3b61cb62bf3..b4e0366ea10 100644 --- a/docs/en/client/java-sdk-user-guide.md +++ b/docs/en/client/java-sdk-user-guide.md @@ -414,24 +414,6 @@ The configuration methods, in descending order of priority, are 3. Via the `app.properties` configuration file * You can specify `apollo.override-system-properties=true` in `classpath:/META-INF/app.properties` -### 1.2.4.9 Monitor-related Configuration - -> Applicable for version 2.4.0 and above -Starting from version 2.4.0, the observability of the client has been enhanced. Users can obtain the client status information directly through ConfigService by accessing ConfigMonitor and report the status as metrics to monitoring systems. Below are some related configurations. - -`apollo.client.monitor.enabled`: Enables the Monitor mechanism, i.e., whether ConfigMonitor is activated. The default is false. - -`apollo.client.monitor.jmx.enabled`: Exposes Monitor data in JMX format. If enabled, tools like J-console and Jprofiler can be used to view the relevant information. The default is false. - -`apollo.client.monitor.exception-queue-size`: Sets the maximum number of exceptions that the Monitor can store. The default value is 25. - -`apollo.client.monitor.external.type`: **Non-standard configuration item**, used to activate the corresponding monitoring system's Exporter when exporting metric data. For example, if the apollo-plugin-client-prometheus is introduced, "prometheus" can be specified to enable it. The values available for configuration depend on the MetricsExporter SPI introduced (official or custom implementations). This design allows for easy extensibility. If multiple, incorrect, or no values are set, no Exporter will be enabled. - -For specific usage, see the section on Extension Development - Java Client Access to Different Monitoring Systems. - -`apollo.client.monitor.external.export-period`: The Exporter exports status information (e.g., thread pools) from the Monitor and converts it into metric data through scheduled tasks. The export-period controls the frequency of these scheduled tasks. The default is 10 seconds. - - # II. Maven Dependency Apollo's client jar package has been uploaded to the central repository, the application only needs to be introduced in the following way when it is actually used. @@ -468,8 +450,6 @@ Apollo supports API approach and Spring integration approach, how to choose whic * For more interesting practical usage scenarios and sample code, please refer to [apollo-use-cases](https://github.com/ctripcorp/apollo-use-cases) - - ## 3.1 API Usage The API approach is the easiest and most efficient way to use Apollo configuration without relying on the Spring Framework to use it. @@ -539,207 +519,6 @@ String someNamespace = "test"; ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML); String content = configFile.getContent(); ``` -### 3.1.5 Using the Monitor Feature - -In version 2.4.0, apollo-client significantly enhanced observability by providing the ConfigMonitor API and metrics export options for JMX and Prometheus. - -To enable the monitor feature, you need to configure apollo.client.monitor.enabled to true. - - -```yaml -apollo: - client: - monitor: - enabled: true -``` - -#### 3.1.5.1 Exposing Status Information via JMX - -Enable apollo.client.monitor.jmx.enabled in the configuration. - -```yaml -apollo: - client: - monitor: - enabled: true - jmx: - enabled: true -``` - -After starting the application, you can view it using J-console or J-profiler; here, we use J-profiler as an example. - -![](https://raw.githubusercontent.com/Rawven/image/main/20241020224657.png) - -#### 3.1.5.2 Exporting Metrics via Prometheus - -Introduce the official dependency package -```xml - - com.ctrip.framework.apollo - apollo-plugin-client-prometheus - 2.4.0-SNAPSHOT - -``` -Adjust the configuration apollo.client.monitor.external.type=prometheus -```yaml -apollo: - client: - monitor: - enabled: true - external: - type: prometheus -``` - -This allows you to obtain ExporterData through ConfigMonitor (the format depends on the monitoring system you configured), and then expose the endpoint to Prometheus. - - -Example code - -```java -@RestController -@ResponseBody -public class TestController { - - @GetMapping("/metrics") - public String metrics() { - ConfigMonitor configMonitor = ConfigService.getConfigMonitor(); - return configMonitor.getExporterData(); - } -} -``` - -After starting the application, let Prometheus listen to this interface, and you will see request logs with a similar format. -``` -# TYPE apollo_client_thread_pool_active_task_count gauge -# HELP apollo_client_thread_pool_active_task_count apollo gauge metrics -apollo_client_thread_pool_active_task_count{thread_pool_name="RemoteConfigRepository"} 0.0 -apollo_client_thread_pool_active_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 -apollo_client_thread_pool_active_task_count{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_active_task_count{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_namespace_timeout gauge -# HELP apollo_client_namespace_timeout apollo gauge metrics -apollo_client_namespace_timeout 0.0 -# TYPE apollo_client_thread_pool_pool_size gauge -# HELP apollo_client_thread_pool_pool_size apollo gauge metrics -apollo_client_thread_pool_pool_size{thread_pool_name="RemoteConfigRepository"} 1.0 -apollo_client_thread_pool_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 -apollo_client_thread_pool_pool_size{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_pool_size{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_thread_pool_queue_remaining_capacity gauge -# HELP apollo_client_thread_pool_queue_remaining_capacity apollo gauge metrics -apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="RemoteConfigRepository"} 2.147483647E9 -apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="AbstractApolloClientMetricsExporter"} 2.147483647E9 -apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_exception_num counter -# HELP apollo_client_exception_num apollo counter metrics -apollo_client_exception_num_total 1404.0 -apollo_client_exception_num_created 1.729435502796E9 -# TYPE apollo_client_thread_pool_largest_pool_size gauge -# HELP apollo_client_thread_pool_largest_pool_size apollo gauge metrics -apollo_client_thread_pool_largest_pool_size{thread_pool_name="RemoteConfigRepository"} 1.0 -apollo_client_thread_pool_largest_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 -apollo_client_thread_pool_largest_pool_size{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_largest_pool_size{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_thread_pool_queue_size gauge -# HELP apollo_client_thread_pool_queue_size apollo gauge metrics -apollo_client_thread_pool_queue_size{thread_pool_name="RemoteConfigRepository"} 352.0 -apollo_client_thread_pool_queue_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 0.0 -apollo_client_thread_pool_queue_size{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_queue_size{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_namespace_usage counter -# HELP apollo_client_namespace_usage apollo counter metrics -apollo_client_namespace_usage_total{namespace="application"} 11.0 -apollo_client_namespace_usage_created{namespace="application"} 1.729435502791E9 -# TYPE apollo_client_thread_pool_core_pool_size gauge -# HELP apollo_client_thread_pool_core_pool_size apollo gauge metrics -apollo_client_thread_pool_core_pool_size{thread_pool_name="RemoteConfigRepository"} 1.0 -apollo_client_thread_pool_core_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 -apollo_client_thread_pool_core_pool_size{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_core_pool_size{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_namespace_not_found gauge -# HELP apollo_client_namespace_not_found apollo gauge metrics -apollo_client_namespace_not_found 351.0 -# TYPE apollo_client_thread_pool_total_task_count gauge -# HELP apollo_client_thread_pool_total_task_count apollo gauge metrics -apollo_client_thread_pool_total_task_count{thread_pool_name="RemoteConfigRepository"} 353.0 -apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 4.0 -apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_namespace_first_load_time_spend_in_ms gauge -# HELP apollo_client_namespace_first_load_time_spend_in_ms apollo gauge metrics -apollo_client_namespace_first_load_time_spend_in_ms{namespace="application"} 108.0 -# TYPE apollo_client_thread_pool_maximum_pool_size gauge -# HELP apollo_client_thread_pool_maximum_pool_size apollo gauge metrics -apollo_client_thread_pool_maximum_pool_size{thread_pool_name="RemoteConfigRepository"} 2.147483647E9 -apollo_client_thread_pool_maximum_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 2.147483647E9 -apollo_client_thread_pool_maximum_pool_size{thread_pool_name="AbstractConfigFile"} 2.147483647E9 -apollo_client_thread_pool_maximum_pool_size{thread_pool_name="AbstractConfig"} 2.147483647E9 -# TYPE apollo_client_namespace_item_num gauge -# HELP apollo_client_namespace_item_num apollo gauge metrics -apollo_client_namespace_item_num{namespace="application"} 9.0 -# TYPE apollo_client_thread_pool_completed_task_count gauge -# HELP apollo_client_thread_pool_completed_task_count apollo gauge metrics -apollo_client_thread_pool_completed_task_count{thread_pool_name="RemoteConfigRepository"} 1.0 -apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 3.0 -apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfig"} 0.0 -# EOF -``` - -You can also see similar information on the Prometheus console. - -![](https://raw.githubusercontent.com/Rawven/image/main/20240922125033.png) - -#### 3.1.5.3 Manually Calling the ConfigMonitor API to Retrieve Related Data (for example, when users need to manually process data to report to the monitoring system) - -```java - ConfigMonitor configMonitor = ConfigService.getConfigMonitor(); - // Error related monitoring API - ApolloClientExceptionMonitorApi exceptionMonitorApi = configMonitor.getExceptionMonitorApi(); - List apolloConfigExceptionList = exceptionMonitorApi.getApolloConfigExceptionList(); - // Namespace related monitoring API - ApolloClientNamespaceMonitorApi namespaceMonitorApi = configMonitor.getNamespaceMonitorApi(); - List namespace404 = namespaceMonitorApi.getNotFoundNamespaces(); - // Startup parameter related monitoring API - ApolloClientBootstrapArgsMonitorApi runningParamsMonitorApi = configMonitor.getRunningParamsMonitorApi(); - String bootstrapNamespaces = runningParamsMonitorApi.getBootstrapNamespaces(); - // Thread pool related monitoring API - ApolloClientThreadPoolMonitorApi threadPoolMonitorApi = configMonitor.getThreadPoolMonitorApi(); - ApolloThreadPoolInfo remoteConfigRepositoryThreadPoolInfo = threadPoolMonitorApi.getRemoteConfigRepositoryThreadPoolInfo(); -``` - -#### 3.1.5.4 Metrics Data Table - -## Namespace Metrics - -| Metric Name | Tags | -|-----------------------------------------------------|-----------| -| apollo_client_namespace_usage_total | namespace | -| apollo_client_namespace_item_num | namespace | -| apollo_client_namespace_not_found | | -| apollo_client_namespace_timeout | | -| apollo_client_namespace_first_load_time_spend_in_ms | namespace | - -## Thread Pool Metrics - -| Metric Name | Tags | -| -------------------------------------------------- | ---------------- | -| apollo_client_thread_pool_pool_size | thread_pool_name | -| apollo_client_thread_pool_maximum_pool_size | thread_pool_name | -| apollo_client_thread_pool_largest_pool_size | thread_pool_name | -| apollo_client_thread_pool_completed_task_count | thread_pool_name | -| apollo_client_thread_pool_queue_remaining_capacity | thread_pool_name | -| apollo_client_thread_pool_total_task_count | thread_pool_name | -| apollo_client_thread_pool_active_task_count | thread_pool_name | -| apollo_client_thread_pool_core_pool_size | thread_pool_name | -| apollo_client_thread_pool_queue_size | thread_pool_name | - -## Exception Metrics - -| Metric Name | Tags | -| --------------------------------- | ---- | -| apollo_client_exception_num_total | | ## 3.2 Spring integration approach @@ -1502,15 +1281,4 @@ The interface is `com.ctrip.framework.apollo.spi.ConfigServiceLoadBalancerClient The Input is multiple ConfigServices returned by meta server, and the output is a ConfigService selected. -The default service provider is `com.ctrip.framework.apollo.spi.RandomConfigServiceLoadBalancerClient`, which chooses one ConfigService from multiple ConfigServices using random strategy . - -## 7.2 MetricsExporter Extension - -> from version 2.4.0 -To meet users' varying system requirements for metrics exporting (e.g., Prometheus, Skywalking) when using apollo-client, we have provided an SPI in the enhanced observability of version 2.4.0. - -The interface is com.ctrip.framework.apollo.monitor.internal.exporter.ApolloClientMetricsExporter. - -We offer an abstract class for a general metrics export framework, com.ctrip.framework.apollo.monitor.internal.exporter.AbstractApolloClientMetricsExporter. You just need to extend this class and implement the relevant methods to customize integration with other monitoring systems. You can refer to the implementation of apollo-plugin-client-prometheus. - -By default, there are no services provided, which means no metrics data will be exported. \ No newline at end of file +The default service provider is `com.ctrip.framework.apollo.spi.RandomConfigServiceLoadBalancerClient`, which chooses one ConfigService from multiple ConfigServices using random strategy . \ No newline at end of file diff --git a/docs/en/extension/java-client-how-to-use-custom-monitor-system.md b/docs/en/extension/java-client-how-to-use-custom-monitor-system.md deleted file mode 100644 index 5bd8d6fbb0f..00000000000 --- a/docs/en/extension/java-client-how-to-use-custom-monitor-system.md +++ /dev/null @@ -1,141 +0,0 @@ -In version 2.4.0 and above of the Java client, support for metrics collection and export has been added, allowing users to extend and integrate with different monitoring systems. - -## Taking Prometheus Integration as an Example - -Create the `PrometheusApolloClientMetricsExporter` class, which extends `AbstractApolloClientMetricsExporter` (the generic metrics export framework). - -The code after extending is roughly as follows: - -```java - -public class PrometheusApolloClientMetricsExporter extends - AbstractApolloClientMetricsExporter implements ApolloClientMetricsExporter { - - @Override - public void doInit() { - - } - - @Override - public boolean isSupport(String form) { - - } - - - @Override - public void registerOrUpdateCounterSample(String name, Map tags, double incrValue) { - - } - - - @Override - public void registerOrUpdateGaugeSample(String name, Map tags, double value) { - - } - - @Override - public String response() { - - } -} - -``` - -The doInit method is provided for users to extend during initialization and will be called in the init method of AbstractApolloClientMetricsExporter. - -```java - @Override - public void init(List collectors, long collectPeriod) { - log.info("Initializing metrics exporter with {} collectors and collect period of {} seconds.", - collectors.size(), collectPeriod); - doInit(); - this.collectors = collectors; - initScheduleMetricsCollectSync(collectPeriod); - log.info("Metrics collection scheduled with a period of {} seconds.", collectPeriod); - } -``` - -Here, the Prometheus Java client is introduced, and the CollectorRegistry and cache map need to be initialized. - -```java - private CollectorRegistry registry; - private Map map; - - @Override - public void doInit() { - registry = new CollectorRegistry(); - map = new HashMap<>(); - } -``` - -The isSupport method will be called in DefaultApolloClientMetricsExporterFactory via SPI to check which MetricsExporter to enable, allowing accurate activation of the configured exporter when multiple SPI implementations exist. - -For example, if you want to enable Prometheus and specify the value as "prometheus," it should synchronize here: - -```java - @Override - public boolean isSupport(String form) { - return PROMETHEUS.equals(form); - } -``` - -The methods registerOrUpdateCounterSample and registerOrUpdateGaugeSample are used to register Counter and Gauge type metrics, simply registering based on the provided parameters. - -```java - @Override - public void registerOrUpdateCounterSample(String name, Map tags, - double incrValue) { - Counter counter = (Counter) map.get(name); - if (counter == null) { - counter = createCounter(name, tags); - map.put(name, counter); - } - counter.labels(tags.values().toArray(new String[0])).inc(incrValue); - } - - private Counter createCounter(String name, Map tags) { - return Counter.build() - .name(name) - .help("apollo") - .labelNames(tags.keySet().toArray(new String[0])) - .register(registry); - } - - @Override - public void registerOrUpdateGaugeSample(String name, Map tags, double value) { - Gauge gauge = (Gauge) map.get(name); - if (gauge == null) { - gauge = createGauge(name, tags); - map.put(name, gauge); - } - gauge.labels(tags.values().toArray(new String[0])).set(value); - } - - private Gauge createGauge(String name, Map tags) { - return Gauge.build() - .name(name) - .help("apollo") - .labelNames(tags.keySet().toArray(new String[0])) - .register(registry); - } -``` - -Finally, you need to implement the response method, which is used to export data in the format of the integrated monitoring system. It will ultimately be obtained in the getExporterData method of ConfigMonitor, allowing users to expose an endpoint for monitoring systems to pull data. - -```java - @Override - public String response() { - try (StringWriter writer = new StringWriter()) { - TextFormat.writeFormat(TextFormat.CONTENT_TYPE_OPENMETRICS_100, writer, - registry.metricFamilySamples()); - return writer.toString(); - } catch (IOException e) { - logger.error("Write metrics to Prometheus format failed", e); - return ""; - } - } -``` - -At this point, the client's metric data has been integrated with Prometheus. - -Full code:[code](https://github.com/apolloconfig/apollo-java/main/master/apollo-plugin/apollo-plugin-client-prometheus/src/main/java/com/ctrip/framework/apollo/monitor/internal/exporter/impl/PrometheusApolloClientMetricsExporter.java) \ No newline at end of file diff --git a/docs/zh/client/java-sdk-user-guide.md b/docs/zh/client/java-sdk-user-guide.md index 00d7c812093..14ca7b00d16 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -509,157 +509,28 @@ ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML String content = configFile.getContent(); ``` -### 3.1.5 使用Monitor功能 +### 3.1.5 获取客户端监控指标 apollo-client在2.4.0版本里大幅增强了可观测性,提供了ConfigMonitor-API以及JMX,Prometheus的指标导出方式 +详见 [1.2.4.1 开启客户端监控](#_1241-开启客户端监控) +相关配置开启请参照 1.2.4.9 小节 -若启用monitor功能,前提需要配置apollo.client.monitor.enabled为true - -```yaml -apollo: - client: - monitor: - enabled: true -``` #### 3.1.5.1 以JMX形式暴露状态信息 -在配置中对apollo.client.monitor.jmx.enabled进行启用 +启用相关配置 -```yaml -apollo: - client: - monitor: - enabled: true - jmx: - enabled: true +```properties +apollo.client.monitor.enabled = true +apollo.client.monitor.jmx.enabled = true ``` 启动应用后,开启J-console或J-profiler即可查看,这里用J-profiler做例子 -![](https://raw.githubusercontent.com/Rawven/image/main/20241020224657.png) - -#### 3.1.5.2 以Prometheus形式导出指标 -引入提供的官方依赖包 -```xml - - com.ctrip.framework.apollo - apollo-plugin-client-prometheus - 2.4.0-SNAPSHOT - -``` -调整配置apollo.client.monitor.external.type=prometheus -```yaml -apollo: - client: - monitor: - enabled: true - external: - type: prometheus -``` +![JProfiler showing Apollo client monitoring metrics in JMX](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-jmx.png) -这样就可以通过ConfigMonitor拿到ExporterData(格式取决于你配置的监控系统),然后暴露端点给Prometheus即可 -示例代码 - -```java -@RestController -@ResponseBody -public class TestController { - - @GetMapping("/metrics") - public String metrics() { - ConfigMonitor configMonitor = ConfigService.getConfigMonitor(); - return configMonitor.getExporterData(); - } -} -``` - -启动应用后让Prometheus监听该接口,打印请求日志即可发现如下类似格式信息 - -``` -# TYPE apollo_client_thread_pool_active_task_count gauge -# HELP apollo_client_thread_pool_active_task_count apollo gauge metrics -apollo_client_thread_pool_active_task_count{thread_pool_name="RemoteConfigRepository"} 0.0 -apollo_client_thread_pool_active_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 -apollo_client_thread_pool_active_task_count{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_active_task_count{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_namespace_timeout gauge -# HELP apollo_client_namespace_timeout apollo gauge metrics -apollo_client_namespace_timeout 0.0 -# TYPE apollo_client_thread_pool_pool_size gauge -# HELP apollo_client_thread_pool_pool_size apollo gauge metrics -apollo_client_thread_pool_pool_size{thread_pool_name="RemoteConfigRepository"} 1.0 -apollo_client_thread_pool_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 -apollo_client_thread_pool_pool_size{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_pool_size{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_thread_pool_queue_remaining_capacity gauge -# HELP apollo_client_thread_pool_queue_remaining_capacity apollo gauge metrics -apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="RemoteConfigRepository"} 2.147483647E9 -apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="AbstractApolloClientMetricsExporter"} 2.147483647E9 -apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_exception_num counter -# HELP apollo_client_exception_num apollo counter metrics -apollo_client_exception_num_total 1404.0 -apollo_client_exception_num_created 1.729435502796E9 -# TYPE apollo_client_thread_pool_largest_pool_size gauge -# HELP apollo_client_thread_pool_largest_pool_size apollo gauge metrics -apollo_client_thread_pool_largest_pool_size{thread_pool_name="RemoteConfigRepository"} 1.0 -apollo_client_thread_pool_largest_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 -apollo_client_thread_pool_largest_pool_size{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_largest_pool_size{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_thread_pool_queue_size gauge -# HELP apollo_client_thread_pool_queue_size apollo gauge metrics -apollo_client_thread_pool_queue_size{thread_pool_name="RemoteConfigRepository"} 352.0 -apollo_client_thread_pool_queue_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 0.0 -apollo_client_thread_pool_queue_size{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_queue_size{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_namespace_usage counter -# HELP apollo_client_namespace_usage apollo counter metrics -apollo_client_namespace_usage_total{namespace="application"} 11.0 -apollo_client_namespace_usage_created{namespace="application"} 1.729435502791E9 -# TYPE apollo_client_thread_pool_core_pool_size gauge -# HELP apollo_client_thread_pool_core_pool_size apollo gauge metrics -apollo_client_thread_pool_core_pool_size{thread_pool_name="RemoteConfigRepository"} 1.0 -apollo_client_thread_pool_core_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 -apollo_client_thread_pool_core_pool_size{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_core_pool_size{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_namespace_not_found gauge -# HELP apollo_client_namespace_not_found apollo gauge metrics -apollo_client_namespace_not_found 351.0 -# TYPE apollo_client_thread_pool_total_task_count gauge -# HELP apollo_client_thread_pool_total_task_count apollo gauge metrics -apollo_client_thread_pool_total_task_count{thread_pool_name="RemoteConfigRepository"} 353.0 -apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 4.0 -apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractConfig"} 0.0 -# TYPE apollo_client_namespace_first_load_time_spend_in_ms gauge -# HELP apollo_client_namespace_first_load_time_spend_in_ms apollo gauge metrics -apollo_client_namespace_first_load_time_spend_in_ms{namespace="application"} 108.0 -# TYPE apollo_client_thread_pool_maximum_pool_size gauge -# HELP apollo_client_thread_pool_maximum_pool_size apollo gauge metrics -apollo_client_thread_pool_maximum_pool_size{thread_pool_name="RemoteConfigRepository"} 2.147483647E9 -apollo_client_thread_pool_maximum_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 2.147483647E9 -apollo_client_thread_pool_maximum_pool_size{thread_pool_name="AbstractConfigFile"} 2.147483647E9 -apollo_client_thread_pool_maximum_pool_size{thread_pool_name="AbstractConfig"} 2.147483647E9 -# TYPE apollo_client_namespace_item_num gauge -# HELP apollo_client_namespace_item_num apollo gauge metrics -apollo_client_namespace_item_num{namespace="application"} 9.0 -# TYPE apollo_client_thread_pool_completed_task_count gauge -# HELP apollo_client_thread_pool_completed_task_count apollo gauge metrics -apollo_client_thread_pool_completed_task_count{thread_pool_name="RemoteConfigRepository"} 1.0 -apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 3.0 -apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfigFile"} 0.0 -apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfig"} 0.0 -# EOF -``` - -同时查看Prometheus控制台也能看到如下信息 - -![](https://raw.githubusercontent.com/Rawven/image/main/20240922125033.png) - -#### 3.1.5.3 用户手动调用ConfigMonitor-API获取相关数据(比如当用户需要手动加工数据上报到监控系统时) +#### 3.1.5.2 用户手动调用ConfigMonitor-API获取相关数据(比如当用户需要手动加工数据上报到监控系统时) ```java ConfigMonitor configMonitor = ConfigService.getConfigMonitor(); @@ -677,7 +548,7 @@ apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfig" ApolloThreadPoolInfo remoteConfigRepositoryThreadPoolInfo = threadPoolMonitorApi.getRemoteConfigRepositoryThreadPoolInfo(); ``` -#### 3.1.5.4 指标数据表格 +#### 3.1.5.3 指标数据表格 ## Namespace Metrics @@ -709,6 +580,9 @@ apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfig" | --------------------------------- | ---- | | apollo_client_exception_num_total | | +#### 3.1.5.4 客户端对接外部监控系统 +详见 [7.2 MetricsExporter扩展](#_7.2_MetricsExporter扩展) + ## 3.2 Spring整合方式 ### 3.2.1 配置 @@ -1440,15 +1314,262 @@ interface是`com.ctrip.framework.apollo.spi.ConfigServiceLoadBalancerClient`。 默认服务提供是`com.ctrip.framework.apollo.spi.RandomConfigServiceLoadBalancerClient`,使用random策略,也就是随机从多个ConfigService中选择1个ConfigService。 + ## 7.2 MetricsExporter扩展 -> from version 2.4.0 -为了满足用户使用apollo-client时,对指标导出的系统有不同的系统需求(Prometheus,Skywalking...) +在2.4.0版本及以上的java客户端中,增加了指标收集,导出的支持,用户可以自行扩展接入不同的监控系统。 + +### 客户端对接Prometheus +引入提供的官方依赖包 +```xml + + com.ctrip.framework.apollo + apollo-plugin-client-prometheus + 2.4.0-SNAPSHOT + +``` +调整配置apollo.client.monitor.external.type=prometheus +```properties +apollo.client.monitor.external.type= prometheus +``` + +这样就可以通过ConfigMonitor拿到ExporterData(格式取决于你配置的监控系统),然后暴露端点给Prometheus即可 + +示例代码 + +```java +@RestController +@ResponseBody +public class TestController { + + @GetMapping("/metrics") + public String metrics() { + ConfigMonitor configMonitor = ConfigService.getConfigMonitor(); + return configMonitor.getExporterData(); + } +} +``` + +启动应用后让Prometheus监听该接口,打印请求日志即可发现如下类似格式信息 -我们在2.4.0版本增强的可观测性中提供了**spi** +``` +# TYPE apollo_client_thread_pool_active_task_count gauge +# HELP apollo_client_thread_pool_active_task_count apollo gauge metrics +apollo_client_thread_pool_active_task_count{thread_pool_name="RemoteConfigRepository"} 0.0 +apollo_client_thread_pool_active_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 +apollo_client_thread_pool_active_task_count{thread_pool_name="AbstractConfigFile"} 0.0 +apollo_client_thread_pool_active_task_count{thread_pool_name="AbstractConfig"} 0.0 +# TYPE apollo_client_namespace_timeout gauge +# HELP apollo_client_namespace_timeout apollo gauge metrics +apollo_client_namespace_timeout 0.0 +# TYPE apollo_client_thread_pool_pool_size gauge +# HELP apollo_client_thread_pool_pool_size apollo gauge metrics +apollo_client_thread_pool_pool_size{thread_pool_name="RemoteConfigRepository"} 1.0 +apollo_client_thread_pool_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 +apollo_client_thread_pool_pool_size{thread_pool_name="AbstractConfigFile"} 0.0 +apollo_client_thread_pool_pool_size{thread_pool_name="AbstractConfig"} 0.0 +# TYPE apollo_client_thread_pool_queue_remaining_capacity gauge +# HELP apollo_client_thread_pool_queue_remaining_capacity apollo gauge metrics +apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="RemoteConfigRepository"} 2.147483647E9 +apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="AbstractApolloClientMetricsExporter"} 2.147483647E9 +apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="AbstractConfigFile"} 0.0 +apollo_client_thread_pool_queue_remaining_capacity{thread_pool_name="AbstractConfig"} 0.0 +# TYPE apollo_client_exception_num counter +# HELP apollo_client_exception_num apollo counter metrics +apollo_client_exception_num_total 1404.0 +apollo_client_exception_num_created 1.729435502796E9 +# TYPE apollo_client_thread_pool_largest_pool_size gauge +# HELP apollo_client_thread_pool_largest_pool_size apollo gauge metrics +apollo_client_thread_pool_largest_pool_size{thread_pool_name="RemoteConfigRepository"} 1.0 +apollo_client_thread_pool_largest_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 +apollo_client_thread_pool_largest_pool_size{thread_pool_name="AbstractConfigFile"} 0.0 +apollo_client_thread_pool_largest_pool_size{thread_pool_name="AbstractConfig"} 0.0 +# TYPE apollo_client_thread_pool_queue_size gauge +# HELP apollo_client_thread_pool_queue_size apollo gauge metrics +apollo_client_thread_pool_queue_size{thread_pool_name="RemoteConfigRepository"} 352.0 +apollo_client_thread_pool_queue_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 0.0 +apollo_client_thread_pool_queue_size{thread_pool_name="AbstractConfigFile"} 0.0 +apollo_client_thread_pool_queue_size{thread_pool_name="AbstractConfig"} 0.0 +# TYPE apollo_client_namespace_usage counter +# HELP apollo_client_namespace_usage apollo counter metrics +apollo_client_namespace_usage_total{namespace="application"} 11.0 +apollo_client_namespace_usage_created{namespace="application"} 1.729435502791E9 +# TYPE apollo_client_thread_pool_core_pool_size gauge +# HELP apollo_client_thread_pool_core_pool_size apollo gauge metrics +apollo_client_thread_pool_core_pool_size{thread_pool_name="RemoteConfigRepository"} 1.0 +apollo_client_thread_pool_core_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.0 +apollo_client_thread_pool_core_pool_size{thread_pool_name="AbstractConfigFile"} 0.0 +apollo_client_thread_pool_core_pool_size{thread_pool_name="AbstractConfig"} 0.0 +# TYPE apollo_client_namespace_not_found gauge +# HELP apollo_client_namespace_not_found apollo gauge metrics +apollo_client_namespace_not_found 351.0 +# TYPE apollo_client_thread_pool_total_task_count gauge +# HELP apollo_client_thread_pool_total_task_count apollo gauge metrics +apollo_client_thread_pool_total_task_count{thread_pool_name="RemoteConfigRepository"} 353.0 +apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 4.0 +apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractConfigFile"} 0.0 +apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractConfig"} 0.0 +# TYPE apollo_client_namespace_first_load_time_spend_in_ms gauge +# HELP apollo_client_namespace_first_load_time_spend_in_ms apollo gauge metrics +apollo_client_namespace_first_load_time_spend_in_ms{namespace="application"} 108.0 +# TYPE apollo_client_thread_pool_maximum_pool_size gauge +# HELP apollo_client_thread_pool_maximum_pool_size apollo gauge metrics +apollo_client_thread_pool_maximum_pool_size{thread_pool_name="RemoteConfigRepository"} 2.147483647E9 +apollo_client_thread_pool_maximum_pool_size{thread_pool_name="AbstractApolloClientMetricsExporter"} 2.147483647E9 +apollo_client_thread_pool_maximum_pool_size{thread_pool_name="AbstractConfigFile"} 2.147483647E9 +apollo_client_thread_pool_maximum_pool_size{thread_pool_name="AbstractConfig"} 2.147483647E9 +# TYPE apollo_client_namespace_item_num gauge +# HELP apollo_client_namespace_item_num apollo gauge metrics +apollo_client_namespace_item_num{namespace="application"} 9.0 +# TYPE apollo_client_thread_pool_completed_task_count gauge +# HELP apollo_client_thread_pool_completed_task_count apollo gauge metrics +apollo_client_thread_pool_completed_task_count{thread_pool_name="RemoteConfigRepository"} 1.0 +apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 3.0 +apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfigFile"} 0.0 +apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfig"} 0.0 +# EOF +``` + +同时查看Prometheus控制台也能看到如下信息 + +![Prometheus console showing Apollo client metrics](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-prometheus.png) + +### 自定义实现案例: 以接入Prometheus为例 + +创建PrometheusApolloClientMetricsExporter类,继承AbstractApoolloClientMetircsExporter(通用指标导出框架) + +继承后大致代码如下 + +```java + +public class PrometheusApolloClientMetricsExporter extends + AbstractApolloClientMetricsExporter implements ApolloClientMetricsExporter { + + @Override + public void doInit() { + + } + + @Override + public boolean isSupport(String form) { + + } + + + @Override + public void registerOrUpdateCounterSample(String name, Map tags, double incrValue) { + + } + + + @Override + public void registerOrUpdateGaugeSample(String name, Map tags, double value) { + + } + + @Override + public String response() { + + } +} + +``` -interface是`com.ctrip.framework.apollo.monitor.internal.exporter.ApolloClientMetricsExporter`。 +doInit方法是供用户在初始化时自行做扩展的,会在AbstractApoolloClientMetircsExporter里的init方法被调用 + +```java + @Override + public void init(List collectors, long collectPeriod) { + log.info("Initializing metrics exporter with {} collectors and collect period of {} seconds.", + collectors.size(), collectPeriod); + doInit(); + this.collectors = collectors; + initScheduleMetricsCollectSync(collectPeriod); + log.info("Metrics collection scheduled with a period of {} seconds.", collectPeriod); + } +``` + +这里引入了prometheus的java客户端,需要对CollectorRegistry和缓存map做初始化 + +```java + private CollectorRegistry registry; + private Map map; + + @Override + public void doInit() { + registry = new CollectorRegistry(); + map = new HashMap<>(); + } +``` + +isSupport方法将会在DefaultApolloClientMetricsExporterFactory通过SPI读取MetricsExporter时被调用做判断,用于实现在有多个SPI实现时可以准确启用用户所配置的那一个Exporter + +比如配置时候你希望启用prometheus,你规定的值为prometheus,那这里就同步 + +```java + @Override + public boolean isSupport(String form) { + return PROMETHEUS.equals(form); + } +``` + +registerOrUpdateCounterSample,registerOrUpdateGaugeSample即是用来注册Counter,Gauge类型指标的方法,只需要根据传来的参数正常注册即可 + +```java + @Override + public void registerOrUpdateCounterSample(String name, Map tags, + double incrValue) { + Counter counter = (Counter) map.get(name); + if (counter == null) { + counter = createCounter(name, tags); + map.put(name, counter); + } + counter.labels(tags.values().toArray(new String[0])).inc(incrValue); + } + + private Counter createCounter(String name, Map tags) { + return Counter.build() + .name(name) + .help("apollo") + .labelNames(tags.keySet().toArray(new String[0])) + .register(registry); + } + + @Override + public void registerOrUpdateGaugeSample(String name, Map tags, double value) { + Gauge gauge = (Gauge) map.get(name); + if (gauge == null) { + gauge = createGauge(name, tags); + map.put(name, gauge); + } + gauge.labels(tags.values().toArray(new String[0])).set(value); + } + + private Gauge createGauge(String name, Map tags) { + return Gauge.build() + .name(name) + .help("apollo") + .labelNames(tags.keySet().toArray(new String[0])) + .register(registry); + } +``` + +最后需要实现response方法,该方法用于导出你接入的监控系统格式的数据,最终会在ConfigMonitor的getExporterData方法里得到,用于用户自行暴露端口然后供监控系统拉取 + +```java + @Override + public String response() { + try (StringWriter writer = new StringWriter()) { + TextFormat.writeFormat(TextFormat.CONTENT_TYPE_OPENMETRICS_100, writer, + registry.metricFamilySamples()); + return writer.toString(); + } catch (IOException e) { + logger.error("Write metrics to Prometheus format failed", e); + return ""; + } + } +``` -我们提供了通用指标导出框架抽象类 `com.ctrip.framework.apollo.monitor.internal.exporter.AbstractApolloClientMetricsExporter`,只需继承该类实现相关方法即可自定义接入其它监控系统,可参考apollo-plugin-client-prometheus的实现 +至此,已经将Client的指标数据接入Prometheus。 -默认无服务提供,即不会导出指标数据 \ No newline at end of file +完整代码:[PrometheusApolloClientMetricsExporter.java]https://github.com/apolloconfig/apollo-java/main/master/apollo-plugin/apollo-plugin-client-prometheus/src/main/java/com/ctrip/framework/apollo/monitor/internal/exporter/impl/PrometheusApolloClientMetricsExporter.java \ No newline at end of file diff --git a/docs/zh/extension/java-client-how-to-use-custom-monitor-system.md b/docs/zh/extension/java-client-how-to-use-custom-monitor-system.md deleted file mode 100644 index 28f6c2b9947..00000000000 --- a/docs/zh/extension/java-client-how-to-use-custom-monitor-system.md +++ /dev/null @@ -1,141 +0,0 @@ -在2.4.0版本及以上的java客户端中,增加了指标收集,导出的支持,用户可以自行扩展接入不同的监控系统。 - -## 以接入Prometheus为例 - -创建PrometheusApolloClientMetricsExporter类,继承AbstractApoolloClientMetircsExporter(通用指标导出框架) - -继承后大致代码如下 - -```java - -public class PrometheusApolloClientMetricsExporter extends - AbstractApolloClientMetricsExporter implements ApolloClientMetricsExporter { - - @Override - public void doInit() { - - } - - @Override - public boolean isSupport(String form) { - - } - - - @Override - public void registerOrUpdateCounterSample(String name, Map tags, double incrValue) { - - } - - - @Override - public void registerOrUpdateGaugeSample(String name, Map tags, double value) { - - } - - @Override - public String response() { - - } -} - -``` - -doInit方法是供用户在初始化时自行做扩展的,会在AbstractApoolloClientMetircsExporter里的init方法被调用 - -```java - @Override - public void init(List collectors, long collectPeriod) { - log.info("Initializing metrics exporter with {} collectors and collect period of {} seconds.", - collectors.size(), collectPeriod); - doInit(); - this.collectors = collectors; - initScheduleMetricsCollectSync(collectPeriod); - log.info("Metrics collection scheduled with a period of {} seconds.", collectPeriod); - } -``` - -这里引入了prometheus的java客户端,需要对CollectorRegistry和缓存map做初始化 - -```java - private CollectorRegistry registry; - private Map map; - - @Override - public void doInit() { - registry = new CollectorRegistry(); - map = new HashMap<>(); - } -``` - -isSupport方法将会在DefaultApolloClientMetricsExporterFactory通过SPI读取MetricsExporter时被调用做判断,用于实现在有多个SPI实现时可以准确启用用户所配置的那一个Exporter - -比如配置时候你希望启用prometheus,你规定的值为prometheus,那这里就同步 - -```java - @Override - public boolean isSupport(String form) { - return PROMETHEUS.equals(form); - } -``` - -registerOrUpdateCounterSample,registerOrUpdateGaugeSample即是用来注册Counter,Gauge类型指标的方法,只需要根据传来的参数正常注册即可 - -```java - @Override - public void registerOrUpdateCounterSample(String name, Map tags, - double incrValue) { - Counter counter = (Counter) map.get(name); - if (counter == null) { - counter = createCounter(name, tags); - map.put(name, counter); - } - counter.labels(tags.values().toArray(new String[0])).inc(incrValue); - } - - private Counter createCounter(String name, Map tags) { - return Counter.build() - .name(name) - .help("apollo") - .labelNames(tags.keySet().toArray(new String[0])) - .register(registry); - } - - @Override - public void registerOrUpdateGaugeSample(String name, Map tags, double value) { - Gauge gauge = (Gauge) map.get(name); - if (gauge == null) { - gauge = createGauge(name, tags); - map.put(name, gauge); - } - gauge.labels(tags.values().toArray(new String[0])).set(value); - } - - private Gauge createGauge(String name, Map tags) { - return Gauge.build() - .name(name) - .help("apollo") - .labelNames(tags.keySet().toArray(new String[0])) - .register(registry); - } -``` - -最后需要实现response方法,该方法用于导出你接入的监控系统格式的数据,最终会在ConfigMonitor的getExporterData方法里得到,用于用户自行暴露端口然后供监控系统拉取 - -```java - @Override - public String response() { - try (StringWriter writer = new StringWriter()) { - TextFormat.writeFormat(TextFormat.CONTENT_TYPE_OPENMETRICS_100, writer, - registry.metricFamilySamples()); - return writer.toString(); - } catch (IOException e) { - logger.error("Write metrics to Prometheus format failed", e); - return ""; - } - } -``` - -至此,已经将Client的指标数据接入Prometheus。 - -完整代码:[code]https://github.com/apolloconfig/apollo-java/main/master/apollo-plugin/apollo-plugin-client-prometheus/src/main/java/com/ctrip/framework/apollo/monitor/internal/exporter/impl/PrometheusApolloClientMetricsExporter.java \ No newline at end of file