From 9bdef062d41b2c01fc0a3b07eb83b09c2a3457b4 Mon Sep 17 00:00:00 2001 From: "ci.datadog-api-spec" Date: Mon, 20 Jul 2026 17:07:24 +0000 Subject: [PATCH] Regenerate client from commit ba40d2e of spec repo --- .generator/schemas/v2/openapi.yaml | 23 ++++- ...etrics_CreateTagIndexingRule_2435129406.rs | 48 +++++++++ ...etrics_UpdateTagIndexingRule_4127399471.rs | 54 +++++++++++ .../model_tag_indexing_rule_dynamic_tags.rs | 46 ++++++++- .../model_tag_indexing_rule_options_data.rs | 10 +- ...age-fields-returns-Created-response.frozen | 1 + ...usage-fields-returns-Created-response.json | 63 ++++++++++++ ...-false-returns-Bad-Request-response.frozen | 1 + ...de-false-returns-Bad-Request-response.json | 39 ++++++++ ...aximum-returns-Bad-Request-response.frozen | 1 + ...-maximum-returns-Bad-Request-response.json | 39 ++++++++ ...-false-returns-Bad-Request-response.frozen | 1 + ...de-false-returns-Bad-Request-response.json | 39 ++++++++ ...ag-usage-fields-returns-OK-response.frozen | 1 + ...-tag-usage-fields-returns-OK-response.json | 97 +++++++++++++++++++ tests/scenarios/features/v2/given.json | 12 +++ tests/scenarios/features/v2/metrics.feature | 49 +++++++++- 17 files changed, 520 insertions(+), 4 deletions(-) create mode 100644 examples/v2_metrics_CreateTagIndexingRule_2435129406.rs create mode 100644 examples/v2_metrics_UpdateTagIndexingRule_4127399471.rs create mode 100644 tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.frozen create mode 100644 tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.json create mode 100644 tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.frozen create mode 100644 tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.json create mode 100644 tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.frozen create mode 100644 tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.json create mode 100644 tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.frozen create mode 100644 tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.json create mode 100644 tests/scenarios/cassettes/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.frozen create mode 100644 tests/scenarios/cassettes/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.json diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index ed984a56d0..61320cadad 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -104076,8 +104076,29 @@ components: $ref: "#/components/schemas/TagIndexingRuleType" type: object TagIndexingRuleDynamicTags: - description: Configuration for including dynamically queried tags. + description: |- + Options for dynamic tag indexing applied per metric, such as tags filtered by query usage. + + Before a tag key is dropped by this rule, two grace period conditions must be met: + + 1. The metric must be submitted for at least as long as the selected window. + 2. A tag key must have been submitted for at least 15 days. + + Any metric or tag key that does not meet these conditions are excluded from this + indexing rule. The `exclude_not_*` fields require `exclude_tags_mode` to be set to `true`. properties: + exclude_not_queried_window_seconds: + description: >- + Tags that have not been queried within this window are excluded from indexing. Maximum of `7776000` (90 days). + example: 3600 + format: int64 + maximum: 7776000 + type: integer + exclude_not_used_in_assets: + description: >- + Tags not used in any dashboards, monitors, notebooks, or SLOs are excluded from indexing. + example: false + type: boolean queried_tags_window_seconds: description: Window in seconds for evaluating queried tags. example: 3600 diff --git a/examples/v2_metrics_CreateTagIndexingRule_2435129406.rs b/examples/v2_metrics_CreateTagIndexingRule_2435129406.rs new file mode 100644 index 0000000000..dba8e54b6c --- /dev/null +++ b/examples/v2_metrics_CreateTagIndexingRule_2435129406.rs @@ -0,0 +1,48 @@ +// Create a tag indexing rule with exclude-mode tag usage fields returns "Created" +// response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_metrics::MetricsAPI; +use datadog_api_client::datadogV2::model::TagIndexingRuleCreateAttributes; +use datadog_api_client::datadogV2::model::TagIndexingRuleCreateData; +use datadog_api_client::datadogV2::model::TagIndexingRuleCreateRequest; +use datadog_api_client::datadogV2::model::TagIndexingRuleDynamicTags; +use datadog_api_client::datadogV2::model::TagIndexingRuleOptions; +use datadog_api_client::datadogV2::model::TagIndexingRuleOptionsData; +use datadog_api_client::datadogV2::model::TagIndexingRuleType; + +#[tokio::main] +async fn main() { + let body = TagIndexingRuleCreateRequest::new(TagIndexingRuleCreateData::new( + TagIndexingRuleCreateAttributes::new( + vec!["dd.test.*".to_string()], + "my-indexing-rule".to_string(), + ) + .exclude_tags_mode(true) + .ignored_metric_name_matches(vec![]) + .options( + TagIndexingRuleOptions::new() + .data( + TagIndexingRuleOptionsData::new() + .dynamic_tags( + TagIndexingRuleDynamicTags::new() + .exclude_not_queried_window_seconds(3600) + .exclude_not_used_in_assets(true), + ) + .manage_preexisting_metrics(true) + .override_previous_rules(false), + ) + .version(1), + ) + .tags(vec!["env".to_string(), "service".to_string()]), + TagIndexingRuleType::TAG_INDEXING_RULES, + )); + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.CreateTagIndexingRule", true); + let api = MetricsAPI::with_config(configuration); + let resp = api.create_tag_indexing_rule(body).await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/examples/v2_metrics_UpdateTagIndexingRule_4127399471.rs b/examples/v2_metrics_UpdateTagIndexingRule_4127399471.rs new file mode 100644 index 0000000000..3e02fb1be2 --- /dev/null +++ b/examples/v2_metrics_UpdateTagIndexingRule_4127399471.rs @@ -0,0 +1,54 @@ +// Update a tag indexing rule with exclude-mode tag usage fields returns "OK" +// response +use datadog_api_client::datadog; +use datadog_api_client::datadogV2::api_metrics::MetricsAPI; +use datadog_api_client::datadogV2::model::TagIndexingRuleDynamicTags; +use datadog_api_client::datadogV2::model::TagIndexingRuleOptions; +use datadog_api_client::datadogV2::model::TagIndexingRuleOptionsData; +use datadog_api_client::datadogV2::model::TagIndexingRuleType; +use datadog_api_client::datadogV2::model::TagIndexingRuleUpdateAttributes; +use datadog_api_client::datadogV2::model::TagIndexingRuleUpdateData; +use datadog_api_client::datadogV2::model::TagIndexingRuleUpdateRequest; + +#[tokio::main] +async fn main() { + // there is a valid "tag_indexing_rule_exclude_mode" in the system + let tag_indexing_rule_exclude_mode_data_id = + std::env::var("TAG_INDEXING_RULE_EXCLUDE_MODE_DATA_ID").unwrap(); + let body = TagIndexingRuleUpdateRequest::new( + TagIndexingRuleUpdateData::new(TagIndexingRuleType::TAG_INDEXING_RULES).attributes( + TagIndexingRuleUpdateAttributes::new() + .exclude_tags_mode(true) + .ignored_metric_name_matches(vec![]) + .metric_name_matches(vec!["dd.test.*".to_string()]) + .name("my-indexing-rule".to_string()) + .options( + TagIndexingRuleOptions::new() + .data( + TagIndexingRuleOptionsData::new() + .dynamic_tags( + TagIndexingRuleDynamicTags::new() + .exclude_not_queried_window_seconds(7200) + .exclude_not_used_in_assets(true), + ) + .manage_preexisting_metrics(true) + .override_previous_rules(false), + ) + .version(1), + ) + .rule_order(2) + .tags(vec!["env".to_string(), "service".to_string()]), + ), + ); + let mut configuration = datadog::Configuration::new(); + configuration.set_unstable_operation_enabled("v2.UpdateTagIndexingRule", true); + let api = MetricsAPI::with_config(configuration); + let resp = api + .update_tag_indexing_rule(tag_indexing_rule_exclude_mode_data_id.clone(), body) + .await; + if let Ok(value) = resp { + println!("{:#?}", value); + } else { + println!("{:#?}", resp.unwrap_err()); + } +} diff --git a/src/datadogV2/model/model_tag_indexing_rule_dynamic_tags.rs b/src/datadogV2/model/model_tag_indexing_rule_dynamic_tags.rs index 571e040188..4bf3f093bf 100644 --- a/src/datadogV2/model/model_tag_indexing_rule_dynamic_tags.rs +++ b/src/datadogV2/model/model_tag_indexing_rule_dynamic_tags.rs @@ -6,11 +6,25 @@ use serde::{Deserialize, Deserializer, Serialize}; use serde_with::skip_serializing_none; use std::fmt::{self, Formatter}; -/// Configuration for including dynamically queried tags. +/// Options for dynamic tag indexing applied per metric, such as tags filtered by query usage. +/// +/// Before a tag key is dropped by this rule, two grace period conditions must be met: +/// +/// 1. The metric must be submitted for at least as long as the selected window. +/// 2. A tag key must have been submitted for at least 15 days. +/// +/// Any metric or tag key that does not meet these conditions are excluded from this +/// indexing rule. The `exclude_not_*` fields require `exclude_tags_mode` to be set to `true`. #[non_exhaustive] #[skip_serializing_none] #[derive(Clone, Debug, PartialEq, Serialize)] pub struct TagIndexingRuleDynamicTags { + /// Tags that have not been queried within this window are excluded from indexing. Maximum of `7776000` (90 days). + #[serde(rename = "exclude_not_queried_window_seconds")] + pub exclude_not_queried_window_seconds: Option, + /// Tags not used in any dashboards, monitors, notebooks, or SLOs are excluded from indexing. + #[serde(rename = "exclude_not_used_in_assets")] + pub exclude_not_used_in_assets: Option, /// Window in seconds for evaluating queried tags. #[serde(rename = "queried_tags_window_seconds")] pub queried_tags_window_seconds: Option, @@ -27,6 +41,8 @@ pub struct TagIndexingRuleDynamicTags { impl TagIndexingRuleDynamicTags { pub fn new() -> TagIndexingRuleDynamicTags { TagIndexingRuleDynamicTags { + exclude_not_queried_window_seconds: None, + exclude_not_used_in_assets: None, queried_tags_window_seconds: None, related_asset_tags: None, additional_properties: std::collections::BTreeMap::new(), @@ -34,6 +50,16 @@ impl TagIndexingRuleDynamicTags { } } + pub fn exclude_not_queried_window_seconds(mut self, value: i64) -> Self { + self.exclude_not_queried_window_seconds = Some(value); + self + } + + pub fn exclude_not_used_in_assets(mut self, value: bool) -> Self { + self.exclude_not_used_in_assets = Some(value); + self + } + pub fn queried_tags_window_seconds(mut self, value: i64) -> Self { self.queried_tags_window_seconds = Some(value); self @@ -76,6 +102,8 @@ impl<'de> Deserialize<'de> for TagIndexingRuleDynamicTags { where M: MapAccess<'a>, { + let mut exclude_not_queried_window_seconds: Option = None; + let mut exclude_not_used_in_assets: Option = None; let mut queried_tags_window_seconds: Option = None; let mut related_asset_tags: Option = None; let mut additional_properties: std::collections::BTreeMap< @@ -86,6 +114,20 @@ impl<'de> Deserialize<'de> for TagIndexingRuleDynamicTags { while let Some((k, v)) = map.next_entry::()? { match k.as_str() { + "exclude_not_queried_window_seconds" => { + if v.is_null() { + continue; + } + exclude_not_queried_window_seconds = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } + "exclude_not_used_in_assets" => { + if v.is_null() { + continue; + } + exclude_not_used_in_assets = + Some(serde_json::from_value(v).map_err(M::Error::custom)?); + } "queried_tags_window_seconds" => { if v.is_null() { continue; @@ -109,6 +151,8 @@ impl<'de> Deserialize<'de> for TagIndexingRuleDynamicTags { } let content = TagIndexingRuleDynamicTags { + exclude_not_queried_window_seconds, + exclude_not_used_in_assets, queried_tags_window_seconds, related_asset_tags, additional_properties, diff --git a/src/datadogV2/model/model_tag_indexing_rule_options_data.rs b/src/datadogV2/model/model_tag_indexing_rule_options_data.rs index 256699df86..fd20687fad 100644 --- a/src/datadogV2/model/model_tag_indexing_rule_options_data.rs +++ b/src/datadogV2/model/model_tag_indexing_rule_options_data.rs @@ -11,7 +11,15 @@ use std::fmt::{self, Formatter}; #[skip_serializing_none] #[derive(Clone, Debug, PartialEq, Serialize)] pub struct TagIndexingRuleOptionsData { - /// Configuration for including dynamically queried tags. + /// Options for dynamic tag indexing applied per metric, such as tags filtered by query usage. + /// + /// Before a tag key is dropped by this rule, two grace period conditions must be met: + /// + /// 1. The metric must be submitted for at least as long as the selected window. + /// 2. A tag key must have been submitted for at least 15 days. + /// + /// Any metric or tag key that does not meet these conditions are excluded from this + /// indexing rule. The `exclude_not_*` fields require `exclude_tags_mode` to be set to `true`. #[serde(rename = "dynamic_tags")] pub dynamic_tags: Option, /// When true, the rule applies to metrics that were ingested before the rule was created. diff --git a/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.frozen b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.frozen new file mode 100644 index 0000000000..0f10cd49f0 --- /dev/null +++ b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.frozen @@ -0,0 +1 @@ +2026-07-20T13:47:22.097Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.json b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.json new file mode 100644 index 0000000000..d4b5ae96c4 --- /dev/null +++ b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.json @@ -0,0 +1,63 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"exclude_tags_mode\":true,\"ignored_metric_name_matches\":[],\"metric_name_matches\":[\"dd.test.*\"],\"name\":\"my-indexing-rule\",\"options\":{\"data\":{\"dynamic_tags\":{\"exclude_not_queried_window_seconds\":3600,\"exclude_not_used_in_assets\":true},\"manage_preexisting_metrics\":true,\"override_previous_rules\":false},\"version\":1},\"tags\":[\"env\",\"service\"]},\"type\":\"tag_indexing_rules\"}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"50b7b68a-4580-4f9b-8c2c-8622446e68eb\",\"type\":\"tag_indexing_rules\",\"attributes\":{\"created_at\":\"2026-07-20T13:47:24.033083Z\",\"created_by_handle\":\"9919ec9b-ebc7-49ee-8dc8-03626e717cca\",\"exclude_tags_mode\":true,\"ignored_metric_name_matches\":[],\"metric_name_matches\":[\"dd.test.*\"],\"modified_at\":\"2026-07-20T13:47:24.033083Z\",\"modified_by_handle\":\"9919ec9b-ebc7-49ee-8dc8-03626e717cca\",\"name\":\"my-indexing-rule\",\"options\":{\"version\":1,\"data\":{\"override_previous_rules\":false,\"manage_preexisting_metrics\":true,\"dynamic_tags\":{\"exclude_not_queried_window_seconds\":3600,\"exclude_not_used_in_assets\":true}}},\"rule_order\":1,\"tags\":[\"env\",\"service\"]}}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 201, + "message": "Created" + } + }, + "recorded_at": "Mon, 20 Jul 2026 13:47:22 GMT" + }, + { + "request": { + "body": "", + "headers": { + "Accept": [ + "*/*" + ] + }, + "method": "delete", + "uri": "https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules/50b7b68a-4580-4f9b-8c2c-8622446e68eb" + }, + "response": { + "body": { + "string": "", + "encoding": null + }, + "headers": {}, + "status": { + "code": 204, + "message": "No Content" + } + }, + "recorded_at": "Mon, 20 Jul 2026 13:47:22 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.frozen b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.frozen new file mode 100644 index 0000000000..e653d57061 --- /dev/null +++ b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.frozen @@ -0,0 +1 @@ +2026-07-20T13:47:24.179Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.json b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.json new file mode 100644 index 0000000000..74b18ae779 --- /dev/null +++ b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.json @@ -0,0 +1,39 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"exclude_tags_mode\":false,\"ignored_metric_name_matches\":[],\"metric_name_matches\":[\"dd.test.*\"],\"name\":\"my-indexing-rule\",\"options\":{\"data\":{\"dynamic_tags\":{\"exclude_not_queried_window_seconds\":3600},\"manage_preexisting_metrics\":true,\"override_previous_rules\":false},\"version\":1},\"tags\":[\"env\",\"service\"]},\"type\":\"tag_indexing_rules\"}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules" + }, + "response": { + "body": { + "string": "{\"errors\":[\"Invalid request body: exclude_not_queried_window_seconds/exclude_not_used_in_assets cannot be set when exclude_tags_mode is false \u2014 \\\"by tag usage\\\" is Exclude-mode only\"]}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 400, + "message": "Bad Request" + } + }, + "recorded_at": "Mon, 20 Jul 2026 13:47:24 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.frozen b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.frozen new file mode 100644 index 0000000000..34477e0b53 --- /dev/null +++ b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.frozen @@ -0,0 +1 @@ +2026-07-20T13:47:24.273Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.json b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.json new file mode 100644 index 0000000000..78d11e685c --- /dev/null +++ b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.json @@ -0,0 +1,39 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"exclude_tags_mode\":true,\"ignored_metric_name_matches\":[],\"metric_name_matches\":[\"dd.test.*\"],\"name\":\"my-indexing-rule\",\"options\":{\"data\":{\"dynamic_tags\":{\"exclude_not_queried_window_seconds\":7776001},\"manage_preexisting_metrics\":true,\"override_previous_rules\":false},\"version\":1},\"tags\":[\"env\",\"service\"]},\"type\":\"tag_indexing_rules\"}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules" + }, + "response": { + "body": { + "string": "{\"errors\":[\"Invalid request body: dynamic_tags.exclude_not_queried_window_seconds cannot exceed 7776000 seconds (90 days)\"]}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 400, + "message": "Bad Request" + } + }, + "recorded_at": "Mon, 20 Jul 2026 13:47:24 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.frozen b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.frozen new file mode 100644 index 0000000000..bfa63b117d --- /dev/null +++ b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.frozen @@ -0,0 +1 @@ +2026-07-20T13:47:24.367Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.json b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.json new file mode 100644 index 0000000000..86c5639de1 --- /dev/null +++ b/tests/scenarios/cassettes/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.json @@ -0,0 +1,39 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"exclude_tags_mode\":false,\"ignored_metric_name_matches\":[],\"metric_name_matches\":[\"dd.test.*\"],\"name\":\"my-indexing-rule\",\"options\":{\"data\":{\"dynamic_tags\":{\"exclude_not_used_in_assets\":true},\"manage_preexisting_metrics\":true,\"override_previous_rules\":false},\"version\":1},\"tags\":[\"env\",\"service\"]},\"type\":\"tag_indexing_rules\"}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules" + }, + "response": { + "body": { + "string": "{\"errors\":[\"Invalid request body: exclude_not_queried_window_seconds/exclude_not_used_in_assets cannot be set when exclude_tags_mode is false \u2014 \\\"by tag usage\\\" is Exclude-mode only\"]}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 400, + "message": "Bad Request" + } + }, + "recorded_at": "Mon, 20 Jul 2026 13:47:24 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.frozen b/tests/scenarios/cassettes/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.frozen new file mode 100644 index 0000000000..41394dceed --- /dev/null +++ b/tests/scenarios/cassettes/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.frozen @@ -0,0 +1 @@ +2026-07-20T13:47:24.486Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.json b/tests/scenarios/cassettes/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.json new file mode 100644 index 0000000000..1dbf25a8a1 --- /dev/null +++ b/tests/scenarios/cassettes/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.json @@ -0,0 +1,97 @@ +{ + "http_interactions": [ + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"exclude_tags_mode\":true,\"metric_name_matches\":[\"dd.TestUpdateatagindexingrulewithexcludemodetagusagefieldsreturnsOKresponse1784555244.*\"],\"name\":\"TestUpdateatagindexingrulewithexcludemodetagusagefieldsreturnsOKresponse1784555244\",\"tags\":[\"env\",\"service\"]},\"type\":\"tag_indexing_rules\"}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "post", + "uri": "https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"e4a507ac-ee83-439b-bf65-72d162150e3c\",\"type\":\"tag_indexing_rules\",\"attributes\":{\"created_at\":\"2026-07-20T13:47:24.568418Z\",\"created_by_handle\":\"9919ec9b-ebc7-49ee-8dc8-03626e717cca\",\"exclude_tags_mode\":true,\"metric_name_matches\":[\"dd.TestUpdateatagindexingrulewithexcludemodetagusagefieldsreturnsOKresponse1784555244.*\"],\"modified_at\":\"2026-07-20T13:47:24.568418Z\",\"modified_by_handle\":\"9919ec9b-ebc7-49ee-8dc8-03626e717cca\",\"name\":\"TestUpdateatagindexingrulewithexcludemodetagusagefieldsreturnsOKresponse1784555244\",\"options\":{\"version\":1,\"data\":{\"override_previous_rules\":false,\"manage_preexisting_metrics\":true}},\"rule_order\":1,\"tags\":[\"env\",\"service\"]}}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 201, + "message": "Created" + } + }, + "recorded_at": "Mon, 20 Jul 2026 13:47:24 GMT" + }, + { + "request": { + "body": { + "string": "{\"data\":{\"attributes\":{\"exclude_tags_mode\":true,\"ignored_metric_name_matches\":[],\"metric_name_matches\":[\"dd.test.*\"],\"name\":\"my-indexing-rule\",\"options\":{\"data\":{\"dynamic_tags\":{\"exclude_not_queried_window_seconds\":7200,\"exclude_not_used_in_assets\":true},\"manage_preexisting_metrics\":true,\"override_previous_rules\":false},\"version\":1},\"rule_order\":2,\"tags\":[\"env\",\"service\"]},\"type\":\"tag_indexing_rules\"}}", + "encoding": null + }, + "headers": { + "Accept": [ + "application/json" + ], + "Content-Type": [ + "application/json" + ] + }, + "method": "put", + "uri": "https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules/e4a507ac-ee83-439b-bf65-72d162150e3c" + }, + "response": { + "body": { + "string": "{\"data\":{\"id\":\"e4a507ac-ee83-439b-bf65-72d162150e3c\",\"type\":\"tag_indexing_rules\",\"attributes\":{\"created_at\":\"2026-07-20T13:47:24.568418Z\",\"created_by_handle\":\"9919ec9b-ebc7-49ee-8dc8-03626e717cca\",\"exclude_tags_mode\":true,\"ignored_metric_name_matches\":[],\"metric_name_matches\":[\"dd.test.*\"],\"modified_at\":\"2026-07-20T13:47:24.708603Z\",\"modified_by_handle\":\"9919ec9b-ebc7-49ee-8dc8-03626e717cca\",\"name\":\"my-indexing-rule\",\"options\":{\"version\":1,\"data\":{\"override_previous_rules\":false,\"manage_preexisting_metrics\":true,\"dynamic_tags\":{\"exclude_not_queried_window_seconds\":7200,\"exclude_not_used_in_assets\":true}}},\"rule_order\":2,\"tags\":[\"env\",\"service\"]}}}", + "encoding": null + }, + "headers": { + "Content-Type": [ + "application/vnd.api+json" + ] + }, + "status": { + "code": 200, + "message": "OK" + } + }, + "recorded_at": "Mon, 20 Jul 2026 13:47:24 GMT" + }, + { + "request": { + "body": "", + "headers": { + "Accept": [ + "*/*" + ] + }, + "method": "delete", + "uri": "https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules/e4a507ac-ee83-439b-bf65-72d162150e3c" + }, + "response": { + "body": { + "string": "", + "encoding": null + }, + "headers": {}, + "status": { + "code": 204, + "message": "No Content" + } + }, + "recorded_at": "Mon, 20 Jul 2026 13:47:24 GMT" + } + ], + "recorded_with": "VCR 6.0.0" +} \ No newline at end of file diff --git a/tests/scenarios/features/v2/given.json b/tests/scenarios/features/v2/given.json index 0f9de6d48a..75fa924ff1 100644 --- a/tests/scenarios/features/v2/given.json +++ b/tests/scenarios/features/v2/given.json @@ -954,6 +954,18 @@ "tag": "Metrics", "operationId": "CreateTagIndexingRule" }, + { + "parameters": [ + { + "name": "body", + "value": "{\n \"data\": {\n \"type\": \"tag_indexing_rules\",\n \"attributes\": {\n \"name\": \"{{ unique_alnum }}\",\n \"exclude_tags_mode\": true,\n \"metric_name_matches\": [\"dd.{{ unique_alnum }}.*\"],\n \"tags\": [\"env\", \"service\"]\n }\n }\n}" + } + ], + "step": "there is a valid \"tag_indexing_rule_exclude_mode\" in the system", + "key": "tag_indexing_rule_exclude_mode", + "tag": "Metrics", + "operationId": "CreateTagIndexingRule" + }, { "parameters": [ { diff --git a/tests/scenarios/features/v2/metrics.feature b/tests/scenarios/features/v2/metrics.feature index 24b766d5d5..d463aa4250 100644 --- a/tests/scenarios/features/v2/metrics.feature +++ b/tests/scenarios/features/v2/metrics.feature @@ -106,6 +106,42 @@ Feature: Metrics When the request is sent Then the response status is 201 Created + @team:DataDog/metrics-experience + Scenario: Create a tag indexing rule with exclude-mode tag usage fields returns "Created" response + Given a valid "appKeyAuth" key in the system + And operation "CreateTagIndexingRule" enabled + And new "CreateTagIndexingRule" request + And body with value {"data": {"attributes": {"exclude_tags_mode": true, "ignored_metric_name_matches": [], "metric_name_matches": ["dd.test.*"], "name": "my-indexing-rule", "options": {"data": {"dynamic_tags": {"exclude_not_queried_window_seconds": 3600, "exclude_not_used_in_assets": true}, "manage_preexisting_metrics": true, "override_previous_rules": false}, "version": 1}, "tags": ["env", "service"]}, "type": "tag_indexing_rules"}} + When the request is sent + Then the response status is 201 Created + + @team:DataDog/metrics-experience + Scenario: Create a tag indexing rule with exclude_not_queried_window_seconds and exclude_tags_mode false returns "Bad Request" response + Given a valid "appKeyAuth" key in the system + And operation "CreateTagIndexingRule" enabled + And new "CreateTagIndexingRule" request + And body with value {"data": {"attributes": {"exclude_tags_mode": false, "ignored_metric_name_matches": [], "metric_name_matches": ["dd.test.*"], "name": "my-indexing-rule", "options": {"data": {"dynamic_tags": {"exclude_not_queried_window_seconds": 3600}, "manage_preexisting_metrics": true, "override_previous_rules": false}, "version": 1}, "tags": ["env", "service"]}, "type": "tag_indexing_rules"}} + When the request is sent + Then the response status is 400 Bad Request + + @skip @team:DataDog/metrics-experience + Scenario: Create a tag indexing rule with exclude_not_queried_window_seconds over the maximum returns "Bad Request" response + Given a valid "appKeyAuth" key in the system + And operation "CreateTagIndexingRule" enabled + And new "CreateTagIndexingRule" request + And body with value {"data": {"attributes": {"exclude_tags_mode": true, "ignored_metric_name_matches": [], "metric_name_matches": ["dd.test.*"], "name": "my-indexing-rule", "options": {"data": {"dynamic_tags": {"exclude_not_queried_window_seconds": 7776001}, "manage_preexisting_metrics": true, "override_previous_rules": false}, "version": 1}, "tags": ["env", "service"]}, "type": "tag_indexing_rules"}} + When the request is sent + Then the response status is 400 Bad Request + + @team:DataDog/metrics-experience + Scenario: Create a tag indexing rule with exclude_not_used_in_assets and exclude_tags_mode false returns "Bad Request" response + Given a valid "appKeyAuth" key in the system + And operation "CreateTagIndexingRule" enabled + And new "CreateTagIndexingRule" request + And body with value {"data": {"attributes": {"exclude_tags_mode": false, "ignored_metric_name_matches": [], "metric_name_matches": ["dd.test.*"], "name": "my-indexing-rule", "options": {"data": {"dynamic_tags": {"exclude_not_used_in_assets": true}, "manage_preexisting_metrics": true, "override_previous_rules": false}, "version": 1}, "tags": ["env", "service"]}, "type": "tag_indexing_rules"}} + When the request is sent + Then the response status is 400 Bad Request + @replay-only @skip-validation @team:DataDog/metrics-experience Scenario: Delete a tag configuration returns "No Content" response Given there is a valid "metric" in the system @@ -995,7 +1031,7 @@ Feature: Metrics And operation "UpdateTagIndexingRule" enabled And new "UpdateTagIndexingRule" request And request contains "id" parameter from "REPLACE.ME" - And body with value {"data": {"attributes": {"ignored_metric_name_matches": [], "metric_name_matches": ["dd.test.*"], "name": "my-indexing-rule", "options": {"data": {"dynamic_tags": {"queried_tags_window_seconds": 3600, "related_asset_tags": false}, "manage_preexisting_metrics": true, "metric_match": {"queried_window_seconds": 3600}, "override_previous_rules": false}, "version": 1}, "rule_order": 2, "tags": ["env", "service"]}, "type": "tag_indexing_rules"}} + And body with value {"data": {"attributes": {"ignored_metric_name_matches": [], "metric_name_matches": ["dd.test.*"], "name": "my-indexing-rule", "options": {"data": {"dynamic_tags": {"exclude_not_queried_window_seconds": 3600, "exclude_not_used_in_assets": false, "queried_tags_window_seconds": 3600, "related_asset_tags": false}, "manage_preexisting_metrics": true, "metric_match": {"queried_window_seconds": 3600}, "override_previous_rules": false}, "version": 1}, "rule_order": 2, "tags": ["env", "service"]}, "type": "tag_indexing_rules"}} When the request is sent Then the response status is 409 Conflict @@ -1019,3 +1055,14 @@ Feature: Metrics And body with value {"data": {"attributes": {"ignored_metric_name_matches": [], "metric_name_matches": ["dd.test.*"], "name": "my-indexing-rule", "options": {"data": {"dynamic_tags": {"queried_tags_window_seconds": 3600, "related_asset_tags": false}, "manage_preexisting_metrics": true, "metric_match": {"queried_window_seconds": 3600}, "override_previous_rules": false}, "version": 1}, "rule_order": 2, "tags": ["env", "service"]}, "type": "tag_indexing_rules"}} When the request is sent Then the response status is 200 OK + + @team:DataDog/metrics-experience + Scenario: Update a tag indexing rule with exclude-mode tag usage fields returns "OK" response + Given a valid "appKeyAuth" key in the system + And operation "UpdateTagIndexingRule" enabled + And there is a valid "tag_indexing_rule_exclude_mode" in the system + And new "UpdateTagIndexingRule" request + And request contains "id" parameter from "tag_indexing_rule_exclude_mode.data.id" + And body with value {"data": {"attributes": {"exclude_tags_mode": true, "ignored_metric_name_matches": [], "metric_name_matches": ["dd.test.*"], "name": "my-indexing-rule", "options": {"data": {"dynamic_tags": {"exclude_not_queried_window_seconds": 7200, "exclude_not_used_in_assets": true}, "manage_preexisting_metrics": true, "override_previous_rules": false}, "version": 1}, "rule_order": 2, "tags": ["env", "service"]}, "type": "tag_indexing_rules"}} + When the request is sent + Then the response status is 200 OK