From 1a3466cd24d3fc32e2fc48c53ca222447e09cdf8 Mon Sep 17 00:00:00 2001 From: liu Date: Sun, 25 Aug 2024 16:40:09 +0800 Subject: [PATCH 01/12] feat(): add apollo-client-observability docs --- docs/zh/client/java-sdk-user-guide.md | 34 +++++ ...client-how-to-use-custom-monitor-system.md | 141 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 docs/zh/extension/java-client-how-to-use-custom-monitor-system.md diff --git a/docs/zh/client/java-sdk-user-guide.md b/docs/zh/client/java-sdk-user-guide.md index 4250c2bdb9b..14c1602c7dc 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -398,6 +398,26 @@ apollo.label=YOUR-APOLLO-LABEL 3. 通过`app.properties`配置文件 * 可以在`classpath:/META-INF/app.properties`指定`apollo.override-system-properties=true` + +#### 1.2.4.9 Monitor相关配置 + +> 适用于2.4.0及以上版本 +在2.4.0版本开始,客户端的可观测性得到了加强,用户可以通过ConfigService获取到ConfigMonitor直接获得客户端状态信息以及将状态信息以指标形式上报给监控系统,以下是一些相关配置 + +`apollo.client.monitor.enabled`:是否启动Monitor机制, 即ConfigMonitor是否启用,默认false + +`apollo.client.monitor.jmx.enabled`:是否将Monitor数据以Jmx形式暴露,开启后可以通过J-console,Jprofiler等工具查看相关信息,默认为false + +![](https://cdn.jsdelivr.net/gh/Rawven/image@main/2024-08-24-14-59-01-image.png) + +`apollo.client.monitor.exception-queue-size`:设置Monitor存储Exception的最大数量,默认值为25 + +`apollo.client.monitor.external.type`:**非常规配置项**,用于导出指标数据时启用对应监控系统的Exporter,如引入apollo-plugin-client-prometheus则可填写prometheus进行启用,可填配置取决于用户引入的MetricsExporter的SPI使可用官方提供的或自己实现),这种设计是为了用户能更方便的扩展。多填,错填和不填则不启用任何Exporter。 + +具体使用:TODO-LINK + +`apollo.client.monitor.external.export-period`:Exporter从Monitor中导出状态信息(如线程池等)并转为指标数据是通过定时任务的方式,export-period可以控制定时任务的频率,默认为10秒 + # 二、Maven Dependency Apollo的客户端jar包已经上传到中央仓库,应用在实际使用时只需要按照如下方式引入即可。 ```xml @@ -1220,3 +1240,17 @@ interface是`com.ctrip.framework.apollo.spi.ConfigServiceLoadBalancerClient`。 输入是meta server返回的多个ConfigService,输出是1个ConfigService。 默认服务提供是`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版本增强的可观测性中提供了**spi** + +interface是`com.ctrip.framework.apollo.monitor.internal.exporter.ApolloClientMetricsExporter`。 + +我们提供了通用指标导出框架抽象类 `com.ctrip.framework.apollo.monitor.internal.exporter.AbstractApolloClientMetricsExporter`,只需继承该类实现相关方法即可自定义接入其它监控系统,可参考apollo-plugin-client-prometheus的实现 + +默认无服务提供,即不会导出指标数据 \ 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 new file mode 100644 index 00000000000..2b8bd47e41b --- /dev/null +++ b/docs/zh/extension/java-client-how-to-use-custom-monitor-system.md @@ -0,0 +1,141 @@ +在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。 + +完整代码:TODO URL \ No newline at end of file From 7c2bb1e065c758bdf8ade9609bd5659f460b6558 Mon Sep 17 00:00:00 2001 From: liu Date: Mon, 26 Aug 2024 12:48:22 +0800 Subject: [PATCH 02/12] feat(): add apollo-client-observability docs --- docs/zh/client/java-sdk-user-guide.md | 52 +++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/docs/zh/client/java-sdk-user-guide.md b/docs/zh/client/java-sdk-user-guide.md index 14c1602c7dc..e20f47952e9 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -511,6 +511,58 @@ ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML String content = configFile.getContent(); ``` +### 3.1.5 使用Monitor-API + +apollo-client在2.4.0版本里提供了Monitor-API,供用户可以对client有更强的可观测性 + +#### 3.1.5.1 获取ConfigMonitor + +```java + ConfigMonitor configMonitor = ConfigService.getConfigMonitor(); + //错误相关监控API + ApolloClientExceptionMonitorApi exceptionMonitorApi = configMonitor.getExceptionMonitorApi(); + List apolloConfigExceptionList = exceptionMonitorApi.getApolloConfigExceptionList(); + //命名空间相关监控API + ApolloClientNamespaceMonitorApi namespaceMonitorApi = configMonitor.getNamespaceMonitorApi(); + List namespace404 = namespaceMonitorApi.getNotFoundNamespaces(); + //启动参数相关监控API + ApolloClientBootstrapArgsMonitorApi runningParamsMonitorApi = configMonitor.getRunningParamsMonitorApi(); + String bootstrapNamespaces = runningParamsMonitorApi.getBootstrapNamespaces(); + //线程池相关监控API + ApolloClientThreadPoolMonitorApi threadPoolMonitorApi = configMonitor.getThreadPoolMonitorApi(); + ApolloThreadPoolInfo remoteConfigRepositoryThreadPoolInfo = threadPoolMonitorApi.getRemoteConfigRepositoryThreadPoolInfo(); +``` + +#### 3.1.5.2 指标数据表格 + +```java + //用户配置的监控系统形式的指标数据 + String exporterData = configMonitor.getExporterData(); +``` + +| 指标名称 | 类型 | 描述 | 标签 | +|------------------------------------------| --- | --- | --- | +| apollo_client_exception_num | counter | Apollo异常计数 | | +| apollo_client_exception_num_total | counter | 总异常计数 | | +| apollo_client_exception_num_created | counter | 创建时间戳 | | +| apollo_client_queueSize | gauge | Apollo队列大小 | ThreadPoolName | +| apollo_client_config_file_num | gauge | 配置文件数量 | namespace | +| apollo_client_poolSize | gauge | 线程池大小 | ThreadPoolName | +| apollo_client_currentLoad | gauge | 当前负载 | ThreadPoolName | +| apollo_client_namespace_first_load_spend | gauge | 首次加载时间 | namespace | +| apollo_client_namespace_item_num | gauge | 命名空间项数量 | namespace | +| apollo_client_namespace_usage | counter | 命名空间使用计数 | namespace | +| apollo_client_largestPoolSize | gauge | 最大线程池大小 | ThreadPoolName | +| apollo_client_maximumPoolSize | gauge | 最大线程池容量 | ThreadPoolName | +| apollo_client_corePoolSize | gauge | 核心线程池大小 | ThreadPoolName | +| apollo_client_queueRemainingCapacity | gauge | 队列剩余容量 | ThreadPoolName | +| apollo_client_namespace_not_found | gauge | 未找到的命名空间计数 | | +| apollo_client_namespace_timeout | gauge | 命名空间超时计数 | | +| apollo_client_activeTaskCount | gauge | 活动任务计数 | ThreadPoolName | +| apollo_client_queueCapacity | gauge | 队列容量 | ThreadPoolName | +| apollo_client_totalTaskCount | gauge | 总任务计数 | ThreadPoolName | +| apollo_client_completedTaskCount | gauge | 完成任务计数 | ThreadPoolName | + ## 3.2 Spring整合方式 ### 3.2.1 配置 From e2e8c7f4bca7dd1db026431ada4e9b0279f02f6c Mon Sep 17 00:00:00 2001 From: liu Date: Mon, 26 Aug 2024 13:14:50 +0800 Subject: [PATCH 03/12] feat(): add apollo-client-observability docs --- docs/en/client/java-sdk-user-guide.md | 224 ++++++++++++++++++ ...client-how-to-use-custom-monitor-system.md | 141 +++++++++++ docs/zh/client/java-sdk-user-guide.md | 208 +++++++++++++--- ...client-how-to-use-custom-monitor-system.md | 4 +- 4 files changed, 542 insertions(+), 35 deletions(-) create mode 100644 docs/en/extension/java-client-how-to-use-custom-monitor-system.md diff --git a/docs/en/client/java-sdk-user-guide.md b/docs/en/client/java-sdk-user-guide.md index 2f2d887ef77..344e1d02a02 100644 --- a/docs/en/client/java-sdk-user-guide.md +++ b/docs/en/client/java-sdk-user-guide.md @@ -414,6 +414,26 @@ 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. + +![Monitor Configuration](https://cdn.jsdelivr.net/gh/Rawven/image@main/2024-08-24-14-59-01-image.png) + +`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. @@ -450,6 +470,8 @@ 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. @@ -519,6 +541,197 @@ 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/20240828003803.png) + +#### 3.1.5.2 Exporting Metrics via Prometheus + +Configure apollo.client.monitor.external.type to prometheus in the configuration (make sure to include apollo-client-plugin-prometheus and necessary dependencies!). +```yaml +apollo: + client: + monitor: + enabled: true + external: + type: prometheus +``` + +You can retrieve ExporterData via ConfigMonitor (the format depends on your configured monitoring system) and then expose the endpoint to Prometheus. +示例代码 + +```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_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_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_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"} 2.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_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_namespace_item_num gauge +# HELP apollo_client_namespace_item_num apollo gauge metrics +apollo_client_namespace_item_num{namespace="application"} 8.0 +apollo_client_namespace_item_num{namespace="application1"} 2.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"} 2.0 +apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 0.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 +# TYPE apollo_client_namespace_not_found gauge +# HELP apollo_client_namespace_not_found apollo gauge metrics +apollo_client_namespace_not_found 0.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"} 4.0 +apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.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_usage counter +# HELP apollo_client_namespace_usage apollo counter metrics +apollo_client_namespace_usage_total{namespace="application"} 1.0 +apollo_client_namespace_usage_created{namespace="application"} 1.725899226271E9 +apollo_client_namespace_usage_total{namespace="application1"} 1.0 +apollo_client_namespace_usage_created{namespace="application1"} 1.72589922627E9 +# 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_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"} 99.0 +apollo_client_namespace_first_load_time_spend_in_ms{namespace="application1"} 40.0 +# 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 +# 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 @@ -1282,3 +1495,14 @@ 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 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 new file mode 100644 index 00000000000..5bd8d6fbb0f --- /dev/null +++ b/docs/en/extension/java-client-how-to-use-custom-monitor-system.md @@ -0,0 +1,141 @@ +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 e20f47952e9..92c549eb064 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -414,7 +414,7 @@ apollo.label=YOUR-APOLLO-LABEL `apollo.client.monitor.external.type`:**非常规配置项**,用于导出指标数据时启用对应监控系统的Exporter,如引入apollo-plugin-client-prometheus则可填写prometheus进行启用,可填配置取决于用户引入的MetricsExporter的SPI使可用官方提供的或自己实现),这种设计是为了用户能更方便的扩展。多填,错填和不填则不启用任何Exporter。 -具体使用:TODO-LINK +具体使用见 扩展开发-java客户端接入不同监控系统 `apollo.client.monitor.external.export-period`:Exporter从Monitor中导出状态信息(如线程池等)并转为指标数据是通过定时任务的方式,export-period可以控制定时任务的频率,默认为10秒 @@ -511,11 +511,151 @@ ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML String content = configFile.getContent(); ``` -### 3.1.5 使用Monitor-API +### 3.1.5 使用Monitor功能 -apollo-client在2.4.0版本里提供了Monitor-API,供用户可以对client有更强的可观测性 +apollo-client在2.4.0版本里大幅增强了可观测性,提供了ConfigMonitor-API以及JMX,Prometheus的指标导出方式 -#### 3.1.5.1 获取ConfigMonitor +若启用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 +``` + +启动应用后,开启J-console或J-profiler即可查看,这里用J-profiler做例子 + +![](https://raw.githubusercontent.com/Rawven/image/main/20240828003803.png) + +#### 3.1.5.2 以Prometheus形式导出指标 + +在配置中对apollo.client.monitor.external.type中配置为prometheus(同时请确认是否引入了apollo-client-plugin-prometheus和必要依赖!) + +```yaml +apollo: + client: + monitor: + enabled: true + 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监听该接口,打印请求日志即可发现如下类似格式信息 + +``` +# 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_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_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"} 2.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_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_namespace_item_num gauge +# HELP apollo_client_namespace_item_num apollo gauge metrics +apollo_client_namespace_item_num{namespace="application"} 8.0 +apollo_client_namespace_item_num{namespace="application1"} 2.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"} 2.0 +apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 0.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 +# TYPE apollo_client_namespace_not_found gauge +# HELP apollo_client_namespace_not_found apollo gauge metrics +apollo_client_namespace_not_found 0.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"} 4.0 +apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.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_usage counter +# HELP apollo_client_namespace_usage apollo counter metrics +apollo_client_namespace_usage_total{namespace="application"} 1.0 +apollo_client_namespace_usage_created{namespace="application"} 1.725899226271E9 +apollo_client_namespace_usage_total{namespace="application1"} 1.0 +apollo_client_namespace_usage_created{namespace="application1"} 1.72589922627E9 +# 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_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"} 99.0 +apollo_client_namespace_first_load_time_spend_in_ms{namespace="application1"} 40.0 +# 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 +# EOF +``` + +同时查看Prometheus控制台也能看到如下信息 + +![](https://raw.githubusercontent.com/Rawven/image/main/20240922125033.png) + +#### 3.1.5.3 用户手动调用ConfigMonitor-API获取相关数据(比如当用户需要手动加工数据上报到监控系统时) ```java ConfigMonitor configMonitor = ConfigService.getConfigMonitor(); @@ -533,35 +673,37 @@ apollo-client在2.4.0版本里提供了Monitor-API,供用户可以对client有 ApolloThreadPoolInfo remoteConfigRepositoryThreadPoolInfo = threadPoolMonitorApi.getRemoteConfigRepositoryThreadPoolInfo(); ``` -#### 3.1.5.2 指标数据表格 - -```java - //用户配置的监控系统形式的指标数据 - String exporterData = configMonitor.getExporterData(); -``` - -| 指标名称 | 类型 | 描述 | 标签 | -|------------------------------------------| --- | --- | --- | -| apollo_client_exception_num | counter | Apollo异常计数 | | -| apollo_client_exception_num_total | counter | 总异常计数 | | -| apollo_client_exception_num_created | counter | 创建时间戳 | | -| apollo_client_queueSize | gauge | Apollo队列大小 | ThreadPoolName | -| apollo_client_config_file_num | gauge | 配置文件数量 | namespace | -| apollo_client_poolSize | gauge | 线程池大小 | ThreadPoolName | -| apollo_client_currentLoad | gauge | 当前负载 | ThreadPoolName | -| apollo_client_namespace_first_load_spend | gauge | 首次加载时间 | namespace | -| apollo_client_namespace_item_num | gauge | 命名空间项数量 | namespace | -| apollo_client_namespace_usage | counter | 命名空间使用计数 | namespace | -| apollo_client_largestPoolSize | gauge | 最大线程池大小 | ThreadPoolName | -| apollo_client_maximumPoolSize | gauge | 最大线程池容量 | ThreadPoolName | -| apollo_client_corePoolSize | gauge | 核心线程池大小 | ThreadPoolName | -| apollo_client_queueRemainingCapacity | gauge | 队列剩余容量 | ThreadPoolName | -| apollo_client_namespace_not_found | gauge | 未找到的命名空间计数 | | -| apollo_client_namespace_timeout | gauge | 命名空间超时计数 | | -| apollo_client_activeTaskCount | gauge | 活动任务计数 | ThreadPoolName | -| apollo_client_queueCapacity | gauge | 队列容量 | ThreadPoolName | -| apollo_client_totalTaskCount | gauge | 总任务计数 | ThreadPoolName | -| apollo_client_completedTaskCount | gauge | 完成任务计数 | ThreadPoolName | +#### 3.1.5.4 指标数据表格 + +## Namespace Metrics + +| 指标名称 | 标签 | +| ---------------------------------------- | --------- | +| 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 + +| 指标名称 | 标签 | +| -------------------------------------------------- | ---------------- | +| 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 + +| 指标名称 | 标签 | +| --------------------------------- | ---- | +| apollo_client_exception_num_total | | ## 3.2 Spring整合方式 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 index 2b8bd47e41b..28f6c2b9947 100644 --- 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 @@ -1,4 +1,4 @@ -在2.4.0版本的java客户端中,增加了指标收集,导出的支持,用户可以自行扩展接入不同的监控系统。 +在2.4.0版本及以上的java客户端中,增加了指标收集,导出的支持,用户可以自行扩展接入不同的监控系统。 ## 以接入Prometheus为例 @@ -138,4 +138,4 @@ registerOrUpdateCounterSample,registerOrUpdateGaugeSample即是用来注册Count 至此,已经将Client的指标数据接入Prometheus。 -完整代码:TODO URL \ No newline at end of file +完整代码:[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 From 2b52c0283128cc9509963ea93f397db816d52a65 Mon Sep 17 00:00:00 2001 From: liu Date: Mon, 26 Aug 2024 13:14:50 +0800 Subject: [PATCH 04/12] feat(): add apollo-client-observability docs --- docs/en/client/java-sdk-user-guide.md | 234 ++++++++++++++++++ ...client-how-to-use-custom-monitor-system.md | 141 +++++++++++ docs/zh/client/java-sdk-user-guide.md | 214 +++++++++++++--- ...client-how-to-use-custom-monitor-system.md | 4 +- 4 files changed, 558 insertions(+), 35 deletions(-) create mode 100644 docs/en/extension/java-client-how-to-use-custom-monitor-system.md diff --git a/docs/en/client/java-sdk-user-guide.md b/docs/en/client/java-sdk-user-guide.md index 2f2d887ef77..fb65ba35241 100644 --- a/docs/en/client/java-sdk-user-guide.md +++ b/docs/en/client/java-sdk-user-guide.md @@ -414,6 +414,26 @@ 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. + +![Monitor Configuration](https://cdn.jsdelivr.net/gh/Rawven/image@main/2024-08-24-14-59-01-image.png) + +`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. @@ -450,6 +470,8 @@ 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. @@ -519,6 +541,207 @@ 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/20240828003803.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_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_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_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"} 2.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_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_namespace_item_num gauge +# HELP apollo_client_namespace_item_num apollo gauge metrics +apollo_client_namespace_item_num{namespace="application"} 8.0 +apollo_client_namespace_item_num{namespace="application1"} 2.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"} 2.0 +apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 0.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 +# TYPE apollo_client_namespace_not_found gauge +# HELP apollo_client_namespace_not_found apollo gauge metrics +apollo_client_namespace_not_found 0.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"} 4.0 +apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.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_usage counter +# HELP apollo_client_namespace_usage apollo counter metrics +apollo_client_namespace_usage_total{namespace="application"} 1.0 +apollo_client_namespace_usage_created{namespace="application"} 1.725899226271E9 +apollo_client_namespace_usage_total{namespace="application1"} 1.0 +apollo_client_namespace_usage_created{namespace="application1"} 1.72589922627E9 +# 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_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"} 99.0 +apollo_client_namespace_first_load_time_spend_in_ms{namespace="application1"} 40.0 +# 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 +# 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 @@ -1282,3 +1505,14 @@ 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 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 new file mode 100644 index 00000000000..5bd8d6fbb0f --- /dev/null +++ b/docs/en/extension/java-client-how-to-use-custom-monitor-system.md @@ -0,0 +1,141 @@ +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 e20f47952e9..4abd1b7d612 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -414,7 +414,7 @@ apollo.label=YOUR-APOLLO-LABEL `apollo.client.monitor.external.type`:**非常规配置项**,用于导出指标数据时启用对应监控系统的Exporter,如引入apollo-plugin-client-prometheus则可填写prometheus进行启用,可填配置取决于用户引入的MetricsExporter的SPI使可用官方提供的或自己实现),这种设计是为了用户能更方便的扩展。多填,错填和不填则不启用任何Exporter。 -具体使用:TODO-LINK +具体使用见 扩展开发-java客户端接入不同监控系统 `apollo.client.monitor.external.export-period`:Exporter从Monitor中导出状态信息(如线程池等)并转为指标数据是通过定时任务的方式,export-period可以控制定时任务的频率,默认为10秒 @@ -511,11 +511,157 @@ ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML String content = configFile.getContent(); ``` -### 3.1.5 使用Monitor-API +### 3.1.5 使用Monitor功能 -apollo-client在2.4.0版本里提供了Monitor-API,供用户可以对client有更强的可观测性 +apollo-client在2.4.0版本里大幅增强了可观测性,提供了ConfigMonitor-API以及JMX,Prometheus的指标导出方式 -#### 3.1.5.1 获取ConfigMonitor +若启用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 +``` + +启动应用后,开启J-console或J-profiler即可查看,这里用J-profiler做例子 + +![](https://raw.githubusercontent.com/Rawven/image/main/20240828003803.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 +``` + +这样就可以通过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_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_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_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"} 2.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_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_namespace_item_num gauge +# HELP apollo_client_namespace_item_num apollo gauge metrics +apollo_client_namespace_item_num{namespace="application"} 8.0 +apollo_client_namespace_item_num{namespace="application1"} 2.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"} 2.0 +apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 0.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 +# TYPE apollo_client_namespace_not_found gauge +# HELP apollo_client_namespace_not_found apollo gauge metrics +apollo_client_namespace_not_found 0.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"} 4.0 +apollo_client_thread_pool_total_task_count{thread_pool_name="AbstractApolloClientMetricsExporter"} 1.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_usage counter +# HELP apollo_client_namespace_usage apollo counter metrics +apollo_client_namespace_usage_total{namespace="application"} 1.0 +apollo_client_namespace_usage_created{namespace="application"} 1.725899226271E9 +apollo_client_namespace_usage_total{namespace="application1"} 1.0 +apollo_client_namespace_usage_created{namespace="application1"} 1.72589922627E9 +# 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_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"} 99.0 +apollo_client_namespace_first_load_time_spend_in_ms{namespace="application1"} 40.0 +# 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 +# EOF +``` + +同时查看Prometheus控制台也能看到如下信息 + +![](https://raw.githubusercontent.com/Rawven/image/main/20240922125033.png) + +#### 3.1.5.3 用户手动调用ConfigMonitor-API获取相关数据(比如当用户需要手动加工数据上报到监控系统时) ```java ConfigMonitor configMonitor = ConfigService.getConfigMonitor(); @@ -533,35 +679,37 @@ apollo-client在2.4.0版本里提供了Monitor-API,供用户可以对client有 ApolloThreadPoolInfo remoteConfigRepositoryThreadPoolInfo = threadPoolMonitorApi.getRemoteConfigRepositoryThreadPoolInfo(); ``` -#### 3.1.5.2 指标数据表格 - -```java - //用户配置的监控系统形式的指标数据 - String exporterData = configMonitor.getExporterData(); -``` - -| 指标名称 | 类型 | 描述 | 标签 | -|------------------------------------------| --- | --- | --- | -| apollo_client_exception_num | counter | Apollo异常计数 | | -| apollo_client_exception_num_total | counter | 总异常计数 | | -| apollo_client_exception_num_created | counter | 创建时间戳 | | -| apollo_client_queueSize | gauge | Apollo队列大小 | ThreadPoolName | -| apollo_client_config_file_num | gauge | 配置文件数量 | namespace | -| apollo_client_poolSize | gauge | 线程池大小 | ThreadPoolName | -| apollo_client_currentLoad | gauge | 当前负载 | ThreadPoolName | -| apollo_client_namespace_first_load_spend | gauge | 首次加载时间 | namespace | -| apollo_client_namespace_item_num | gauge | 命名空间项数量 | namespace | -| apollo_client_namespace_usage | counter | 命名空间使用计数 | namespace | -| apollo_client_largestPoolSize | gauge | 最大线程池大小 | ThreadPoolName | -| apollo_client_maximumPoolSize | gauge | 最大线程池容量 | ThreadPoolName | -| apollo_client_corePoolSize | gauge | 核心线程池大小 | ThreadPoolName | -| apollo_client_queueRemainingCapacity | gauge | 队列剩余容量 | ThreadPoolName | -| apollo_client_namespace_not_found | gauge | 未找到的命名空间计数 | | -| apollo_client_namespace_timeout | gauge | 命名空间超时计数 | | -| apollo_client_activeTaskCount | gauge | 活动任务计数 | ThreadPoolName | -| apollo_client_queueCapacity | gauge | 队列容量 | ThreadPoolName | -| apollo_client_totalTaskCount | gauge | 总任务计数 | ThreadPoolName | -| apollo_client_completedTaskCount | gauge | 完成任务计数 | ThreadPoolName | +#### 3.1.5.4 指标数据表格 + +## Namespace Metrics + +| 指标名称 | 标签 | +| ---------------------------------------- | --------- | +| 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 + +| 指标名称 | 标签 | +| -------------------------------------------------- | ---------------- | +| 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 + +| 指标名称 | 标签 | +| --------------------------------- | ---- | +| apollo_client_exception_num_total | | ## 3.2 Spring整合方式 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 index 2b8bd47e41b..28f6c2b9947 100644 --- 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 @@ -1,4 +1,4 @@ -在2.4.0版本的java客户端中,增加了指标收集,导出的支持,用户可以自行扩展接入不同的监控系统。 +在2.4.0版本及以上的java客户端中,增加了指标收集,导出的支持,用户可以自行扩展接入不同的监控系统。 ## 以接入Prometheus为例 @@ -138,4 +138,4 @@ registerOrUpdateCounterSample,registerOrUpdateGaugeSample即是用来注册Count 至此,已经将Client的指标数据接入Prometheus。 -完整代码:TODO URL \ No newline at end of file +完整代码:[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 From c172d6c01226f62e0715575f48eb31975ead3ca1 Mon Sep 17 00:00:00 2001 From: Rawven Date: Wed, 23 Oct 2024 21:40:12 +0800 Subject: [PATCH 05/12] Update docs/zh/client/java-sdk-user-guide.md Co-authored-by: wxq --- docs/zh/client/java-sdk-user-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/client/java-sdk-user-guide.md b/docs/zh/client/java-sdk-user-guide.md index dd904cf0e32..00d7c812093 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -399,7 +399,7 @@ apollo.label=YOUR-APOLLO-LABEL * 可以在`classpath:/META-INF/app.properties`指定`apollo.override-system-properties=true` -#### 1.2.4.9 Monitor相关配置 +#### 1.2.4.9 开启客户端监控 > 适用于2.4.0及以上版本 在2.4.0版本开始,客户端的可观测性得到了加强,用户可以通过ConfigService获取到ConfigMonitor直接获得客户端状态信息以及将状态信息以指标形式上报给监控系统,以下是一些相关配置 From cd0bd7eb106397fcf8b9147adff7c4b44d709f55 Mon Sep 17 00:00:00 2001 From: Rawven Date: Wed, 23 Oct 2024 21:40:26 +0800 Subject: [PATCH 06/12] docs(): add doc --- doc/images/apollo-client-monitor-jmx.png | Bin 0 -> 87217 bytes .../apollo-client-monitor-prometheus.png | Bin 0 -> 30299 bytes docs/en/client/java-sdk-user-guide.md | 234 +--------- ...client-how-to-use-custom-monitor-system.md | 141 ------ docs/zh/client/java-sdk-user-guide.md | 412 ++++++++++++------ ...client-how-to-use-custom-monitor-system.md | 141 ------ 6 files changed, 268 insertions(+), 660 deletions(-) create mode 100644 doc/images/apollo-client-monitor-jmx.png create mode 100644 doc/images/apollo-client-monitor-prometheus.png delete mode 100644 docs/en/extension/java-client-how-to-use-custom-monitor-system.md delete mode 100644 docs/zh/extension/java-client-how-to-use-custom-monitor-system.md diff --git a/doc/images/apollo-client-monitor-jmx.png b/doc/images/apollo-client-monitor-jmx.png new file mode 100644 index 0000000000000000000000000000000000000000..703b055e001baa7148649047a90a966415be8c5b GIT binary patch literal 87217 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 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..db3692b9052 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 -``` - -这样就可以通过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控制台也能看到如下信息 +![JProfiler showing Apollo client monitoring metrics in JMX](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-jmx.png) -![](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,263 @@ 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客户端中,增加了指标收集,导出的支持,用户可以自行扩展接入不同的监控系统。 -我们在2.4.0版本增强的可观测性中提供了**spi** +### 客户端对接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即可 + +示例代码 -interface是`com.ctrip.framework.apollo.monitor.internal.exporter.ApolloClientMetricsExporter`。 +```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控制台也能看到如下信息 + +![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() { + + } +} + +``` + +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 From 07c29b621062ce98fd01393f731a0229d4ea6f9b Mon Sep 17 00:00:00 2001 From: Rawven Date: Wed, 23 Oct 2024 21:40:26 +0800 Subject: [PATCH 07/12] docs(): add doc --- doc/images/apollo-client-monitor-jmx.png | Bin 0 -> 87217 bytes .../apollo-client-monitor-prometheus.png | Bin 0 -> 30299 bytes docs/en/client/java-sdk-user-guide.md | 234 +--------- ...client-how-to-use-custom-monitor-system.md | 141 ------ docs/zh/client/java-sdk-user-guide.md | 412 ++++++++++++------ ...client-how-to-use-custom-monitor-system.md | 141 ------ 6 files changed, 268 insertions(+), 660 deletions(-) create mode 100644 doc/images/apollo-client-monitor-jmx.png create mode 100644 doc/images/apollo-client-monitor-prometheus.png delete mode 100644 docs/en/extension/java-client-how-to-use-custom-monitor-system.md delete mode 100644 docs/zh/extension/java-client-how-to-use-custom-monitor-system.md diff --git a/doc/images/apollo-client-monitor-jmx.png b/doc/images/apollo-client-monitor-jmx.png new file mode 100644 index 0000000000000000000000000000000000000000..703b055e001baa7148649047a90a966415be8c5b GIT binary patch literal 87217 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 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..89ec0c5800f 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 -``` - -这样就可以通过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控制台也能看到如下信息 +![JProfiler showing Apollo client monitoring metrics in JMX](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-jmx.png) -![](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扩展](#_72_metricsExporter扩展) + ## 3.2 Spring整合方式 ### 3.2.1 配置 @@ -1440,15 +1314,263 @@ 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客户端中,增加了指标收集,导出的支持,用户可以自行扩展接入不同的监控系统。 -我们在2.4.0版本增强的可观测性中提供了**spi** +### 客户端对接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即可 + +示例代码 -interface是`com.ctrip.framework.apollo.monitor.internal.exporter.ApolloClientMetricsExporter`。 +```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控制台也能看到如下信息 + +![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() { + + } +} + +``` + +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 From 84c55c8152713b8162987fa6bddf93b6a43c49b9 Mon Sep 17 00:00:00 2001 From: Rawven Date: Wed, 23 Oct 2024 23:22:36 +0800 Subject: [PATCH 08/12] Update docs/zh/client/java-sdk-user-guide.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- docs/zh/client/java-sdk-user-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/client/java-sdk-user-guide.md b/docs/zh/client/java-sdk-user-guide.md index db3692b9052..d62cf11d8ec 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -1573,4 +1573,4 @@ registerOrUpdateCounterSample,registerOrUpdateGaugeSample即是用来注册Count 至此,已经将Client的指标数据接入Prometheus。 -完整代码:[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 +完整代码:[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 From f7166bf46e0e4b4250fe1839d04bbfe9bf5f9374 Mon Sep 17 00:00:00 2001 From: liu Date: Sat, 28 Dec 2024 00:30:36 +0800 Subject: [PATCH 09/12] docs(): add doc --- .../apollo-client-monitor-exporter-load.jpg | Bin 0 -> 58592 bytes docs/zh/client/java-sdk-user-guide.md | 33 ++++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 doc/images/apollo-client-monitor-exporter-load.jpg diff --git a/doc/images/apollo-client-monitor-exporter-load.jpg b/doc/images/apollo-client-monitor-exporter-load.jpg new file mode 100644 index 0000000000000000000000000000000000000000..12883f22567035db3025b54a4952600c18df0466 GIT binary patch literal 58592 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 NQ%zeHb@lF_{|9=V?j`^L literal 0 HcmV?d00001 diff --git a/docs/zh/client/java-sdk-user-guide.md b/docs/zh/client/java-sdk-user-guide.md index 9e1708887e4..bda435fa2b8 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -419,7 +419,7 @@ apollo.client.monitor.jmx.enabled = true apollo.client.monitor.exception-queue-size= 30 #4.指定导出指标数据使用的对应监控系统的Exporter类型,如引入apollo-plugin-client-prometheus则可填写prometheus进行启用, -#可填配置取决于用户引入的MetricsExporter的SPI +# 取决于SPI MetricsExporter的实现 apollo.client.monitor.external.type= prometheus #5.指定Exporter从Monitor中导出状态信息转为指标数据的频率,默认为10秒导出一次, @@ -427,7 +427,6 @@ apollo.client.monitor.external.export-period= 20 ``` -======= #### 1.2.4.10 ConfigMap缓存设置 > 适用于2.4.0及以上版本 @@ -1427,7 +1426,7 @@ interface是`com.ctrip.framework.apollo.spi.ConfigServiceLoadBalancerClient`。 ## 7.2 指标输出到Prometheus > 适用于2.4.0及以上版本 -在2.4.0版本及以上的java客户端中,增加了指标收集,导出的支持,默认支持Prometheus,用户可以自行扩展接入不同的监控系统。 +可支持导出指标到Prometheus,或者基于SPI编写不同的实现来接入不同的监控系统。 引入客户端插件 ```xml @@ -1548,14 +1547,20 @@ apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfig" ## 7.3 指标输出到自定义监控系统 > 适用于2.4.0及以上版本 -需要写1个Exporter, 继承AbstractApolloClientMetricsExporter, 并实现里面的 +用户需要自行编写MetricsExporter, 继承AbstractApolloClientMetricsExporter, 实现里面的 doInit (初始化方法), isSupport (external-type配置调用方法), registerOrUpdateCounterSample (注册更新Counter指标方法), registerOrUpdateGaugeSample (注册更新Gauge指标方法), response (导出所需类型指标数据方法) +并配置相关SPI文件 -### skyWalking为例 +MetricsExporter加载流程图 +![Exporter load by apollo client](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-exporter-load.jpg) + + + +### 7.3.1 SkyWalking案例 通过配置 ```properties apollo.client.monitor.enabled=true @@ -1566,13 +1571,15 @@ apollo.client.monitor.external.type=skywalking 创建SkyWalkingMetricsExporter类,继承AbstractApolloClientMetricsExporter -继承后大致代码如下 +继承后大致代码如下 +注意: 样例演示,切勿直接到生产直接使用,请根据公司内具体情况来实现 ```java public class SkyWalkingMetricsExporter extends AbstractApolloClientMetricsExporter { private static final String SKYWALKING = "skywalking"; protected SkywalkingMeterRegistry registry; + //用户设计时,需考虑存储指标的数据结构是否有内存占用过多问题 protected Map counterMap; private Map gaugeMap; private Map> gaugeValues; @@ -1660,10 +1667,13 @@ public void init(List collectors, long collect apm-toolkit-micrometer-1.10 ``` -根据Micrometer的机制初始化SkywalkingMeterRegistry,以及一些map用于存储指标数据 +根据Micrometer的机制初始化SkywalkingMeterRegistry, +以及一些map用于存储指标数据 + ```java private static final String SKYWALKING = "skywalking"; private SkywalkingMeterRegistry registry; +//用户设计时,需考虑存储指标的数据结构是否有内存占用过多问题 private Map counterMap; private Map gaugeMap; private Map> gaugeValues; @@ -1747,4 +1757,13 @@ public String response() { } ``` +最后在项目目录下resources/META-INF/services编写对应的spi文件,告诉框架来加载这个类 +文件名为com.ctrip.framework.apollo.monitor.internal.exporter.ApolloClientMetricsExporter +```text +your.package.SkyWalkingMetricsExporter +``` 至此,已经将Client的指标数据接入SkyWalking。 + +### 7.3.2 Prometheus案例 + +[PrometheusApolloClientMetricsExporter.java](https://github.com/apolloconfig/apollo-java/blob/main/apollo-plugin/apollo-plugin-client-prometheus/src/main/java/com/ctrip/framework/apollo/monitor/internal/exporter/impl/PrometheusApolloClientMetricsExporter.java) From 1b89685c2500f5b14f36421d11e95c6e7140dbae Mon Sep 17 00:00:00 2001 From: liu Date: Sat, 28 Dec 2024 01:08:47 +0800 Subject: [PATCH 10/12] docs(): add english doc --- docs/en/client/java-sdk-user-guide.md | 448 +++++++++++++++++++++++++- docs/zh/client/java-sdk-user-guide.md | 14 +- 2 files changed, 454 insertions(+), 8 deletions(-) diff --git a/docs/en/client/java-sdk-user-guide.md b/docs/en/client/java-sdk-user-guide.md index 024aac7b17f..fcaafe84afa 100644 --- a/docs/en/client/java-sdk-user-guide.md +++ b/docs/en/client/java-sdk-user-guide.md @@ -415,6 +415,32 @@ 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 Enable Client Monitoring + +> Applicable to version 2.4.0 and above + +After enabling the following configurations, you can use `ConfigService.getConfigMonitor()` to retrieve client monitoring information and enable automatic reporting. + +```properties +# 1. Whether to enable the Monitor mechanism, i.e., whether ConfigMonitor is enabled. Default is false. +apollo.client.monitor.enabled = true + +# 2. Whether to expose Monitor data in JMX format. When enabled, you can view related information through tools like J-console. Default is false. +apollo.client.monitor.jmx.enabled = true + +# 3. The maximum number of exception logs that Monitor can store. The default is 25, following the FIFO principle. +apollo.client.monitor.exception-queue-size = 30 + +# 4. Specify the Exporter type for exporting metric data to the corresponding monitoring system. +# If you introduce apollo-plugin-client-prometheus, set this to "prometheus" to enable it. +# This depends on the SPI implementation of MetricsExporter. +apollo.client.monitor.external.type = prometheus + +# 5. Specify the frequency at which the Exporter exports status information from Monitor as metric data. +# The default is once every 10 seconds. +apollo.client.monitor.external.export-period = 20 + + #### 1.2.4.10 ConfigMap cache > For version 2.4.0 and above @@ -611,6 +637,84 @@ ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML String content = configFile.getContent(); ``` +### 3.1.5 Retrieve Client Monitoring Metrics +> Applicable to version 2.4.0 and above + +Apollo Client significantly enhanced observability in version 2.4.0, providing the ConfigMonitor API as well as metric export options via JMX and Prometheus. For configuration details, see [1.2.4.9 Enable Client Monitoring](#_1249-开启客户端监控). + +#### 3.1.5.1 Retrieve Monitoring Data via ConfigMonitor + +```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(); +// Bootstrap parameter-related monitoring API +ApolloClientBootstrapArgsMonitorApi runningParamsMonitorApi = configMonitor.getBootstrapArgsMonitorApi(); +String bootstrapNamespaces = runningParamsMonitorApi.getBootstrapNamespaces(); +// Thread pool-related monitoring API +ApolloClientThreadPoolMonitorApi threadPoolMonitorApi = configMonitor.getThreadPoolMonitorApi(); +ApolloThreadPoolInfo remoteConfigRepositoryThreadPoolInfo = threadPoolMonitorApi.getRemoteConfigRepositoryThreadPoolInfo(); +``` + + +#### 3.1.5.2 Expose Status Information via JMX + +Enable the relevant configuration: + +```properties +apollo.client.monitor.enabled = true +apollo.client.monitor.jmx.enabled = true +``` + +After starting the application, use J-console or similar tools to view the metrics. Below is an example using J-console: + +![showing Apollo client monitoring metrics in JMX](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-jmx.jpg) +#### 3.1.5.3 Client Export Metrics to External Monitoring Systems + +Users can customize the integration with monitoring systems such as Prometheus as needed. The client provides an SPI, see [7.2 MetricsExporter Extension](#_7.2_MetricsExporter-extension) for details. + +*Related Metrics Data Tables* + +**Namespace Metrics** + +Metric corresponding API: ApolloClientNamespaceMonitorApi + +| Metric Name | Tag | Corresponding Monitor-API | +| ---------------------------------------------------- | ---------- | --------------------------------------------------- | +| apollo_client_namespace_usage_total | namespace | namespaceMetrics.getUsageCount() | +| apollo_client_namespace_item_num | namespace | namespaceMetrics.getFirstLoadTimeSpendInMs() | +| apollo_client_namespace_not_found | | namespaceMonitorApi.getNotFoundNamespaces() | +| apollo_client_namespace_timeout | | namespaceMonitorApi.getTimeoutNamespaces() | +| apollo_client_namespace_first_load_time_spend_in_ms | namespace | namespaceMetrics.getLatestUpdateTime | + +**Thread Pool Metrics** + +Metric corresponding API: ApolloClientThreadPoolMonitorApi + +| Metric Name | Tag | Corresponding Monitor-API | +| ---------------------------------------------------- | --------------- | --------------------------------------------------- | +| apollo_client_thread_pool_pool_size | thread_pool_name | threadPoolInfo.getPoolSize() | +| apollo_client_thread_pool_maximum_pool_size | thread_pool_name | threadPoolInfo.getMaximumPoolSize() | +| apollo_client_thread_pool_largest_pool_size | thread_pool_name | threadPoolInfo.getLargestPoolSize() | +| apollo_client_thread_pool_completed_task_count | thread_pool_name | threadPoolInfo.getCompletedTaskCount() | +| apollo_client_thread_pool_queue_remaining_capacity | thread_pool_name | threadPoolInfo.getQueueRemainingCapacity() | +| apollo_client_thread_pool_total_task_count | thread_pool_name | threadPoolInfo.getTotalTaskCount() | +| apollo_client_thread_pool_active_task_count | thread_pool_name | threadPoolInfo.getActiveTaskCount() | +| apollo_client_thread_pool_core_pool_size | thread_pool_name | threadPoolInfo.getCorePoolSize() | +| apollo_client_thread_pool_queue_size | thread_pool_name | threadPoolInfo.getQueueSize() | + +**Exception Metrics** + +Metric corresponding API: ApolloClientExceptionMonitorApi + +| Metric Name | Tag | +| ----------------------------------- | ----------------------------------------------------- | +| apollo_client_exception_num_total | exceptionMonitorApi.getExceptionCountFromStartup() | + ## 3.2 Spring integration approach ### 3.2.1 Configuration @@ -1372,4 +1476,346 @@ 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 . \ 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 . + + +## 7.2 Exporting Metrics to Prometheus +> Applicable to version 2.4.0 and above + +Metrics can be exported to Prometheus, or different implementations can be written based on SPI to integrate with various monitoring systems. + +Import the client plugin +```xml + + com.ctrip.framework.apollo + apollo-plugin-client-prometheus + 2.4.0 + +``` +Adjust the configuration +```properties +apollo.client.monitor.enabled=true +apollo.client.monitor.external.type=prometheus +``` +You can obtain the ExporterData via ConfigMonitor (the format depends on the monitoring system you configure, here it supports Prometheus format). + +Since Prometheus retrieves metrics via pulling, users need to expose the endpoint by themselves and implement a controller like the one below. + +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 the endpoint, and by printing the request logs, you will see information in a format similar to the following. + +``` +# 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 +``` + +At the same time, you can also view the following information on the Prometheus console: + +![Prometheus console showing Apollo client metrics](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-prometheus.png) + +## 7.3 Exporting Metrics to Custom Monitoring Systems +> Applicable to version 2.4.0 and above + +Users need to implement a MetricsExporter by extending `AbstractApolloClientMetricsExporter` and implement the following methods: +- `doInit` (Initialization method) +- `isSupport` (Method to check if the external-type configuration is supported) +- `registerOrUpdateCounterSample` (Method to register or update Counter metrics) +- `registerOrUpdateGaugeSample` (Method to register or update Gauge metrics) +- `response` (Method to export the required metric data) + +Additionally, you need to configure the corresponding SPI files. + +MetricsExporter Loading Flowchart: +![Exporter load by apollo client](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-exporter-load.jpg) + +### 7.3.1 SkyWalking Example +By configuring: +```properties +apollo.client.monitor.enabled=true +#exporter内定义 +apollo.client.monitor.external.type=skywalking +``` + +Create a SkyWalkingMetricsExporter class, which extends AbstractApolloClientMetricsExporter. + +The basic code after inheritance is as follows: +Note: This is just an example, do not use it directly in production. Implement it according to your company's specific situation. + +```java +public class SkyWalkingMetricsExporter extends AbstractApolloClientMetricsExporter { + + private static final String SKYWALKING = "skywalking"; + protected SkywalkingMeterRegistry registry; + // When designing, users should consider if the data structure for storing metrics consumes too much memory. + protected Map counterMap; + private Map gaugeMap; + private Map> gaugeValues; + + @Override + public void doInit() { + registry = new SkywalkingMeterRegistry(); + counterMap = new ConcurrentHashMap<>(); + gaugeValues = new ConcurrentHashMap<>(); + gaugeMap = new ConcurrentHashMap<>(); + } + + @Override + public boolean isSupport(String form) { + return SKYWALKING.equals(form); + } + + @Override + public void registerOrUpdateCounterSample(String name, Map tags, double incrValue) { + String key = name + tags.toString(); + Counter counter = counterMap.get(key); + + if (counter == null) { + counter = createCounter(name, tags); + counterMap.put(key, counter); + } + + counter.increment(incrValue); + } + + private Counter createCounter(String name, Map tags) { + return Counter.builder(name) + .tags(tags.entrySet().stream() + .map(entry -> Tag.of(entry.getKey(), entry.getValue())) + .collect(Collectors.toList())) + .register(registry); + } + + @Override + public void registerOrUpdateGaugeSample(String name, Map tags, double value) { + String key = name + tags.toString(); + Gauge gauge = gaugeMap.get(key); + if (gauge == null) { + createGauge(name, tags, value); + } else { + gaugeValues.get(key).set(value); + } + } + + public void createGauge(String name, Map tags, double value) { + String key = name + tags.toString(); + AtomicReference valueHolder = gaugeValues.computeIfAbsent(key, k -> new AtomicReference<>(value)); + gaugeMap.computeIfAbsent(key, k -> Gauge.builder(name, valueHolder::get) + .tags(tags.entrySet().stream() + .map(entry -> Tag.of(entry.getKey(), entry.getValue())) + .collect(Collectors.toList())) + .register(registry)); + } + + @Override + public String response() { + // No need to implement in SkyWalking push mode + return "This method does not need to be implemented in SkyWalking's push mode"; + } +} + +``` + +The doInit method is for users to extend during initialization. It will be called within the init method in AbstractApolloClientMetricsExporter. + +```java +@Override +public void init(List collectors, long collectPeriod) { + // code + doInit(); + // code +} +``` + +Import Micrometer: +```xml + + org.apache.skywalking + apm-toolkit-micrometer-1.10 + +``` +Initialize the SkywalkingMeterRegistry according to Micrometer's mechanism, +and use some maps to store metric data. + +```java +private static final String SKYWALKING = "skywalking"; +private SkywalkingMeterRegistry registry; +// When designing, users should consider if the data structure for storing metrics consumes too much memory. +private Map counterMap; +private Map gaugeMap; +private Map> gaugeValues; + +@Override +public void doInit() { + registry = new SkywalkingMeterRegistry(); + counterMap = new ConcurrentHashMap<>(); + gaugeValues = new ConcurrentHashMap<>(); + gaugeMap = new ConcurrentHashMap<>(); +} + +``` + +The isSupport method will be called when DefaultApolloClientMetricsExporterFactory reads the MetricsExporter via SPI, to check if the correct exporter is enabled when there are multiple SPI implementations. + +For example, when configuring and enabling SkyWalking, and you set the apollo.client.monitor.external.type configuration value as skyWalking, the method will be implemented like this: +```java +@Override +public boolean isSupport(String form) { + return SKYWALKING.equals(form); +} +``` + +The registerOrUpdateCounterSample and registerOrUpdateGaugeSample methods are used to register Counter and Gauge type metrics. You just need to register and update the data as per the parameters passed in. +```java +@Override +public void registerOrUpdateCounterSample(String name, Map tags, double incrValue) { + String key = name + tags.toString(); + Counter counter = counterMap.get(key); + + if (counter == null) { + counter = createCounter(name, tags); + counterMap.put(key, counter); + } + + counter.increment(incrValue); +} + +private Counter createCounter(String name, Map tags) { + return Counter.builder(name) + .tags(tags.entrySet().stream() + .map(entry -> Tag.of(entry.getKey(), entry.getValue())) + .collect(Collectors.toList())) + .register(registry); +} + +@Override +public void registerOrUpdateGaugeSample(String name, Map tags, double value) { + String key = name + tags.toString(); + Gauge gauge = gaugeMap.get(key); + + if (gauge == null) { + createGauge(name, tags, value); + } else { + gaugeValues.get(key).set(value); + } +} + +public void createGauge(String name, Map tags, double value) { + String key = name + tags.toString(); + AtomicReference valueHolder = gaugeValues.computeIfAbsent(key, k -> new AtomicReference<>(value)); + + gaugeMap.computeIfAbsent(key, k -> Gauge.builder(name, valueHolder::get) + .tags(tags.entrySet().stream() + .map(entry -> Tag.of(entry.getKey(), entry.getValue())) + .collect(Collectors.toList())) + .register(registry)); +} +``` + +The response method is for monitoring systems with pull-based metrics retrieval, like Prometheus. However, since SkyWalking uses a push mode, this method does not need to be implemented. Just configure SkyWalking for your use case. + +```java +@Override +public String response() { + // No need to implement in SkyWalking's push mode + return "This method does not need to be implemented in SkyWalking's push mode"; +} + +``` + +Finally, in the project directory under resources/META-INF/services, +create the corresponding SPI file to tell the framework to load this class. The file name should be com.ctrip.framework.apollo.monitor.internal.exporter.ApolloClientMetricsExporter. +```text +your.package.SkyWalkingMetricsExporter +``` +At this point, the client metrics data has been integrated into SkyWalking. + +### 7.3.2 Prometheus Example + +[PrometheusApolloClientMetricsExporter.java](https://github.com/apolloconfig/apollo-java/blob/main/apollo-plugin/apollo-plugin-client-prometheus/src/main/java/com/ctrip/framework/apollo/monitor/internal/exporter/impl/PrometheusApolloClientMetricsExporter.java) diff --git a/docs/zh/client/java-sdk-user-guide.md b/docs/zh/client/java-sdk-user-guide.md index bda435fa2b8..54516313b0c 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -1548,11 +1548,12 @@ apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfig" > 适用于2.4.0及以上版本 用户需要自行编写MetricsExporter, 继承AbstractApolloClientMetricsExporter, 实现里面的 -doInit (初始化方法), -isSupport (external-type配置调用方法), -registerOrUpdateCounterSample (注册更新Counter指标方法), -registerOrUpdateGaugeSample (注册更新Gauge指标方法), -response (导出所需类型指标数据方法) +- `doInit` (初始化方法) +- `isSupport` (external-type配置调用方法) +- `registerOrUpdateCounterSample` (注册更新Counter指标方法) +- `registerOrUpdateGaugeSample` (注册更新Gauge指标方法) +- `response` (导出所需类型指标数据方法) + 并配置相关SPI文件 MetricsExporter加载流程图 @@ -1561,13 +1562,12 @@ MetricsExporter加载流程图 ### 7.3.1 SkyWalking案例 -通过配置 +通过配置开启 ```properties apollo.client.monitor.enabled=true #exporter内定义 apollo.client.monitor.external.type=skywalking ``` -开启 创建SkyWalkingMetricsExporter类,继承AbstractApolloClientMetricsExporter From b11328b2d52b2af44e089bdafdcfb0133461db54 Mon Sep 17 00:00:00 2001 From: liu Date: Sat, 28 Dec 2024 01:15:12 +0800 Subject: [PATCH 11/12] fix(): conflict --- docs/en/client/java-sdk-user-guide.md | 8 ++++---- docs/zh/client/java-sdk-user-guide.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/en/client/java-sdk-user-guide.md b/docs/en/client/java-sdk-user-guide.md index fcaafe84afa..5dfe0854144 100644 --- a/docs/en/client/java-sdk-user-guide.md +++ b/docs/en/client/java-sdk-user-guide.md @@ -637,12 +637,12 @@ ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML String content = configFile.getContent(); ``` -### 3.1.5 Retrieve Client Monitoring Metrics +### 3.1.6 Retrieve Client Monitoring Metrics > Applicable to version 2.4.0 and above Apollo Client significantly enhanced observability in version 2.4.0, providing the ConfigMonitor API as well as metric export options via JMX and Prometheus. For configuration details, see [1.2.4.9 Enable Client Monitoring](#_1249-开启客户端监控). -#### 3.1.5.1 Retrieve Monitoring Data via ConfigMonitor +#### 3.1.6.1 Retrieve Monitoring Data via ConfigMonitor ```java ConfigMonitor configMonitor = ConfigService.getConfigMonitor(); @@ -661,7 +661,7 @@ ApolloThreadPoolInfo remoteConfigRepositoryThreadPoolInfo = threadPoolMonitorApi ``` -#### 3.1.5.2 Expose Status Information via JMX +#### 3.1.6.2 Expose Status Information via JMX Enable the relevant configuration: @@ -673,7 +673,7 @@ apollo.client.monitor.jmx.enabled = true After starting the application, use J-console or similar tools to view the metrics. Below is an example using J-console: ![showing Apollo client monitoring metrics in JMX](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-jmx.jpg) -#### 3.1.5.3 Client Export Metrics to External Monitoring Systems +#### 3.1.6.3 Client Export Metrics to External Monitoring Systems Users can customize the integration with monitoring systems such as Prometheus as needed. The client provides an SPI, see [7.2 MetricsExporter Extension](#_7.2_MetricsExporter-extension) for details. diff --git a/docs/zh/client/java-sdk-user-guide.md b/docs/zh/client/java-sdk-user-guide.md index 54516313b0c..3830a04cc7d 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -610,13 +610,13 @@ ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML String content = configFile.getContent(); ``` -### 3.1.5 获取客户端监控指标 +### 3.1.6 获取客户端监控指标 > 适用于2.4.0及以上版本 apollo-client在2.4.0版本里大幅增强了可观测性,提供了ConfigMonitor-API以及JMX,Prometheus的指标导出方式,相关启用配置详见 [1.2.4.9 开启客户端监控](#_1249-开启客户端监控) -#### 3.1.5.1 通过ConfigMonitor获取监控数据 +#### 3.1.6.1 通过ConfigMonitor获取监控数据 ```java ConfigMonitor configMonitor = ConfigService.getConfigMonitor(); @@ -634,7 +634,7 @@ apollo-client在2.4.0版本里大幅增强了可观测性,提供了ConfigMonit ApolloThreadPoolInfo remoteConfigRepositoryThreadPoolInfo = threadPoolMonitorApi.getRemoteConfigRepositoryThreadPoolInfo(); ``` -#### 3.1.5.2 以JMX形式暴露状态信息 +#### 3.1.6.2 以JMX形式暴露状态信息 启用相关配置 @@ -647,7 +647,7 @@ apollo.client.monitor.jmx.enabled = true ![showing Apollo client monitoring metrics in JMX](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-jmx.jpg) -#### 3.1.5.3 客户端导出指标上报到外部监控系统 +#### 3.1.6.3 客户端导出指标上报到外部监控系统 用户可以根据需求自定义接入Prometheus等监控系统,客户端提供了SPI,详见 [7.2 MetricsExporter扩展](#_7.2_MetricsExporter扩展) From 4538c5a6af083650944351e4cb5f0f680018d988 Mon Sep 17 00:00:00 2001 From: liu Date: Sat, 28 Dec 2024 01:44:34 +0800 Subject: [PATCH 12/12] fix(): conflict --- .../apollo-client-monitor-exporter-load.jpg | Bin 58592 -> 0 bytes docs/en/client/java-sdk-user-guide.md | 38 ++++++++++++++---- docs/zh/client/java-sdk-user-guide.md | 26 +++++++++++- 3 files changed, 54 insertions(+), 10 deletions(-) delete mode 100644 doc/images/apollo-client-monitor-exporter-load.jpg diff --git a/doc/images/apollo-client-monitor-exporter-load.jpg b/doc/images/apollo-client-monitor-exporter-load.jpg deleted file mode 100644 index 12883f22567035db3025b54a4952600c18df0466..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58592 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 NQ%zeHb@lF_{|9=V?j`^L diff --git a/docs/en/client/java-sdk-user-guide.md b/docs/en/client/java-sdk-user-guide.md index efce844d208..c3927329a25 100644 --- a/docs/en/client/java-sdk-user-guide.md +++ b/docs/en/client/java-sdk-user-guide.md @@ -417,7 +417,7 @@ The configuration methods, in descending order of priority, are #### 1.2.4.9 Enable Client Monitoring -> Applicable to version 2.4.0 and above +> For version 2.4.0 and above After enabling the following configurations, you can use `ConfigService.getConfigMonitor()` to retrieve client monitoring information and enable automatic reporting. @@ -425,7 +425,7 @@ After enabling the following configurations, you can use `ConfigService.getConfi # 1. Whether to enable the Monitor mechanism, i.e., whether ConfigMonitor is enabled. Default is false. apollo.client.monitor.enabled = true -# 2. Whether to expose Monitor data in JMX format. When enabled, you can view related information through tools like J-console. Default is false. +# 2. Whether to expose Monitor data by JMX. When enabled, you can view related information through tools like J-console. Default is false. apollo.client.monitor.jmx.enabled = true # 3. The maximum number of exception logs that Monitor can store. The default is 25, following the FIFO principle. @@ -649,9 +649,9 @@ String value = config.getProperty(someKey, someDefaultValue); ``` ### 3.1.6 Retrieve Client Monitoring Metrics -> Applicable to version 2.4.0 and above +> For version 2.4.0 and above -Apollo Client significantly enhanced observability in version 2.4.0, providing the ConfigMonitor API as well as metric export options via JMX and Prometheus. For configuration details, see [1.2.4.9 Enable Client Monitoring](#_1249-开启客户端监控). +Apollo Client significantly enhanced observability since version 2.4.0, providing the ConfigMonitor API as well as metric export options via JMX and Prometheus. For configuration details, see [1.2.4.9 Enable Client Monitoring](#_1249-enable-client-monitoring). #### 3.1.6.1 Retrieve Monitoring Data via ConfigMonitor @@ -686,7 +686,7 @@ After starting the application, use J-console or similar tools to view the metri ![showing Apollo client monitoring metrics in JMX](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-jmx.jpg) #### 3.1.6.3 Client Export Metrics to External Monitoring Systems -Users can customize the integration with monitoring systems such as Prometheus as needed. The client provides an SPI, see [7.2 MetricsExporter Extension](#_7.2_MetricsExporter-extension) for details. +Users can customize the integration with monitoring systems such as Prometheus as needed. The client provides an SPI, see [7.3 Exporting Metrics to Custom Monitoring Systems](#73-exporting-metrics-to-custom-monitoring-systems). for details. *Related Metrics Data Tables* @@ -1504,7 +1504,7 @@ The default service provider is `com.ctrip.framework.apollo.spi.RandomConfigServ ## 7.2 Exporting Metrics to Prometheus -> Applicable to version 2.4.0 and above +> For 2.4.0 and above Metrics can be exported to Prometheus, or different implementations can be written based on SPI to integrate with various monitoring systems. @@ -1637,13 +1637,35 @@ Users need to implement a MetricsExporter by extending `AbstractApolloClientMetr Additionally, you need to configure the corresponding SPI files. MetricsExporter Loading Flowchart: -![Exporter load by apollo client](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-exporter-load.jpg) +```mermaid +sequenceDiagram + participant Factory as DefaultMetricsExporterFactory + participant Exporter as MetricsExporter + participant SPI as SPI Loader + + %% Step 1: Factory loads all Exporters using SPI + Factory->>SPI: loadAllOrdered(MetricsExporter) + SPI-->>Factory: List + + %% Step 2: Factory checks for supported Exporter + Factory->>Exporter: isSupport(externalSystemType) + Exporter-->>Factory: true / false + + alt Exporter Found + %% Step 3: Factory initializes the Exporter + Factory->>Exporter: init(listeners, exportPeriod) + Factory-->>Client: Exporter Instance + else No Exporter Found + %% Step 4: Factory returns null + Factory-->>Client: null + end +``` ### 7.3.1 SkyWalking Example By configuring: ```properties apollo.client.monitor.enabled=true -#exporter内定义 +# Defined within the exporter apollo.client.monitor.external.type=skywalking ``` diff --git a/docs/zh/client/java-sdk-user-guide.md b/docs/zh/client/java-sdk-user-guide.md index 55ea441ff57..9832b9f5eb6 100644 --- a/docs/zh/client/java-sdk-user-guide.md +++ b/docs/zh/client/java-sdk-user-guide.md @@ -660,7 +660,7 @@ apollo.client.monitor.jmx.enabled = true #### 3.1.6.3 客户端导出指标上报到外部监控系统 -用户可以根据需求自定义接入Prometheus等监控系统,客户端提供了SPI,详见 [7.2 MetricsExporter扩展](#_7.2_MetricsExporter扩展) +用户可以根据需求自定义接入Prometheus等监控系统,客户端提供了SPI,详见 [7.3 指标输出到自定义监控系统](#73-指标输出到自定义监控系统)。 *相关指标数据表格* @@ -1580,7 +1580,29 @@ apollo_client_thread_pool_completed_task_count{thread_pool_name="AbstractConfig" 并配置相关SPI文件 MetricsExporter加载流程图 -![Exporter load by apollo client](https://cdn.jsdelivr.net/gh/apolloconfig/apollo@master/doc/images/apollo-client-monitor-exporter-load.jpg) +```mermaid +sequenceDiagram + participant Factory as DefaultMetricsExporterFactory + participant Exporter as MetricsExporter + participant SPI as SPI Loader + + %% 步骤 1: Factory 从 SPI 加载所有 Exporters + Factory->>SPI: loadAllOrdered(MetricsExporter) + SPI-->>Factory: List + + %% 步骤 2: Factory 查找支持的 Exporter + Factory->>Exporter: isSupport(externalSystemType) + Exporter-->>Factory: true / false + + alt Exporter Found + %% 步骤 3: Factory 初始化 Exporter + Factory->>Exporter: init(listeners, exportPeriod) + Factory-->>Client: Exporter Instance + else No Exporter Found + %% 步骤 4: Factory 返回 null + Factory-->>Client: null + end +```