Commit cecb374d91 for asterisk.org

commit cecb374d91a6ce1490214c6758d55172ab7dea35
Author: whitetreebug <houxirens@qq.com>
Date:   Fri Aug 28 23:40:04 2026 +0800

    res_prometheus: add toggle config for metrics

    In high‑volume call scenarios, Prometheus exports a large number of channels‑related and bridges-related metrics.Not all users require channels_state, channels_duration and bridges_channels.Add conf options to enable or disable channel_details(covering channels_state, channels_duration) and bridge_details(covering bridges_channels).

    UserNote: Add new config option 'channels_detail_metrics_enabled' to disable export of 'asterisk_channels_state' and 'asterisk_channels_duration_seconds' metrics,It defaults to 'yes' to preserve existing behavior

    Add new config option 'bridges_detail_metrics_enabled' to disable export of 'asterisk_bridges_channels_count' metric, It defaults to 'yes' to preserve existing behavior

    Explicitly enable bridges_detail_metrics_enabled for the bridge_to_string unit‑test.

diff --git a/configs/samples/prometheus.conf.sample b/configs/samples/prometheus.conf.sample
index ee4a1965ee..d9eb9ba17a 100644
--- a/configs/samples/prometheus.conf.sample
+++ b/configs/samples/prometheus.conf.sample
@@ -43,6 +43,15 @@ core_metrics_enabled = yes        ; Enable/disable core metrics. Core metrics
                                   ; version of Asterisk, uptime, last reload
                                   ; time, and the overall time it takes to
                                   ; scrape metrics. Default is "yes"
+channels_detail_metrics_enabled = yes
+                                  ; Enable/disable channels_detail. This controls
+                                  ; export of asterisk_channels_state and
+                                  ; asterisk_channels_duration_seconds
+                                  ; Default is "yes"
+bridges_detail_metrics_enabled = yes
+                                  ; Enable/disable bridges_detail. This controls
+                                  ; export of asterisk_bridges_channels_count
+                                  ; Default is "yes"
 uri = metrics                     ; The HTTP route to expose metrics on.
                                   ; Default is "metrics".

