From e4486dd6dd86acdc5886e28165ebac667babcd6d Mon Sep 17 00:00:00 2001 From: vinay-newrelic Date: Wed, 25 Sep 2024 08:42:07 +0530 Subject: [PATCH] feat(dashboards): adds support for `data_format` to the `newrelic_one_dashboard` resource (#2747) Co-authored-by: pranav-new-relic --- go.mod | 2 +- go.sum | 4 +- newrelic/resource_newrelic_one_dashboard.go | 34 +++++ .../resource_newrelic_one_dashboard_test.go | 9 +- newrelic/structures_newrelic_one_dashboard.go | 109 +++++++++++++++ website/docs/r/api_access_key.html.markdown | 2 +- website/docs/r/one_dashboard.html.markdown | 129 ++++++++++++++++-- 7 files changed, 270 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 26f1b08c2..2649f915c 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/newrelic/go-agent/v3 v3.30.0 github.com/newrelic/go-insights v1.0.3 - github.com/newrelic/newrelic-client-go/v2 v2.45.0 + github.com/newrelic/newrelic-client-go/v2 v2.46.0 github.com/stretchr/testify v1.9.0 golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 ) diff --git a/go.sum b/go.sum index 065b3210d..99fb0c6b7 100644 --- a/go.sum +++ b/go.sum @@ -270,8 +270,8 @@ github.com/newrelic/go-agent/v3 v3.30.0 h1:ZXHCT/Cot4iIPwcegCZURuRQOsfmGA6wilW+S github.com/newrelic/go-agent/v3 v3.30.0/go.mod h1:9utrgxlSryNqRrTvII2XBL+0lpofXbqXApvVWPpbzUg= github.com/newrelic/go-insights v1.0.3 h1:zSNp1CEZnXktzSIEsbHJk8v6ZihdPFP2WsO/fzau3OQ= github.com/newrelic/go-insights v1.0.3/go.mod h1:A20BoT8TNkqPGX2nS/Z2fYmKl3Cqa3iKZd4whzedCY4= -github.com/newrelic/newrelic-client-go/v2 v2.45.0 h1:3zaJqE4V2n07b8Fx3byV+WeJSdeTeR4sW6yVSXrrNN4= -github.com/newrelic/newrelic-client-go/v2 v2.45.0/go.mod h1:pDFY24/6iIMEbPIdowTRrRn9YYwkXc3j+B+XpTb4oF4= +github.com/newrelic/newrelic-client-go/v2 v2.46.0 h1:J1dKQFRKfQJQQFbP4EQGRs6JsYL20gXJxRmTjXLuB9E= +github.com/newrelic/newrelic-client-go/v2 v2.46.0/go.mod h1:pDFY24/6iIMEbPIdowTRrRn9YYwkXc3j+B+XpTb4oF4= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= diff --git a/newrelic/resource_newrelic_one_dashboard.go b/newrelic/resource_newrelic_one_dashboard.go index 5ceeaa45a..926d89a7c 100644 --- a/newrelic/resource_newrelic_one_dashboard.go +++ b/newrelic/resource_newrelic_one_dashboard.go @@ -331,6 +331,12 @@ func dashboardWidgetSchemaBase() map[string]*schema.Schema { MinItems: 1, Elem: dashboardWidgetInitialSortingSchemaElem(), }, + "data_format": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + Elem: dashboardWidgetDataFormatSchemaElem(), + }, "ignore_time_range": { Type: schema.TypeBool, Optional: true, @@ -456,6 +462,7 @@ func dashboardWidgetNullValuesSchemaElem() *schema.Resource { }, } } + func dashboardWidgetInitialSortingSchemaElem() *schema.Resource { return &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -473,6 +480,33 @@ func dashboardWidgetInitialSortingSchemaElem() *schema.Resource { } } +func dashboardWidgetDataFormatSchemaElem() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "The column name to be sorted", + }, + "type": { + Type: schema.TypeString, + Required: true, + Description: "Defines the type of the mentioned column", + }, + "format": { + Type: schema.TypeString, + Optional: true, + Description: "Defines the format of the mentioned type", + }, + "precision": { + Type: schema.TypeInt, + Optional: true, + Description: "The precision of the type", + }, + }, + } +} + // dashboardWidgetNRQLQuerySchemaElem defines a NRQL query for use on a dashboard // // see: newrelic/newrelic-client-go/pkg/entities/DashboardWidgetQuery diff --git a/newrelic/resource_newrelic_one_dashboard_test.go b/newrelic/resource_newrelic_one_dashboard_test.go index 522bcf714..0bb6d8eff 100644 --- a/newrelic/resource_newrelic_one_dashboard_test.go +++ b/newrelic/resource_newrelic_one_dashboard_test.go @@ -670,7 +670,10 @@ func testAccCheckNewRelicOneDashboardConfig_PageFull(pageName string, accountID nrql_query { query = "FROM Transaction SELECT count(*)" } - + data_format { + name = "count" + type = "decimal" + } warning = 0 critical = 2 } @@ -782,6 +785,10 @@ func testAccCheckNewRelicOneDashboardConfig_PageFull(pageName string, accountID direction = "desc" name = "appName" } + data_format { + name = "Avg duration" + type = "decimal" + } } widget_json { diff --git a/newrelic/structures_newrelic_one_dashboard.go b/newrelic/structures_newrelic_one_dashboard.go index 8dba57e01..089429d17 100644 --- a/newrelic/structures_newrelic_one_dashboard.go +++ b/newrelic/structures_newrelic_one_dashboard.go @@ -7,6 +7,7 @@ import ( "fmt" "log" "reflect" + "slices" "strconv" "strings" @@ -242,6 +243,8 @@ func expandDashboardPageInput(d *schema.ResourceData, pages []interface{}, meta // Set thresholds rawConfiguration.Thresholds = expandDashboardBillboardWidgetConfigurationInput(d, v.(map[string]interface{}), meta, pageIndex, widgetIndex) + // Set data formatting + rawConfiguration.DataFormat = expandDashboardTableWidgetConfigDataFormatInput(v.(map[string]interface{})) widget.RawConfiguration, err = json.Marshal(rawConfiguration) if err != nil { @@ -377,6 +380,8 @@ func expandDashboardPageInput(d *schema.ResourceData, pages []interface{}, meta rawConfiguration.Thresholds = expandDashboardTableWidgetConfigurationThresholdInput(d, pageIndex, widgetIndex) // Set initalSorting rawConfiguration.InitialSorting = expandDashboardTableWidgetConfigInitialSortingInput(v.(map[string]interface{})) + // Set data formatting + rawConfiguration.DataFormat = expandDashboardTableWidgetConfigDataFormatInput(v.(map[string]interface{})) widget.RawConfiguration, err = json.Marshal(rawConfiguration) if err != nil { @@ -571,6 +576,38 @@ func expandDashboardTableWidgetConfigInitialSortingInput(w map[string]interface{ return nil } +func expandDashboardTableWidgetConfigDataFormatInput(w map[string]interface{}) []*dashboards.DashboardWidgetDataFormat { + var tableWidgetDataFormat []*dashboards.DashboardWidgetDataFormat + if q, ok := w["data_format"]; ok { + for _, v := range q.([]interface{}) { + dashboardDatFormatMap := v.(map[string]interface{}) + + var dataFormat dashboards.DashboardWidgetDataFormat + + if t, ok := dashboardDatFormatMap["type"]; ok { + dataFormat.Type = t.(string) + } + + if n, ok := dashboardDatFormatMap["name"]; ok { + dataFormat.Name = n.(string) + } + + if f, ok := dashboardDatFormatMap["format"]; ok { + dataFormat.Format = f.(string) + } + + if p, ok := dashboardDatFormatMap["precision"]; ok { + dataFormat.Precision = p.(int) + } + + tableWidgetDataFormat = append(tableWidgetDataFormat, &dataFormat) + } + return tableWidgetDataFormat + } + + return nil +} + func expandDashboardTableWidgetConfigurationThresholdInput(d *schema.ResourceData, pageIndex int, widgetIndex int) []dashboards.DashboardTableWidgetThresholdInput { // initialize an object of []DashboardTableWidgetThresholdInput, which would include a list of tableWidgetThresholdsToBeAdded as specified // in the Terraform configuration, with the attribute "threshold" in table widgets @@ -1286,6 +1323,14 @@ func flattenDashboardWidget(in *entities.DashboardWidget, pageGUID string) (stri } } } + + if rawCfg.DataFormat != nil { + dataformat := flattenDashboardWidgetDataFormat(rawCfg.DataFormat) + if len(dataformat) > 0 { + out["data_format"] = dataformat + } + } + case "viz.bullet": widgetType = "widget_bullet" out["limit"] = rawCfg.Limit @@ -1347,6 +1392,13 @@ func flattenDashboardWidget(in *entities.DashboardWidget, pageGUID string) (stri } } + if rawCfg.DataFormat != nil { + dataformat := flattenDashboardWidgetDataFormat(rawCfg.DataFormat) + if len(dataformat) > 0 { + out["data_format"] = dataformat + } + } + if rawCfg.Thresholds != nil { thresholds := flattenDashboardTableWidgetThresholds(rawCfg.Thresholds) if thresholds != nil { @@ -1373,6 +1425,22 @@ func flattenDashboardWidgetInitialSorting(in *dashboards.DashboardWidgetInitialS return out } +func flattenDashboardWidgetDataFormat(in []*dashboards.DashboardWidgetDataFormat) []interface{} { + out := make([]interface{}, len(in)) + + for i, v := range in { + k := make(map[string]interface{}) + + k["name"] = v.Name + k["type"] = v.Type + k["format"] = v.Format + k["precision"] = v.Precision + out[i] = k + } + + return out +} + func flattenDashboardWidgetNRQLQuery(in *[]dashboards.DashboardWidgetNRQLQueryInput) []interface{} { out := make([]interface{}, len(*in)) @@ -1644,6 +1712,8 @@ func validateDashboardArguments(ctx context.Context, d *schema.ResourceDiff, met validateThresholdFields(d, &errorsList, "widget_table") validateThresholdFields(d, &errorsList, "widget_line") + validateWidgetDataFormatterStructure(d, &errorsList, "widget_table") + validateWidgetDataFormatterStructure(d, &errorsList, "widget_billboard") // add any other validation functions here if len(errorsList) == 0 { @@ -1721,3 +1791,42 @@ func validateThresholdFields(d *schema.ResourceDiff, errorsList *[]string, widge } } + +func validateWidgetDataFormatterStructure(d *schema.ResourceDiff, errorsList *[]string, widgetType string) { + _, pagesListObtained := d.GetChange("page") + pages := pagesListObtained.([]interface{}) + for _, p := range pages { + page := p.(map[string]interface{}) + widget, widgetOk := page[widgetType] + if widgetOk { + for _, w := range widget.([]interface{}) { + widget := w.(map[string]interface{}) + dataFormats, dataFormatsOk := widget["data_format"] + if dataFormatsOk { + + for _, t := range dataFormats.([]interface{}) { + dataFormat := t.(map[string]interface{}) + acceptedTypes := []string{"duration", "recent-relative"} + if dataFormat["type"] != nil && (dataFormat["format"] != nil || dataFormat["format"] != "") { + if dataFormat["format"] != "" && slices.Contains(acceptedTypes, dataFormat["type"].(string)) { + *errorsList = append(*errorsList, fmt.Sprintf("'format' should not be provided if 'type' has the value %s", dataFormat["type"])) + } + } + if dataFormat["type"] != nil && dataFormat["precision"] != 0 { + if dataFormat["precision"] != "" && slices.Contains(acceptedTypes, dataFormat["type"].(string)) { + *errorsList = append(*errorsList, fmt.Sprintf("'precision' should not be provided if 'type' has the value %s", dataFormat["type"])) + } + } + + if dataFormat["type"] != nil && dataFormat["format"] != 0 { + if dataFormat["type"].(string) == "date" && dataFormat["format"] != "" { + log.Printf("[WARN] 'type' should be set as 'custom' if format needs to be applied.") + } + } + } + } + } + } + + } +} diff --git a/website/docs/r/api_access_key.html.markdown b/website/docs/r/api_access_key.html.markdown index ddce3dd26..6f340b080 100644 --- a/website/docs/r/api_access_key.html.markdown +++ b/website/docs/r/api_access_key.html.markdown @@ -67,4 +67,4 @@ $ terraform import newrelic_api_access_key.foobar "1234567:INGEST" ## Extended Usage This module may be used to create a user or ingest key using the `create_access_keys_service` resource, and fetch the created key using `fetch_access_keys_service`, by performing a NerdGraph query under the hood, using the ID of the key created via the resource to fetch the created key. Please refer -[create access keys and fetch access keys](https://github.com/newrelic/terraform-provider-newrelic/blob/main/examples/modules/golden-signal-alerts-new/README.md) for more info. \ No newline at end of file +[create access keys and fetch access keys](https://github.com/newrelic/terraform-provider-newrelic/blob/main/examples/modules/newrelic_api_access_key_extended/README.md) for more info. \ No newline at end of file diff --git a/website/docs/r/one_dashboard.html.markdown b/website/docs/r/one_dashboard.html.markdown index acf572919..c5622b976 100644 --- a/website/docs/r/one_dashboard.html.markdown +++ b/website/docs/r/one_dashboard.html.markdown @@ -36,6 +36,11 @@ resource "newrelic_one_dashboard" "exampledash" { direction = "desc" name = "timestamp" } + + data_format { + name = "duration" + type = "decimal" + } } widget_billboard { @@ -46,6 +51,11 @@ resource "newrelic_one_dashboard" "exampledash" { height = 3 refresh_rate = 60000 // 60 seconds + + data_format { + name = "rate" + type = "recent-relative" + } nrql_query { query = "FROM Transaction SELECT rate(count(*), 1 minute)" @@ -300,30 +310,31 @@ All nested `widget` blocks support the following common arguments: Each widget type supports an additional set of arguments: * `widget_area` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `widget_bar` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `linked_entity_guids`: (Optional) Related entity GUIDs. Currently only supports Dashboard entity GUIDs. * `filter_current_dashboard`: (Optional) Use this item to filter the current dashboard. * `widget_billboard` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `critical` - (Optional) Threshold above which the displayed value will be styled with a red color. * `warning` - (Optional) Threshold above which the displayed value will be styled with a yellow color. + * `data_format` - (Optional) A nested block that describes data format. See [Nested data_format blocks](#nested-data_format-blocks) below for details. * `widget_bullet` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `limit` - (Required) Visualization limit for the widget. * `widget_funnel` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `widget_json` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `widget_heatmap` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `linked_entity_guids`: (Optional) Related entity GUIDs. Currently only supports Dashboard entity GUIDs. * `filter_current_dashboard`: (Optional) Use this item to filter the current dashboard. * `widget_histogram` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `widget_line` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `y_axis_left_zero` - (Optional) An attribute that specifies if the values on the graph to be rendered need to be fit to scale, or printed within the specified range from `y_axis_left_min` (or 0 if it is not defined) to `y_axis_left_max`. Use `y_axis_left_zero = true` with a combination of `y_axis_left_min` and `y_axis_left_max` to render values from 0 or the specified minimum to the maximum, and `y_axis_left_zero = false` to fit the graph to scale. * `y_axis_right` - (Optional) An attribute which helps specify the configuration of the Y-Axis displayed on the right side of the line widget. This is a nested block, which includes the following attributes: * `y_axis_right_zero` - (Optional) An attribute that specifies if the values on the graph to be rendered need to be fit to scale, or printed within the specified range from `y_axis_right_min` (or 0 if it is not defined) to `y_axis_right_max`. Use `y_axis_right_zero = true` with a combination of `y_axis_right_min` and `y_axis_right_max` to render values from 0 or the specified minimum to the maximum, and `y_axis_right_zero = false` to fit the graph to scale. @@ -338,15 +349,15 @@ Each widget type supports an additional set of arguments: * `widget_markdown`: * `text` - (Required) The markdown source to be rendered in the widget. * `widget_stacked_bar` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `widget_pie` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `linked_entity_guids`: (Optional) Related entity GUIDs. Currently only supports Dashboard entity GUIDs. * `filter_current_dashboard`: (Optional) Use this item to filter the current dashboard. * `widget_log_table` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `widget_table` - * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) below for details. + * `nrql_query` - (Required) A nested block that describes a NRQL Query. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) below for details. * `linked_entity_guids`: (Optional) Related entity GUIDs. Currently only supports Dashboard entity GUIDs. * `filter_current_dashboard`: (Optional) Use this item to filter the current dashboard. * `threshold` - (Optional) An attribute that helps specify multiple thresholds, each inclusive of a range of values between which the threshold would need to function, the name of the threshold and its severity. Multiple thresholds can be defined in a table widget. The `threshold` attribute requires specifying the following attributes in a nested block - @@ -357,7 +368,97 @@ Each widget type supports an additional set of arguments: * `initial_sorting` - (Optional) An attribute that describes the sorting mechanism for the table. This attribute requires specifying the following attributes in a nested block - * `name` - (Required) The name of column to be sorted. Examples of few valid values are `timestamp`, `appId`, `appName`, etc. * `direction` - (Required) Defines the sort order. Accepted values are `asc` for ascending or `desc` for descending. + * `data_format` - (Optional) A nested block that describes data format. See [Nested data_format blocks](#nested-data_format-blocks) below for details. + + +### Nested `data_format` blocks + +Nested `data_format` blocks help specify the format of data displayed by a widget per attribute in the data returned by the NRQL query rendering the widget; thereby defining how the data fetched is best interpreted. This is supported for **billboards** and **tables**, as these are the only widgets in dashboards which return single or multi-faceted data that may be formatted based on the type of data returned. +This attribute requires specifying the following attributes in a nested block - + + * `name` - (Required) This attribute mandates the specification of the column name to be formatted. It identifies which column the data format should be applied to. + * `type` - (Required) This attribute sets the format category for your data. Accepted values include - + - `decimal` for numeric values + - `date` for date/time values + - `duration` for length of time + - `recent-relative` for values referencing a relative point in time + - `custom` to be used with date/time values, in order to select a specific format the date/time value would need to be rendered as + - `humanized` to be used with numeric values, in order to enable Autoformat + * `format` - (Optional) This attribute is provided when the `name` is that of a column comprising date/time values and the `type` attribute is set to `custom` defining the specific date format to be applied to your data. + + | Accepted value | Format | + |---------------------|-------------------------| + | `%b %d, %Y` | `MMM DD,YYYY` | + | `%d/%m/%Y` | `DD/MM/YYYY(EU)` | + | `%x` | `DD/MM/YYYY(USA)` | + | `%I:%M%p` | `12-hour format` | + | `%H:%Mh` | `24-hour format` | + | `%H:%Mh UTC (%Z)` | `24-hour with timezone` | + | `%Y-%m-%dT%X.%L%Z` | `ISO with timezone` | + | `%b %d, %Y, %X` | `MMM DD, YYYY,hh:mm:ss` | + | `%X` | `hh:mm:ss` | + + + * `precision` - (Optional) This attribute is utilized when the `type` attribute is set to `decimal`, stipulating the precise number of digits after the decimal point for your data. + +-> **IMPORTANT!** + As specified in the description of arguments of `data_format` above, using certain arguments requires using a specific `type` with the arguments, on a case-to-case basis. Please see the examples below for more details on such argument combinations. + +* The following example illustrates using `data_format{}` with values of type `duration`, `recent-relative` and `timestamp` with no additional arguments specified. +```hcl + widget_table { + title = "List of Transactions" + row = 1 + column = 4 + width = 6 + height = 3 + + nrql_query { + account_id = Account_ID + query = "SELECT average(duration), max(duration), min(duration) FROM Transaction FACET name SINCE 1 day ago" + } + + data_format { + name = "Max duration" + Type = "duration" + } + + data_format { + name = "Max duration" + type = "recent-relative" + } + initial_sorting { + direction = "desc" + name = "timestamp" + } +} +``` +* In order to add a `data_format` block for date/time values, the `type` would need to be set to `date`. However, if you would also like to specify a format of the date/time value (with the `format` argument), the type would need to be set to `custom`. +```hcl + data_format { + name = "timestamp" + Type = "date" + } + + data_format { + name = "timestamp" + Type = "custom" + Format = "%Y-%m-%dT%X.%L%Z" + } +``` +* Similarly, in order to use `data_format{}` with numeric values, the `type` would be need to set to `decimal`. The `precision` of the value may also be specified with type `decimal`. However, in order to have "Autoformat" enabled on the numeric value, specify the type as `humanized`. +```hcl + data_format { + name = "count" + type = "decimal" + precision = 4 + } + data_format { + name = "count" + type = "humanized" + } +``` ### Nested `nrql_query` blocks @@ -395,7 +496,7 @@ The following arguments are supported: * `is_multi_selection` - (Optional) Indicates whether this variable supports multiple selection or not. Only applies to variables of type `nrql` or `enum`. * `item` - (Optional) List of possible values for variables of type `enum`. See [Nested item blocks](#nested-item-blocks) below for details. * `name` - (Required) The variable identifier. - * `nrql_query` - (Optional) Configuration for variables of type `nrql`. See [Nested nrql\_query blocks](#nested-nrql-query-blocks) for details. + * `nrql_query` - (Optional) Configuration for variables of type `nrql`. See [Nested nrql\_query blocks](#nested-nrql_query-blocks) for details. * `replacement_strategy` - (Optional) Indicates the strategy to apply when replacing a variable in a NRQL query. One of `default`, `identifier`, `number` or `string`. * `title` - (Optional) Human-friendly display string for this variable. * `type` - (Required) Specifies the data type of the variable and where its possible values may come from. One of `enum`, `nrql` or `string`