diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index ed984a56d0ee..61320cadad6b 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/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.frozen b/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.frozen new file mode 100644 index 000000000000..0f10cd49f01b --- /dev/null +++ b/cassettes/features/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/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.yml b/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.yml new file mode 100644 index 000000000000..6d2c57139b70 --- /dev/null +++ b/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-Created-response.yml @@ -0,0 +1,40 @@ +http_interactions: +- recorded_at: Mon, 20 Jul 2026 13:47:22 GMT + request: + body: + encoding: UTF-8 + 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"}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules + response: + body: + encoding: UTF-8 + 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"]}}}' + headers: + Content-Type: + - application/vnd.api+json + status: + code: 201 + message: Created +- recorded_at: Mon, 20 Jul 2026 13:47:22 GMT + request: + body: null + headers: + Accept: + - '*/*' + method: DELETE + uri: https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules/50b7b68a-4580-4f9b-8c2c-8622446e68eb + response: + body: + encoding: UTF-8 + string: '' + headers: {} + status: + code: 204 + message: No Content +recorded_with: VCR 6.0.0 diff --git a/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.frozen b/cassettes/features/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 000000000000..e653d5706178 --- /dev/null +++ b/cassettes/features/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/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.yml b/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.yml new file mode 100644 index 000000000000..584d6a073099 --- /dev/null +++ b/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-and-exclude-tags-mode-false-returns-Bad-Request-response.yml @@ -0,0 +1,26 @@ +http_interactions: +- recorded_at: Mon, 20 Jul 2026 13:47:24 GMT + request: + body: + encoding: UTF-8 + 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"}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules + response: + body: + encoding: UTF-8 + 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\"]}" + headers: + Content-Type: + - application/vnd.api+json + status: + code: 400 + message: Bad Request +recorded_with: VCR 6.0.0 diff --git a/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.frozen b/cassettes/features/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 000000000000..34477e0b5373 --- /dev/null +++ b/cassettes/features/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/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.yml b/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.yml new file mode 100644 index 000000000000..bf8085281051 --- /dev/null +++ b/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-queried-window-seconds-over-the-maximum-returns-Bad-Request-response.yml @@ -0,0 +1,25 @@ +http_interactions: +- recorded_at: Mon, 20 Jul 2026 13:47:24 GMT + request: + body: + encoding: UTF-8 + 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"}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules + response: + body: + encoding: UTF-8 + string: '{"errors":["Invalid request body: dynamic_tags.exclude_not_queried_window_seconds + cannot exceed 7776000 seconds (90 days)"]}' + headers: + Content-Type: + - application/vnd.api+json + status: + code: 400 + message: Bad Request +recorded_with: VCR 6.0.0 diff --git a/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.frozen b/cassettes/features/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 000000000000..bfa63b117d47 --- /dev/null +++ b/cassettes/features/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/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.yml b/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.yml new file mode 100644 index 000000000000..3175f7ac4f92 --- /dev/null +++ b/cassettes/features/v2/metrics/Create-a-tag-indexing-rule-with-exclude-not-used-in-assets-and-exclude-tags-mode-false-returns-Bad-Request-response.yml @@ -0,0 +1,26 @@ +http_interactions: +- recorded_at: Mon, 20 Jul 2026 13:47:24 GMT + request: + body: + encoding: UTF-8 + 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"}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules + response: + body: + encoding: UTF-8 + 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\"]}" + headers: + Content-Type: + - application/vnd.api+json + status: + code: 400 + message: Bad Request +recorded_with: VCR 6.0.0 diff --git a/cassettes/features/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.frozen b/cassettes/features/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.frozen new file mode 100644 index 000000000000..41394dceed3a --- /dev/null +++ b/cassettes/features/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/cassettes/features/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.yml b/cassettes/features/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.yml new file mode 100644 index 000000000000..7751b3f4a543 --- /dev/null +++ b/cassettes/features/v2/metrics/Update-a-tag-indexing-rule-with-exclude-mode-tag-usage-fields-returns-OK-response.yml @@ -0,0 +1,62 @@ +http_interactions: +- recorded_at: Mon, 20 Jul 2026 13:47:24 GMT + request: + body: + encoding: UTF-8 + string: '{"data":{"attributes":{"exclude_tags_mode":true,"metric_name_matches":["dd.TestUpdateatagindexingrulewithexcludemodetagusagefieldsreturnsOKresponse1784555244.*"],"name":"TestUpdateatagindexingrulewithexcludemodetagusagefieldsreturnsOKresponse1784555244","tags":["env","service"]},"type":"tag_indexing_rules"}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules + response: + body: + encoding: UTF-8 + 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"]}}}' + headers: + Content-Type: + - application/vnd.api+json + status: + code: 201 + message: Created +- recorded_at: Mon, 20 Jul 2026 13:47:24 GMT + request: + body: + encoding: UTF-8 + 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"}}' + 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: + encoding: UTF-8 + 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"]}}}' + headers: + Content-Type: + - application/vnd.api+json + status: + code: 200 + message: OK +- recorded_at: Mon, 20 Jul 2026 13:47:24 GMT + request: + body: null + headers: + Accept: + - '*/*' + method: DELETE + uri: https://api.datadoghq.com/api/v2/metrics/tag-indexing-rules/e4a507ac-ee83-439b-bf65-72d162150e3c + response: + body: + encoding: UTF-8 + string: '' + headers: {} + status: + code: 204 + message: No Content +recorded_with: VCR 6.0.0 diff --git a/examples/v2/metrics/CreateTagIndexingRule_2435129406.rb b/examples/v2/metrics/CreateTagIndexingRule_2435129406.rb new file mode 100644 index 000000000000..b8a6b06fff88 --- /dev/null +++ b/examples/v2/metrics/CreateTagIndexingRule_2435129406.rb @@ -0,0 +1,37 @@ +# Create a tag indexing rule with exclude-mode tag usage fields returns "Created" response + +require "datadog_api_client" +DatadogAPIClient.configure do |config| + config.unstable_operations["v2.create_tag_indexing_rule".to_sym] = true +end +api_instance = DatadogAPIClient::V2::MetricsAPI.new + +body = DatadogAPIClient::V2::TagIndexingRuleCreateRequest.new({ + data: DatadogAPIClient::V2::TagIndexingRuleCreateData.new({ + attributes: DatadogAPIClient::V2::TagIndexingRuleCreateAttributes.new({ + exclude_tags_mode: true, + ignored_metric_name_matches: [], + metric_name_matches: [ + "dd.test.*", + ], + name: "my-indexing-rule", + options: DatadogAPIClient::V2::TagIndexingRuleOptions.new({ + data: DatadogAPIClient::V2::TagIndexingRuleOptionsData.new({ + dynamic_tags: DatadogAPIClient::V2::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: [ + "env", + "service", + ], + }), + type: DatadogAPIClient::V2::TagIndexingRuleType::TAG_INDEXING_RULES, + }), +}) +p api_instance.create_tag_indexing_rule(body) diff --git a/examples/v2/metrics/UpdateTagIndexingRule_4127399471.rb b/examples/v2/metrics/UpdateTagIndexingRule_4127399471.rb new file mode 100644 index 000000000000..a3d43b57f152 --- /dev/null +++ b/examples/v2/metrics/UpdateTagIndexingRule_4127399471.rb @@ -0,0 +1,41 @@ +# Update a tag indexing rule with exclude-mode tag usage fields returns "OK" response + +require "datadog_api_client" +DatadogAPIClient.configure do |config| + config.unstable_operations["v2.update_tag_indexing_rule".to_sym] = true +end +api_instance = DatadogAPIClient::V2::MetricsAPI.new + +# there is a valid "tag_indexing_rule_exclude_mode" in the system +TAG_INDEXING_RULE_EXCLUDE_MODE_DATA_ID = ENV["TAG_INDEXING_RULE_EXCLUDE_MODE_DATA_ID"] + +body = DatadogAPIClient::V2::TagIndexingRuleUpdateRequest.new({ + data: DatadogAPIClient::V2::TagIndexingRuleUpdateData.new({ + attributes: DatadogAPIClient::V2::TagIndexingRuleUpdateAttributes.new({ + exclude_tags_mode: true, + ignored_metric_name_matches: [], + metric_name_matches: [ + "dd.test.*", + ], + name: "my-indexing-rule", + options: DatadogAPIClient::V2::TagIndexingRuleOptions.new({ + data: DatadogAPIClient::V2::TagIndexingRuleOptionsData.new({ + dynamic_tags: DatadogAPIClient::V2::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: [ + "env", + "service", + ], + }), + type: DatadogAPIClient::V2::TagIndexingRuleType::TAG_INDEXING_RULES, + }), +}) +p api_instance.update_tag_indexing_rule(TAG_INDEXING_RULE_EXCLUDE_MODE_DATA_ID, body) diff --git a/features/v2/given.json b/features/v2/given.json index 0f9de6d48a2f..75fa924ff16d 100644 --- a/features/v2/given.json +++ b/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/features/v2/metrics.feature b/features/v2/metrics.feature index 24b766d5d565..d463aa4250b4 100644 --- a/features/v2/metrics.feature +++ b/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 diff --git a/lib/datadog_api_client/v2/models/tag_indexing_rule_dynamic_tags.rb b/lib/datadog_api_client/v2/models/tag_indexing_rule_dynamic_tags.rb index 3e8e296e4030..1527e880f8e9 100644 --- a/lib/datadog_api_client/v2/models/tag_indexing_rule_dynamic_tags.rb +++ b/lib/datadog_api_client/v2/models/tag_indexing_rule_dynamic_tags.rb @@ -17,10 +17,24 @@ require 'time' module DatadogAPIClient::V2 - # 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`. class TagIndexingRuleDynamicTags include BaseGenericModel + # Tags that have not been queried within this window are excluded from indexing. Maximum of `7776000` (90 days). + attr_reader :exclude_not_queried_window_seconds + + # Tags not used in any dashboards, monitors, notebooks, or SLOs are excluded from indexing. + attr_accessor :exclude_not_used_in_assets + # Window in seconds for evaluating queried tags. attr_accessor :queried_tags_window_seconds @@ -33,6 +47,8 @@ class TagIndexingRuleDynamicTags # @!visibility private def self.attribute_map { + :'exclude_not_queried_window_seconds' => :'exclude_not_queried_window_seconds', + :'exclude_not_used_in_assets' => :'exclude_not_used_in_assets', :'queried_tags_window_seconds' => :'queried_tags_window_seconds', :'related_asset_tags' => :'related_asset_tags' } @@ -42,6 +58,8 @@ def self.attribute_map # @!visibility private def self.openapi_types { + :'exclude_not_queried_window_seconds' => :'Integer', + :'exclude_not_used_in_assets' => :'Boolean', :'queried_tags_window_seconds' => :'Integer', :'related_asset_tags' => :'Boolean' } @@ -65,6 +83,14 @@ def initialize(attributes = {}) end } + if attributes.key?(:'exclude_not_queried_window_seconds') + self.exclude_not_queried_window_seconds = attributes[:'exclude_not_queried_window_seconds'] + end + + if attributes.key?(:'exclude_not_used_in_assets') + self.exclude_not_used_in_assets = attributes[:'exclude_not_used_in_assets'] + end + if attributes.key?(:'queried_tags_window_seconds') self.queried_tags_window_seconds = attributes[:'queried_tags_window_seconds'] end @@ -74,6 +100,24 @@ def initialize(attributes = {}) end end + # Check to see if the all the properties in the model are valid + # @return true if the model is valid + # @!visibility private + def valid? + return false if !@exclude_not_queried_window_seconds.nil? && @exclude_not_queried_window_seconds > 7776000 + true + end + + # Custom attribute writer method with validation + # @param exclude_not_queried_window_seconds [Object] Object to be assigned + # @!visibility private + def exclude_not_queried_window_seconds=(exclude_not_queried_window_seconds) + if !exclude_not_queried_window_seconds.nil? && exclude_not_queried_window_seconds > 7776000 + fail ArgumentError, 'invalid value for "exclude_not_queried_window_seconds", must be smaller than or equal to 7776000.' + end + @exclude_not_queried_window_seconds = exclude_not_queried_window_seconds + end + # Returns the object in the form of hash, with additionalProperties support. # @return [Hash] Returns the object in the form of hash # @!visibility private @@ -100,6 +144,8 @@ def to_hash def ==(o) return true if self.equal?(o) self.class == o.class && + exclude_not_queried_window_seconds == o.exclude_not_queried_window_seconds && + exclude_not_used_in_assets == o.exclude_not_used_in_assets && queried_tags_window_seconds == o.queried_tags_window_seconds && related_asset_tags == o.related_asset_tags && additional_properties == o.additional_properties @@ -109,7 +155,7 @@ def ==(o) # @return [Integer] Hash code # @!visibility private def hash - [queried_tags_window_seconds, related_asset_tags, additional_properties].hash + [exclude_not_queried_window_seconds, exclude_not_used_in_assets, queried_tags_window_seconds, related_asset_tags, additional_properties].hash end end end diff --git a/lib/datadog_api_client/v2/models/tag_indexing_rule_options_data.rb b/lib/datadog_api_client/v2/models/tag_indexing_rule_options_data.rb index 277bc0925a98..e875139fb5c4 100644 --- a/lib/datadog_api_client/v2/models/tag_indexing_rule_options_data.rb +++ b/lib/datadog_api_client/v2/models/tag_indexing_rule_options_data.rb @@ -21,7 +21,15 @@ module DatadogAPIClient::V2 class TagIndexingRuleOptionsData include BaseGenericModel - # 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`. attr_accessor :dynamic_tags # When true, the rule applies to metrics that were ingested before the rule was created.