diff --git a/include/asterisk/res_prometheus.h b/include/asterisk/res_prometheus.h
index 2c64437067..d9c2ab57fa 100644
--- a/include/asterisk/res_prometheus.h
+++ b/include/asterisk/res_prometheus.h
@@ -70,6 +70,10 @@ struct prometheus_general_config {
 	unsigned int enabled;
 	/*! \brief Whether or not core metrics are enabled */
 	unsigned int core_metrics_enabled;
+	/*! \brief Whether or not channel detail metrics are enabled */
+	unsigned int channels_detail_metrics_enabled;
+	/*! \brief Whether or not bridge detail metrics are enabled */
+	unsigned int bridges_detail_metrics_enabled;
 	AST_DECLARE_STRING_FIELDS(
 		/*! \brief The HTTP URI we register ourselves to */
 		AST_STRING_FIELD(uri);
diff --git a/res/prometheus/bridges.c b/res/prometheus/bridges.c
index a1f8a24a3b..1d1a403b4d 100644
--- a/res/prometheus/bridges.c
+++ b/res/prometheus/bridges.c
@@ -77,6 +77,7 @@ struct bridge_metric_defs {
  */
 static void bridges_scrape_cb(struct ast_str **response)
 {
+	RAII_VAR(struct prometheus_general_config *, config, prometheus_general_config_get(), ao2_cleanup);
 	struct ao2_container *bridge_cache;
 	struct ao2_container *bridges;
 	struct ao2_iterator it_bridges;
@@ -117,6 +118,11 @@ static void bridges_scrape_cb(struct ast_str **response)
 		return;
 	}

+	if (!config || !config->bridges_detail_metrics_enabled) {
+		ao2_ref(bridges, -1);
+		return;
+	}
+
 	metrics = ast_calloc(ARRAY_LEN(bridge_metric_defs) * num_bridges, sizeof(*metrics));
 	if (!metrics) {
 		ao2_ref(bridges, -1);
diff --git a/res/prometheus/channels.c b/res/prometheus/channels.c
index dae47ebdb9..6b360ee1ae 100644
--- a/res/prometheus/channels.c
+++ b/res/prometheus/channels.c
@@ -129,6 +129,7 @@ static struct prometheus_metric global_channel_metrics[] = {
  */
 static void channels_scrape_cb(struct ast_str **response)
 {
+	RAII_VAR(struct prometheus_general_config *, config, prometheus_general_config_get(), ao2_cleanup);
 	struct ao2_container *channel_cache;
 	struct ao2_container *channels;
 	struct ao2_iterator it_chans;
@@ -176,6 +177,11 @@ static void channels_scrape_cb(struct ast_str **response)
 		return;
 	}

+	if (!config || !config->channels_detail_metrics_enabled) {
+		ao2_ref(channels, -1);
+		return;
+	}
+
 	/* Channel dependent values */
 	channel_metrics = ast_calloc(ARRAY_LEN(channel_metric_defs) * num_channels, sizeof(*channel_metrics));
 	if (!channel_metrics) {
diff --git a/res/res_prometheus.c b/res/res_prometheus.c
index c72ea794e9..24fc3695d8 100644
--- a/res/res_prometheus.c
+++ b/res/res_prometheus.c
@@ -83,6 +83,44 @@
 						</enumlist>
 					</description>
 				</configOption>
+				<configOption name="channels_detail_metrics_enabled" default="yes">
+					<since>
+						<version>20.22.0</version>
+						<version>22.12.0</version>
+						<version>23.6.0</version>
+						<version>24.1.0</version>
+					</since>
+					<synopsis>Enable or disable asterisk_channels_state and asterisk_channels_duration_seconds metrics.</synopsis>
+					<description>
+						<para>
+						channels_detail_metrics_enabled defaults to yes to maintain backward‑compatibility.
+						Set to no to disable the high‑cardinality channel detail metrics.
+						</para>
+						<enumlist>
+							<enum name="no" />
+							<enum name="yes" />
+						</enumlist>
+					</description>
+				</configOption>
+				<configOption name="bridges_detail_metrics_enabled" default="yes">
+					<since>
+						<version>20.22.0</version>
+						<version>22.12.0</version>
+						<version>23.6.0</version>
+						<version>24.1.0</version>
+					</since>
+					<synopsis>Enable or disable asterisk_bridges_channels_count metric.</synopsis>
+					<description>
+						<para>
+						bridges_detail_metrics_enabled defaults to yes to maintain backward‑compatibility.
+						Set to no to disable the high‑cardinality bridge detail metrics.
+						</para>
+						<enumlist>
+							<enum name="no" />
+							<enum name="yes" />
+						</enumlist>
+					</description>
+				</configOption>
 				<configOption name="uri" default="metrics">
 					<since>
 						<version>17.0.0</version>
@@ -991,6 +1029,8 @@ static int load_module(void)
 	}
 	aco_option_register(&cfg_info, "enabled", ACO_EXACT, global_options, "no", OPT_BOOL_T, 1, FLDSET(struct prometheus_general_config, enabled));
 	aco_option_register(&cfg_info, "core_metrics_enabled", ACO_EXACT, global_options, "yes", OPT_BOOL_T, 1, FLDSET(struct prometheus_general_config, core_metrics_enabled));
+	aco_option_register(&cfg_info, "channels_detail_metrics_enabled", ACO_EXACT, global_options, "yes", OPT_BOOL_T, 1, FLDSET(struct prometheus_general_config, channels_detail_metrics_enabled));
+	aco_option_register(&cfg_info, "bridges_detail_metrics_enabled", ACO_EXACT, global_options, "yes", OPT_BOOL_T, 1, FLDSET(struct prometheus_general_config, bridges_detail_metrics_enabled));
 	aco_option_register(&cfg_info, "uri", ACO_EXACT, global_options, "", OPT_STRINGFIELD_T, 1, STRFLDSET(struct prometheus_general_config, uri));
 	aco_option_register(&cfg_info, "auth_username", ACO_EXACT, global_options, "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct prometheus_general_config, auth_username));
 	aco_option_register(&cfg_info, "auth_password", ACO_EXACT, global_options, "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct prometheus_general_config, auth_password));
diff --git a/tests/test_res_prometheus.c b/tests/test_res_prometheus.c
index e613bb2781..bfc3c22d38 100644
--- a/tests/test_res_prometheus.c
+++ b/tests/test_res_prometheus.c
@@ -727,6 +727,7 @@ AST_TEST_DEFINE(bridge_to_string)
 	RAII_VAR(struct ast_bridge *, bridge1, NULL, safe_bridge_destroy);
 	RAII_VAR(struct ast_bridge *, bridge2, NULL, safe_bridge_destroy);
 	RAII_VAR(struct ast_bridge *, bridge3, NULL, safe_bridge_destroy);
+	struct prometheus_general_config *config;
 	struct ast_str *response;

 	switch (cmd) {
@@ -742,6 +743,14 @@ AST_TEST_DEFINE(bridge_to_string)
 		break;
 	}

+	config = config_alloc();
+	if (!config) {
+		return AST_TEST_NOT_RUN;
+	}
+	config->bridges_detail_metrics_enabled = 1;
+	prometheus_general_config_set(config);
+	ao2_ref(config, -1);
+
 	bridge1 = ast_bridge_basic_new();
 	ast_test_validate(test, bridge1 != NULL);