diff --git a/.generator/schemas/v1/openapi.yaml b/.generator/schemas/v1/openapi.yaml index 832230d382..099902b477 100644 --- a/.generator/schemas/v1/openapi.yaml +++ b/.generator/schemas/v1/openapi.yaml @@ -25954,6 +25954,8 @@ components: $ref: '#/components/schemas/WidgetLineType' line_width: $ref: '#/components/schemas/WidgetLineWidth' + order_by: + $ref: '#/components/schemas/WidgetStyleOrderBy' palette: description: Color palette to apply to the widget. type: string @@ -26016,6 +26018,19 @@ components: description: Color palette to apply to the widget. type: string type: object + WidgetStyleOrderBy: + description: 'How to order series in timeseries visualizations. + + - `tags`: Order series alphabetically by tag name (default behavior) + + - `values`: Order series by their current metric values (typically descending)' + enum: + - tags + - values + type: string + x-enum-varnames: + - TAGS + - VALUES WidgetSummaryType: description: Which summary type should be used. enum: diff --git a/docs/datadog_api_client.v1.model.rst b/docs/datadog_api_client.v1.model.rst index c75382ef3d..11d7ba1320 100644 --- a/docs/datadog_api_client.v1.model.rst +++ b/docs/datadog_api_client.v1.model.rst @@ -6857,6 +6857,13 @@ datadog\_api\_client.v1.model.widget\_style module :members: :show-inheritance: +datadog\_api\_client.v1.model.widget\_style\_order\_by module +------------------------------------------------------------- + +.. automodule:: datadog_api_client.v1.model.widget_style_order_by + :members: + :show-inheritance: + datadog\_api\_client.v1.model.widget\_summary\_type module ---------------------------------------------------------- diff --git a/examples/v1/dashboards/CreateDashboard_1259346254.py b/examples/v1/dashboards/CreateDashboard_1259346254.py new file mode 100644 index 0000000000..24db4f984c --- /dev/null +++ b/examples/v1/dashboards/CreateDashboard_1259346254.py @@ -0,0 +1,44 @@ +""" +Create a new dashboard with timeseries widget using order_by values +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v1.api.dashboards_api import DashboardsApi +from datadog_api_client.v1.model.dashboard import Dashboard +from datadog_api_client.v1.model.dashboard_layout_type import DashboardLayoutType +from datadog_api_client.v1.model.timeseries_widget_definition import TimeseriesWidgetDefinition +from datadog_api_client.v1.model.timeseries_widget_definition_type import TimeseriesWidgetDefinitionType +from datadog_api_client.v1.model.timeseries_widget_request import TimeseriesWidgetRequest +from datadog_api_client.v1.model.widget import Widget +from datadog_api_client.v1.model.widget_display_type import WidgetDisplayType +from datadog_api_client.v1.model.widget_request_style import WidgetRequestStyle +from datadog_api_client.v1.model.widget_style_order_by import WidgetStyleOrderBy + +body = Dashboard( + layout_type=DashboardLayoutType.ORDERED, + title="Example-Dashboard with order_by values", + widgets=[ + Widget( + definition=TimeseriesWidgetDefinition( + type=TimeseriesWidgetDefinitionType.TIMESERIES, + requests=[ + TimeseriesWidgetRequest( + q="avg:system.cpu.user{*} by {host}", + style=WidgetRequestStyle( + palette="warm", + order_by=WidgetStyleOrderBy.VALUES, + ), + display_type=WidgetDisplayType.LINE, + ), + ], + ), + ), + ], +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = DashboardsApi(api_client) + response = api_instance.create_dashboard(body=body) + + print(response) diff --git a/examples/v1/dashboards/CreateDashboard_3631423980.py b/examples/v1/dashboards/CreateDashboard_3631423980.py new file mode 100644 index 0000000000..59b1b74705 --- /dev/null +++ b/examples/v1/dashboards/CreateDashboard_3631423980.py @@ -0,0 +1,46 @@ +""" +Create a new dashboard with timeseries widget without order_by for backward compatibility +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v1.api.dashboards_api import DashboardsApi +from datadog_api_client.v1.model.dashboard import Dashboard +from datadog_api_client.v1.model.dashboard_layout_type import DashboardLayoutType +from datadog_api_client.v1.model.timeseries_widget_definition import TimeseriesWidgetDefinition +from datadog_api_client.v1.model.timeseries_widget_definition_type import TimeseriesWidgetDefinitionType +from datadog_api_client.v1.model.timeseries_widget_request import TimeseriesWidgetRequest +from datadog_api_client.v1.model.widget import Widget +from datadog_api_client.v1.model.widget_display_type import WidgetDisplayType +from datadog_api_client.v1.model.widget_line_type import WidgetLineType +from datadog_api_client.v1.model.widget_line_width import WidgetLineWidth +from datadog_api_client.v1.model.widget_request_style import WidgetRequestStyle + +body = Dashboard( + layout_type=DashboardLayoutType.ORDERED, + title="Example-Dashboard without order_by", + widgets=[ + Widget( + definition=TimeseriesWidgetDefinition( + type=TimeseriesWidgetDefinitionType.TIMESERIES, + requests=[ + TimeseriesWidgetRequest( + q="avg:system.cpu.user{*} by {host}", + style=WidgetRequestStyle( + palette="dog_classic", + line_type=WidgetLineType.SOLID, + line_width=WidgetLineWidth.NORMAL, + ), + display_type=WidgetDisplayType.LINE, + ), + ], + ), + ), + ], +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = DashboardsApi(api_client) + response = api_instance.create_dashboard(body=body) + + print(response) diff --git a/examples/v1/dashboards/CreateDashboard_416487533.py b/examples/v1/dashboards/CreateDashboard_416487533.py new file mode 100644 index 0000000000..e97c037066 --- /dev/null +++ b/examples/v1/dashboards/CreateDashboard_416487533.py @@ -0,0 +1,44 @@ +""" +Create a new dashboard with timeseries widget using order_by tags +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v1.api.dashboards_api import DashboardsApi +from datadog_api_client.v1.model.dashboard import Dashboard +from datadog_api_client.v1.model.dashboard_layout_type import DashboardLayoutType +from datadog_api_client.v1.model.timeseries_widget_definition import TimeseriesWidgetDefinition +from datadog_api_client.v1.model.timeseries_widget_definition_type import TimeseriesWidgetDefinitionType +from datadog_api_client.v1.model.timeseries_widget_request import TimeseriesWidgetRequest +from datadog_api_client.v1.model.widget import Widget +from datadog_api_client.v1.model.widget_display_type import WidgetDisplayType +from datadog_api_client.v1.model.widget_request_style import WidgetRequestStyle +from datadog_api_client.v1.model.widget_style_order_by import WidgetStyleOrderBy + +body = Dashboard( + layout_type=DashboardLayoutType.ORDERED, + title="Example-Dashboard with order_by tags", + widgets=[ + Widget( + definition=TimeseriesWidgetDefinition( + type=TimeseriesWidgetDefinitionType.TIMESERIES, + requests=[ + TimeseriesWidgetRequest( + q="avg:system.cpu.user{*} by {host}", + style=WidgetRequestStyle( + palette="dog_classic", + order_by=WidgetStyleOrderBy.TAGS, + ), + display_type=WidgetDisplayType.LINE, + ), + ], + ), + ), + ], +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = DashboardsApi(api_client) + response = api_instance.create_dashboard(body=body) + + print(response) diff --git a/src/datadog_api_client/v1/model/widget_request_style.py b/src/datadog_api_client/v1/model/widget_request_style.py index d8993cee70..899b2682c1 100644 --- a/src/datadog_api_client/v1/model/widget_request_style.py +++ b/src/datadog_api_client/v1/model/widget_request_style.py @@ -16,6 +16,7 @@ if TYPE_CHECKING: from datadog_api_client.v1.model.widget_line_type import WidgetLineType from datadog_api_client.v1.model.widget_line_width import WidgetLineWidth + from datadog_api_client.v1.model.widget_style_order_by import WidgetStyleOrderBy class WidgetRequestStyle(ModelNormal): @@ -23,16 +24,19 @@ class WidgetRequestStyle(ModelNormal): def openapi_types(_): from datadog_api_client.v1.model.widget_line_type import WidgetLineType from datadog_api_client.v1.model.widget_line_width import WidgetLineWidth + from datadog_api_client.v1.model.widget_style_order_by import WidgetStyleOrderBy return { "line_type": (WidgetLineType,), "line_width": (WidgetLineWidth,), + "order_by": (WidgetStyleOrderBy,), "palette": (str,), } attribute_map = { "line_type": "line_type", "line_width": "line_width", + "order_by": "order_by", "palette": "palette", } @@ -40,6 +44,7 @@ def __init__( self_, line_type: Union[WidgetLineType, UnsetType] = unset, line_width: Union[WidgetLineWidth, UnsetType] = unset, + order_by: Union[WidgetStyleOrderBy, UnsetType] = unset, palette: Union[str, UnsetType] = unset, **kwargs, ): @@ -52,6 +57,12 @@ def __init__( :param line_width: Width of line displayed. :type line_width: WidgetLineWidth, optional + :param order_by: How to order series in timeseries visualizations. + + * ``tags`` : Order series alphabetically by tag name (default behavior) + * ``values`` : Order series by their current metric values (typically descending) + :type order_by: WidgetStyleOrderBy, optional + :param palette: Color palette to apply to the widget. :type palette: str, optional """ @@ -59,6 +70,8 @@ def __init__( kwargs["line_type"] = line_type if line_width is not unset: kwargs["line_width"] = line_width + if order_by is not unset: + kwargs["order_by"] = order_by if palette is not unset: kwargs["palette"] = palette super().__init__(kwargs) diff --git a/src/datadog_api_client/v1/model/widget_style_order_by.py b/src/datadog_api_client/v1/model/widget_style_order_by.py new file mode 100644 index 0000000000..1a761fb913 --- /dev/null +++ b/src/datadog_api_client/v1/model/widget_style_order_by.py @@ -0,0 +1,40 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + + +from datadog_api_client.model_utils import ( + ModelSimple, + cached_property, +) + +from typing import ClassVar + + +class WidgetStyleOrderBy(ModelSimple): + """ + How to order series in timeseries visualizations. + - `tags`: Order series alphabetically by tag name (default behavior) + - `values`: Order series by their current metric values (typically descending) + + :param value: Must be one of ["tags", "values"]. + :type value: str + """ + + allowed_values = { + "tags", + "values", + } + TAGS: ClassVar["WidgetStyleOrderBy"] + VALUES: ClassVar["WidgetStyleOrderBy"] + + @cached_property + def openapi_types(_): + return { + "value": (str,), + } + + +WidgetStyleOrderBy.TAGS = WidgetStyleOrderBy("tags") +WidgetStyleOrderBy.VALUES = WidgetStyleOrderBy("values") diff --git a/src/datadog_api_client/v1/models/__init__.py b/src/datadog_api_client/v1/models/__init__.py index 54199dbf5d..43893fead5 100644 --- a/src/datadog_api_client/v1/models/__init__.py +++ b/src/datadog_api_client/v1/models/__init__.py @@ -1138,6 +1138,7 @@ from datadog_api_client.v1.model.widget_sort_by import WidgetSortBy from datadog_api_client.v1.model.widget_sort_order_by import WidgetSortOrderBy from datadog_api_client.v1.model.widget_style import WidgetStyle +from datadog_api_client.v1.model.widget_style_order_by import WidgetStyleOrderBy from datadog_api_client.v1.model.widget_summary_type import WidgetSummaryType from datadog_api_client.v1.model.widget_text_align import WidgetTextAlign from datadog_api_client.v1.model.widget_tick_edge import WidgetTickEdge @@ -2128,6 +2129,7 @@ "WidgetSortBy", "WidgetSortOrderBy", "WidgetStyle", + "WidgetStyleOrderBy", "WidgetSummaryType", "WidgetTextAlign", "WidgetTickEdge", diff --git a/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_tags.frozen b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_tags.frozen new file mode 100644 index 0000000000..951919f26b --- /dev/null +++ b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_tags.frozen @@ -0,0 +1 @@ +2026-01-20T23:39:22.864Z \ No newline at end of file diff --git a/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_tags.yaml b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_tags.yaml new file mode 100644 index 0000000000..935bc8a85b --- /dev/null +++ b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_tags.yaml @@ -0,0 +1,40 @@ +interactions: +- request: + body: '{"layout_type":"ordered","title":"Test-Create_a_new_dashboard_with_timeseries_widget_using_order_by_tags-1768952362 + with order_by tags","widgets":[{"definition":{"requests":[{"display_type":"line","q":"avg:system.cpu.user{*} + by {host}","style":{"order_by":"tags","palette":"dog_classic"}}],"type":"timeseries"}}]}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v1/dashboard + response: + body: + string: '{"id":"2r3-a4g-ubz","title":"Test-Create_a_new_dashboard_with_timeseries_widget_using_order_by_tags-1768952362 + with order_by tags","description":null,"author_handle":"frog@datadoghq.com","author_name":"frog","layout_type":"ordered","url":"/dashboard/2r3-a4g-ubz/test-createanewdashboardwithtimeserieswidgetusingorderbytags-1768952362-with-ord","template_variables":null,"widgets":[{"definition":{"requests":[{"display_type":"line","q":"avg:system.cpu.user{*} + by {host}","style":{"order_by":"tags","palette":"dog_classic"}}],"type":"timeseries"},"id":8704189893014651}],"notify_list":null,"created_at":"2026-01-20T23:39:22.992533+00:00","modified_at":"2026-01-20T23:39:22.992533+00:00","restricted_roles":[]}' + headers: + content-type: + - application/json + status: + code: 200 + message: OK +- request: + body: null + headers: + accept: + - application/json + method: DELETE + uri: https://api.datadoghq.com/api/v1/dashboard/2r3-a4g-ubz + response: + body: + string: '{"deleted_dashboard_id":"2r3-a4g-ubz"}' + headers: + content-type: + - application/json + status: + code: 200 + message: OK +version: 1 diff --git a/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_values.frozen b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_values.frozen new file mode 100644 index 0000000000..67f7233349 --- /dev/null +++ b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_values.frozen @@ -0,0 +1 @@ +2026-01-20T23:39:50.889Z \ No newline at end of file diff --git a/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_values.yaml b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_values.yaml new file mode 100644 index 0000000000..2c4250d28b --- /dev/null +++ b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_using_order_by_values.yaml @@ -0,0 +1,40 @@ +interactions: +- request: + body: '{"layout_type":"ordered","title":"Test-Create_a_new_dashboard_with_timeseries_widget_using_order_by_values-1768952390 + with order_by values","widgets":[{"definition":{"requests":[{"display_type":"line","q":"avg:system.cpu.user{*} + by {host}","style":{"order_by":"values","palette":"warm"}}],"type":"timeseries"}}]}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v1/dashboard + response: + body: + string: '{"id":"5ee-dqv-ruw","title":"Test-Create_a_new_dashboard_with_timeseries_widget_using_order_by_values-1768952390 + with order_by values","description":null,"author_handle":"frog@datadoghq.com","author_name":"frog","layout_type":"ordered","url":"/dashboard/5ee-dqv-ruw/test-createanewdashboardwithtimeserieswidgetusingorderbyvalues-1768952390-with-o","template_variables":null,"widgets":[{"definition":{"requests":[{"display_type":"line","q":"avg:system.cpu.user{*} + by {host}","style":{"order_by":"values","palette":"warm"}}],"type":"timeseries"},"id":8314193502199768}],"notify_list":null,"created_at":"2026-01-20T23:39:51.018015+00:00","modified_at":"2026-01-20T23:39:51.018015+00:00","restricted_roles":[]}' + headers: + content-type: + - application/json + status: + code: 200 + message: OK +- request: + body: null + headers: + accept: + - application/json + method: DELETE + uri: https://api.datadoghq.com/api/v1/dashboard/5ee-dqv-ruw + response: + body: + string: '{"deleted_dashboard_id":"5ee-dqv-ruw"}' + headers: + content-type: + - application/json + status: + code: 200 + message: OK +version: 1 diff --git a/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_without_order_by_for_backward_compatibility.frozen b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_without_order_by_for_backward_compatibility.frozen new file mode 100644 index 0000000000..608e803e2f --- /dev/null +++ b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_without_order_by_for_backward_compatibility.frozen @@ -0,0 +1 @@ +2026-01-20T23:40:15.566Z \ No newline at end of file diff --git a/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_without_order_by_for_backward_compatibility.yaml b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_without_order_by_for_backward_compatibility.yaml new file mode 100644 index 0000000000..2dabdf30ba --- /dev/null +++ b/tests/v1/cassettes/test_scenarios/test_create_a_new_dashboard_with_timeseries_widget_without_order_by_for_backward_compatibility.yaml @@ -0,0 +1,40 @@ +interactions: +- request: + body: '{"layout_type":"ordered","title":"Test-Create_a_new_dashboard_with_timeseries_widget_without_order_by_for_backward_compatibility-1768952415 + without order_by","widgets":[{"definition":{"requests":[{"display_type":"line","q":"avg:system.cpu.user{*} + by {host}","style":{"line_type":"solid","line_width":"normal","palette":"dog_classic"}}],"type":"timeseries"}}]}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v1/dashboard + response: + body: + string: '{"id":"6bg-rgq-fxc","title":"Test-Create_a_new_dashboard_with_timeseries_widget_without_order_by_for_backward_compatibility-1768952415 + without order_by","description":null,"author_handle":"frog@datadoghq.com","author_name":"frog","layout_type":"ordered","url":"/dashboard/6bg-rgq-fxc/test-createanewdashboardwithtimeserieswidgetwithoutorderbyforbackwardcompatibili","template_variables":null,"widgets":[{"definition":{"requests":[{"display_type":"line","q":"avg:system.cpu.user{*} + by {host}","style":{"line_type":"solid","line_width":"normal","palette":"dog_classic"}}],"type":"timeseries"},"id":2503785343641105}],"notify_list":null,"created_at":"2026-01-20T23:40:15.937647+00:00","modified_at":"2026-01-20T23:40:15.937647+00:00","restricted_roles":[]}' + headers: + content-type: + - application/json + status: + code: 200 + message: OK +- request: + body: null + headers: + accept: + - application/json + method: DELETE + uri: https://api.datadoghq.com/api/v1/dashboard/6bg-rgq-fxc + response: + body: + string: '{"deleted_dashboard_id":"6bg-rgq-fxc"}' + headers: + content-type: + - application/json + status: + code: 200 + message: OK +version: 1 diff --git a/tests/v1/features/dashboards.feature b/tests/v1/features/dashboards.feature index 6b67bc6504..349f7de6f9 100644 --- a/tests/v1/features/dashboards.feature +++ b/tests/v1/features/dashboards.feature @@ -946,6 +946,24 @@ Feature: Dashboards And the response "widgets[0].definition.requests[0].display_type" is equal to "bars" And the response "widgets[0].definition.requests[0].q" is equal to "sum:trace.test.errors{env:prod,service:datadog-api-spec} by {resource_name}.as_count()" + @team:DataDog/dashboards-backend + Scenario: Create a new dashboard with timeseries widget using order_by tags + Given new "CreateDashboard" request + And body with value {"layout_type": "ordered", "title": "{{ unique }} with order_by tags","widgets": [{"definition": {"type": "timeseries","requests": [{"q": "avg:system.cpu.user{*} by {host}","style": {"palette": "dog_classic","order_by": "tags"},"display_type": "line"}]}}]} + When the request is sent + Then the response status is 200 OK + And the response "widgets[0].definition.requests[0].style.order_by" is equal to "tags" + And the response "widgets[0].definition.requests[0].style.palette" is equal to "dog_classic" + + @team:DataDog/dashboards-backend + Scenario: Create a new dashboard with timeseries widget using order_by values + Given new "CreateDashboard" request + And body with value {"layout_type": "ordered", "title": "{{ unique }} with order_by values","widgets": [{"definition": {"type": "timeseries","requests": [{"q": "avg:system.cpu.user{*} by {host}","style": {"palette": "warm","order_by": "values"},"display_type": "line"}]}}]} + When the request is sent + Then the response status is 200 OK + And the response "widgets[0].definition.requests[0].style.order_by" is equal to "values" + And the response "widgets[0].definition.requests[0].style.palette" is equal to "warm" + @team:DataDog/dashboards-backend Scenario: Create a new dashboard with timeseries widget with custom_unit Given new "CreateDashboard" request @@ -958,6 +976,16 @@ Feature: Dashboards And the response "widgets[0].definition.requests[0].formulas[0].number_format.unit.type" is equal to "canonical_unit" And the response "widgets[0].definition.requests[0].formulas[0].number_format.unit.unit_name" is equal to "fraction" + @team:DataDog/dashboards-backend + Scenario: Create a new dashboard with timeseries widget without order_by for backward compatibility + Given new "CreateDashboard" request + And body with value {"layout_type": "ordered", "title": "{{ unique }} without order_by","widgets": [{"definition": {"type": "timeseries","requests": [{"q": "avg:system.cpu.user{*} by {host}","style": {"palette": "dog_classic","line_type": "solid","line_width": "normal"},"display_type": "line"}]}}]} + When the request is sent + Then the response status is 200 OK + And the response "widgets[0].definition.requests[0].style.palette" is equal to "dog_classic" + And the response "widgets[0].definition.requests[0].style.line_type" is equal to "solid" + And the response "widgets[0].definition.requests[0].style.line_width" is equal to "normal" + @team:DataDog/dashboards-backend Scenario: Create a new dashboard with toplist widget Given new "CreateDashboard" request