From 77078eaa676129f4f3a933e2ed22e0a7db7f39f4 Mon Sep 17 00:00:00 2001 From: "brian.lamb" <5820125+lambcode@users.noreply.github.com> Date: Tue, 21 Nov 2023 15:09:07 -0700 Subject: [PATCH 1/9] Add triggered for durations --- client/metric_conditions.go | 13 +++-- lightstep/resource_alert.go | 9 +++- lightstep/resource_metric_condition.go | 75 ++++++++++++++++++++++---- 3 files changed, 80 insertions(+), 17 deletions(-) diff --git a/client/metric_conditions.go b/client/metric_conditions.go index cb2aa5e7..669caae0 100644 --- a/client/metric_conditions.go +++ b/client/metric_conditions.go @@ -48,14 +48,17 @@ type Expression struct { } type SubAlertExpression struct { - Thresholds Thresholds `json:"thresholds"` - Operand string `json:"operand"` - IsNoData bool `json:"enable-no-data-alert,omitempty"` + Thresholds Thresholds `json:"thresholds"` + Operand string `json:"operand"` + IsNoData bool `json:"enable-no-data-alert,omitempty"` + NoDataDurationMs *uint64 `json:"no-data-duration-ms,omitempty"` } type Thresholds struct { - Warning *float64 `json:"warning,omitempty"` - Critical *float64 `json:"critical,omitempty"` + Warning *float64 `json:"warning,omitempty"` + WarningDurationMs *uint64 `json:"warning-duration-ms,omitempty"` + Critical *float64 `json:"critical,omitempty"` + CriticalDurationMs *uint64 `json:"critical-duration-ms,omitempty"` } type DependencyMapOptions struct { diff --git a/lightstep/resource_alert.go b/lightstep/resource_alert.go index bff24a37..d1dd5db3 100644 --- a/lightstep/resource_alert.go +++ b/lightstep/resource_alert.go @@ -2,6 +2,7 @@ package lightstep import ( "fmt" + "github.com/lightstep/terraform-provider-lightstep/client" ) @@ -52,7 +53,7 @@ func getCompositeAlertFromUnifiedConditionResourceData(compositeAlertIn *client. return nil, err } - subAlerts = append(subAlerts, map[string]interface{}{ + subAlertExpressionMap := map[string]interface{}{ "name": subAlertIn.Name, "title": subAlertIn.Title, "expression": []map[string]interface{}{ @@ -63,7 +64,11 @@ func getCompositeAlertFromUnifiedConditionResourceData(compositeAlertIn *client. }, }, "query": queries, - }) + } + if subAlertIn.Expression.NoDataDurationMs != nil { + subAlertExpressionMap["no_data_duration_ms"] = subAlertIn.Expression.NoDataDurationMs + } + subAlerts = append(subAlerts, map[string]interface{}{}) } return []map[string][]map[string]interface{}{{ diff --git a/lightstep/resource_metric_condition.go b/lightstep/resource_metric_condition.go index 9b19b288..8c4982e0 100644 --- a/lightstep/resource_metric_condition.go +++ b/lightstep/resource_metric_condition.go @@ -338,11 +338,23 @@ func getThresholdSchemaMap() map[string]*schema.Schema { Optional: true, Description: "Defines the threshold for the alert to transition to a Critical (more severe) status.", }, + "critical_duration_ms": { + Type: schema.TypeInt, + Optional: true, + Default: false, + Description: "Critical threshold must be breached for this duration before the status changes.", + }, "warning": { Type: schema.TypeString, Optional: true, Description: "Defines the threshold for the alert to transition to a Warning (less severe) status.", }, + "warning_duration_ms": { + Type: schema.TypeInt, + Optional: true, + Default: false, + Description: "Critical threshold must be breached for this duration before the status changes.", + }, } } @@ -422,6 +434,12 @@ func getCompositeSubAlertExpressionResource() *schema.Resource { Default: false, Description: "If true, a notification is sent when the alert query returns no data. If false, notifications aren't sent in this scenario.", }, + "no_data_duration_ms": { + Type: schema.TypeInt, + Optional: true, + Default: false, + Description: "No data must be seen for this duration before the status changes.", + }, "operand": { Type: schema.TypeString, Optional: true, @@ -678,11 +696,21 @@ func buildSubAlertExpression(singleExpression map[string]interface{}) (*client.S return nil, err } - return &client.SubAlertExpression{ + e := &client.SubAlertExpression{ IsNoData: singleExpression["is_no_data"].(bool), Operand: singleExpression["operand"].(string), Thresholds: thresholds, - }, nil + } + + noDataDuration := singleExpression["no_data_duration_ms"] + if noDataDuration != "" { + d, err := strconv.ParseUint(noDataDuration.(string), 64, strconv.IntSize) + if err != nil { + return e, err + } + e.NoDataDurationMs = &d + } + return e, nil } func buildAlertingRules(alertingRulesIn *schema.Set) ([]client.AlertingRule, error) { @@ -1014,6 +1042,24 @@ func buildThresholds(singleExpression map[string]interface{}) (client.Thresholds t.Warning = &w } + criticalDuration := singleExpression["critical_duration_ms"] + if criticalDuration != "" { + d, err := strconv.ParseUint(criticalDuration.(string), 64, strconv.IntSize) + if err != nil { + return t, err + } + t.CriticalDurationMs = &d + } + + warningDuration := singleExpression["warning_duration_ms"] + if criticalDuration != "" { + d, err := strconv.ParseUint(warningDuration.(string), 64, strconv.IntSize) + if err != nil { + return t, err + } + t.WarningDurationMs = &d + } + return t, nil } @@ -1231,14 +1277,16 @@ func setResourceDataFromUnifiedCondition(project string, c client.UnifiedConditi } if c.Attributes.Expression != nil { - if err := d.Set("expression", []map[string]interface{}{ - { - "is_multi": c.Attributes.Expression.IsMulti, - "is_no_data": c.Attributes.Expression.IsNoData, - "operand": c.Attributes.Expression.Operand, - "thresholds": buildUntypedThresholds(c.Attributes.Expression.Thresholds), - }, - }); err != nil { + expressionMap := map[string]interface{}{ + "is_multi": c.Attributes.Expression.IsMulti, + "is_no_data": c.Attributes.Expression.IsNoData, + "operand": c.Attributes.Expression.Operand, + "thresholds": buildUntypedThresholds(c.Attributes.Expression.Thresholds), + } + if c.Attributes.Expression.NoDataDurationMs != nil { + expressionMap["no_data_duration_ms"] = c.Attributes.Expression.NoDataDurationMs + } + if err := d.Set("expression", expressionMap); err != nil { return fmt.Errorf("unable to set expression resource field: %v", err) } } @@ -1314,6 +1362,13 @@ func buildUntypedThresholds(thresholds client.Thresholds) []map[string]interface if thresholds.Warning != nil { outputMap["warning"] = strconv.FormatFloat(*thresholds.Warning, 'f', -1, 64) } + + if thresholds.CriticalDurationMs != nil { + outputMap["critical_duration_ms"] = thresholds.CriticalDurationMs + } + if thresholds.WarningDurationMs != nil { + outputMap["warning_duration_ms"] = thresholds.WarningDurationMs + } return []map[string]interface{}{ outputMap, } From 03ae9ef6a14598ee37de994fe9b65905541f952d Mon Sep 17 00:00:00 2001 From: "brian.lamb" <5820125+lambcode@users.noreply.github.com> Date: Tue, 21 Nov 2023 16:02:38 -0700 Subject: [PATCH 2/9] add test --- lightstep/resource_alert_test.go | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/lightstep/resource_alert_test.go b/lightstep/resource_alert_test.go index bfb25178..ef22a43b 100644 --- a/lightstep/resource_alert_test.go +++ b/lightstep/resource_alert_test.go @@ -1172,3 +1172,53 @@ resource "lightstep_alert" "composite_diff_test" { }, }) } + +func TestAccAlertWithThresholdDurations(t *testing.T) { + var condition client.UnifiedCondition + + conditionConfig := ` +resource "lightstep_alert" "test" { + project_name = "` + testProject + `" + name = "Too many requests" + + expression { + is_multi = true + is_no_data = true + no_data_duration_ms = 60000 + operand = "above" + thresholds { + critical = 10 + critical_duration_ms = 120000 + warning = 5 + warning_duration_ms = 180000 + } + } + + query { + query_name = "a" + hidden = false + display = "line" + query_string = "metric requests | rate 1h | filter "service_name" == "frontend" | group_by ["method"], mean" + } +} +` + + resourceName := "lightstep_alert.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccMetricConditionDestroy, + Steps: []resource.TestStep{ + { + Config: conditionConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckLightstepAlertExists(resourceName, &condition), + resource.TestCheckResourceAttr(resourceName, "name", "Too many requests"), + resource.TestCheckResourceAttr(resourceName, "expression.0.no_data_duration_ms", "60000"), + resource.TestCheckResourceAttr(resourceName, "expression.0.thresholds.0.warning_duration_ms", "120000"), + resource.TestCheckResourceAttr(resourceName, "expression.0.thresholds.0.critical_duration_ms", "180000"), + ), + }, + }, + }) +} From 2a7db4964f020f7a114444100bc706868818c430 Mon Sep 17 00:00:00 2001 From: Carmody Date: Thu, 21 Dec 2023 12:39:13 -0500 Subject: [PATCH 3/9] change various types and which object is checked for TestAccAlert --- client/metric_conditions.go | 6 +++--- lightstep/resource_metric_condition.go | 29 +++++++++++++------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/client/metric_conditions.go b/client/metric_conditions.go index 669caae0..5454d80b 100644 --- a/client/metric_conditions.go +++ b/client/metric_conditions.go @@ -51,14 +51,14 @@ type SubAlertExpression struct { Thresholds Thresholds `json:"thresholds"` Operand string `json:"operand"` IsNoData bool `json:"enable-no-data-alert,omitempty"` - NoDataDurationMs *uint64 `json:"no-data-duration-ms,omitempty"` + NoDataDurationMs *int `json:"no-data-duration-ms,omitempty"` } type Thresholds struct { Warning *float64 `json:"warning,omitempty"` - WarningDurationMs *uint64 `json:"warning-duration-ms,omitempty"` + WarningDurationMs *int `json:"warning-duration-ms,omitempty"` Critical *float64 `json:"critical,omitempty"` - CriticalDurationMs *uint64 `json:"critical-duration-ms,omitempty"` + CriticalDurationMs *int `json:"critical-duration-ms,omitempty"` } type DependencyMapOptions struct { diff --git a/lightstep/resource_metric_condition.go b/lightstep/resource_metric_condition.go index 8c4982e0..726753d2 100644 --- a/lightstep/resource_metric_condition.go +++ b/lightstep/resource_metric_condition.go @@ -703,9 +703,9 @@ func buildSubAlertExpression(singleExpression map[string]interface{}) (*client.S } noDataDuration := singleExpression["no_data_duration_ms"] - if noDataDuration != "" { - d, err := strconv.ParseUint(noDataDuration.(string), 64, strconv.IntSize) - if err != nil { + if noDataDuration != nil && noDataDuration != "" && noDataDuration != 0 { + d, ok := noDataDuration.(int) + if !ok { return e, err } e.NoDataDurationMs = &d @@ -1042,20 +1042,20 @@ func buildThresholds(singleExpression map[string]interface{}) (client.Thresholds t.Warning = &w } - criticalDuration := singleExpression["critical_duration_ms"] - if criticalDuration != "" { - d, err := strconv.ParseUint(criticalDuration.(string), 64, strconv.IntSize) - if err != nil { - return t, err + criticalDuration := thresholdsObj["critical_duration_ms"] + if criticalDuration != nil && criticalDuration != "" && criticalDuration != 0 { + d, ok := criticalDuration.(int) + if !ok { + return t, fmt.Errorf("unexpected format for critical_duration_ms") } t.CriticalDurationMs = &d } - warningDuration := singleExpression["warning_duration_ms"] - if criticalDuration != "" { - d, err := strconv.ParseUint(warningDuration.(string), 64, strconv.IntSize) - if err != nil { - return t, err + warningDuration := thresholdsObj["warning_duration_ms"] + if warningDuration != nil && warningDuration != "" && criticalDuration != 0 { + d, ok := warningDuration.(int) + if !ok { + return t, fmt.Errorf("unexpected format for warning_duration_ms") } t.WarningDurationMs = &d } @@ -1286,7 +1286,8 @@ func setResourceDataFromUnifiedCondition(project string, c client.UnifiedConditi if c.Attributes.Expression.NoDataDurationMs != nil { expressionMap["no_data_duration_ms"] = c.Attributes.Expression.NoDataDurationMs } - if err := d.Set("expression", expressionMap); err != nil { + expressionSlice := []map[string]interface{}{expressionMap} + if err := d.Set("expression", expressionSlice); err != nil { return fmt.Errorf("unable to set expression resource field: %v", err) } } From 07747989dbd9ea5d4de514c190a5efca99f23aed Mon Sep 17 00:00:00 2001 From: Carmody Date: Thu, 21 Dec 2023 12:39:51 -0500 Subject: [PATCH 4/9] housekeeping: read project name once --- lightstep/resource_metric_condition.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lightstep/resource_metric_condition.go b/lightstep/resource_metric_condition.go index 726753d2..8ed88be9 100644 --- a/lightstep/resource_metric_condition.go +++ b/lightstep/resource_metric_condition.go @@ -542,7 +542,8 @@ func (p *resourceUnifiedConditionImp) resourceUnifiedConditionRead(ctx context.C return diag.FromErr(fmt.Errorf("failed to translate resource attributes: %v", err)) } - cond, err := c.GetUnifiedCondition(ctx, d.Get("project_name").(string), d.Id()) + projectName := d.Get("project_name").(string) + cond, err := c.GetUnifiedCondition(ctx, projectName, d.Id()) if err != nil { apiErr, ok := err.(client.APIResponseCarrier) if !ok { @@ -557,7 +558,6 @@ func (p *resourceUnifiedConditionImp) resourceUnifiedConditionRead(ctx context.C return diag.FromErr(fmt.Errorf("failed to get metric condition: %v", apiErr)) } - projectName := d.Get("project_name").(string) legacy, err := metricConditionHasEquivalentLegacyQueries(ctx, c, projectName, prevAttrs, &cond.Attributes) if err != nil { return diag.FromErr(fmt.Errorf("failed to compare legacy queries: %v", err)) @@ -566,7 +566,8 @@ func (p *resourceUnifiedConditionImp) resourceUnifiedConditionRead(ctx context.C cond.Attributes.Queries = prevAttrs.Queries } - if err := setResourceDataFromUnifiedCondition(d.Get("project_name").(string), *cond, d, p.conditionSchemaType); err != nil { + err = setResourceDataFromUnifiedCondition(projectName, *cond, d, p.conditionSchemaType) + if err != nil { return diag.FromErr(fmt.Errorf("failed to set metric condition from API response to terraform state: %v", err)) } From 22cc7a234fda5f2a901acbb1422bb7c63259d0d2 Mon Sep 17 00:00:00 2001 From: Carmody Date: Thu, 21 Dec 2023 12:40:14 -0500 Subject: [PATCH 5/9] housekeeping: remove include_filters from alerting_rules in tests --- lightstep/resource_alert_test.go | 47 -------------------------------- 1 file changed, 47 deletions(-) diff --git a/lightstep/resource_alert_test.go b/lightstep/resource_alert_test.go index ef22a43b..b6fc9b86 100644 --- a/lightstep/resource_alert_test.go +++ b/lightstep/resource_alert_test.go @@ -62,13 +62,6 @@ resource "lightstep_alert" "test" { alerting_rule { id = lightstep_slack_destination.slack.id update_interval = "1h" - - include_filters = [ - { - key = "project_name" - value = "catlab" - } - ] } } ` @@ -103,13 +96,6 @@ resource "lightstep_alert" "test" { alerting_rule { id = lightstep_slack_destination.slack.id update_interval = "1h" - - include_filters = [ - { - key = "project_name" - value = "catlab" - } - ] } } ` @@ -206,13 +192,6 @@ EOT alerting_rule { id = lightstep_slack_destination.slack.id update_interval = "1h" - - include_filters = [ - { - key = "project_name" - value = "catlab" - } - ] } } `, uqlQuery) @@ -251,13 +230,6 @@ EOT alerting_rule { id = lightstep_slack_destination.slack.id update_interval = "1h" - - include_filters = [ - { - key = "project_name" - value = "catlab" - } - ] } } `, uqlQuery) @@ -553,11 +525,6 @@ EOT alerting_rule { id = lightstep_slack_destination.slack.id update_interval = "1h" - - include_filters = [{ - key = "project_name" - value = "catlab" - }] } } `, uqlQuery) @@ -706,13 +673,6 @@ resource "lightstep_alert" "errors" { alerting_rule { id = lightstep_slack_destination.slack.id update_interval = "1h" - - include_filters = [ - { - key = "project_name" - value = "catlab" - } - ] } } ` @@ -769,13 +729,6 @@ resource "lightstep_alert" "test" { alerting_rule { id = lightstep_slack_destination.slack.id update_interval = "1h" - - include_filters = [ - { - key = "project_name" - value = "catlab" - } - ] } } ` From 7c39eedb9e1735c129e8377f47c12eb365471c49 Mon Sep 17 00:00:00 2001 From: Carmody Date: Thu, 21 Dec 2023 12:44:45 -0500 Subject: [PATCH 6/9] housekeeping: remove check on alerting_rule include_filter --- lightstep/resource_alert_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lightstep/resource_alert_test.go b/lightstep/resource_alert_test.go index b6fc9b86..4128a46b 100644 --- a/lightstep/resource_alert_test.go +++ b/lightstep/resource_alert_test.go @@ -254,10 +254,6 @@ EOT resource.TestCheckResourceAttr(resourceName, "name", "Too many requests"), resource.TestCheckResourceAttr(resourceName, "description", "A link to a playbook"), resource.TestCheckResourceAttr(resourceName, "query.0.query_string", uqlQuery+"\n"), - resource.TestCheckTypeSetElemNestedAttrs(resourceName, "alerting_rule.*", map[string]string{ - "include_filters.0.key": "project_name", - "include_filters.0.value": "catlab", - }), resource.TestCheckResourceAttr(resourceName, "expression.0.is_no_data", "true"), ), }, From 5386279ac745c6cd1d4198cd209447bcd898e56d Mon Sep 17 00:00:00 2001 From: Carmody Date: Tue, 2 Jan 2024 21:25:09 -0700 Subject: [PATCH 7/9] fix composite alerts --- lightstep/resource_alert.go | 2 +- lightstep/resource_metric_condition.go | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lightstep/resource_alert.go b/lightstep/resource_alert.go index d1dd5db3..b94e9dcf 100644 --- a/lightstep/resource_alert.go +++ b/lightstep/resource_alert.go @@ -68,7 +68,7 @@ func getCompositeAlertFromUnifiedConditionResourceData(compositeAlertIn *client. if subAlertIn.Expression.NoDataDurationMs != nil { subAlertExpressionMap["no_data_duration_ms"] = subAlertIn.Expression.NoDataDurationMs } - subAlerts = append(subAlerts, map[string]interface{}{}) + subAlerts = append(subAlerts, subAlertExpressionMap) } return []map[string][]map[string]interface{}{{ diff --git a/lightstep/resource_metric_condition.go b/lightstep/resource_metric_condition.go index 8ed88be9..3e6e7d69 100644 --- a/lightstep/resource_metric_condition.go +++ b/lightstep/resource_metric_condition.go @@ -341,7 +341,6 @@ func getThresholdSchemaMap() map[string]*schema.Schema { "critical_duration_ms": { Type: schema.TypeInt, Optional: true, - Default: false, Description: "Critical threshold must be breached for this duration before the status changes.", }, "warning": { @@ -352,7 +351,6 @@ func getThresholdSchemaMap() map[string]*schema.Schema { "warning_duration_ms": { Type: schema.TypeInt, Optional: true, - Default: false, Description: "Critical threshold must be breached for this duration before the status changes.", }, } @@ -437,7 +435,6 @@ func getCompositeSubAlertExpressionResource() *schema.Resource { "no_data_duration_ms": { Type: schema.TypeInt, Optional: true, - Default: false, Description: "No data must be seen for this duration before the status changes.", }, "operand": { From 9c89360c5abdb0b9736f6d9c4ff0b29c23372a1f Mon Sep 17 00:00:00 2001 From: Carmody Date: Tue, 2 Jan 2024 21:30:27 -0700 Subject: [PATCH 8/9] docs --- docs/resources/alert.md | 6 ++++++ docs/resources/metric_condition.md | 3 +++ 2 files changed, 9 insertions(+) diff --git a/docs/resources/alert.md b/docs/resources/alert.md index db1ec9b2..42219659 100644 --- a/docs/resources/alert.md +++ b/docs/resources/alert.md @@ -110,6 +110,7 @@ Optional: Optional: - `is_no_data` (Boolean) If true, a notification is sent when the alert query returns no data. If false, notifications aren't sent in this scenario. +- `no_data_duration_ms` (Number) No data must be seen for this duration before the status changes. - `operand` (String) Required when at least one threshold (Critical, Warning) is defined. Indicates whether the alert triggers when the value is above the threshold or below the threshold. - `thresholds` (Block List, Max: 1) Optional values defining the thresholds at which this alert transitions into Critical or Warning states. If a particular threshold is not specified, the alert never transitions into that state. (see [below for nested schema](#nestedblock--composite_alert--alert--expression--thresholds)) @@ -119,7 +120,9 @@ Optional: Optional: - `critical` (String) Defines the threshold for the alert to transition to a Critical (more severe) status. +- `critical_duration_ms` (Number) Critical threshold must be breached for this duration before the status changes. - `warning` (String) Defines the threshold for the alert to transition to a Warning (less severe) status. +- `warning_duration_ms` (Number) Critical threshold must be breached for this duration before the status changes. @@ -161,6 +164,7 @@ Optional: - `is_multi` (Boolean) When false, send a single notification whenever any number of group_by values exceeds the alert threshold. When true, send individual notifications for each distinct group_by value that exceeds the threshold. - `is_no_data` (Boolean) If true, a notification is sent when the alert query returns no data. If false, notifications aren't sent in this scenario. +- `no_data_duration_ms` (Number) No data must be seen for this duration before the status changes. - `operand` (String) Required when at least one threshold (Critical, Warning) is defined. Indicates whether the alert triggers when the value is above the threshold or below the threshold. - `thresholds` (Block List, Max: 1) Optional values defining the thresholds at which this alert transitions into Critical or Warning states. If a particular threshold is not specified, the alert never transitions into that state. (see [below for nested schema](#nestedblock--expression--thresholds)) @@ -170,7 +174,9 @@ Optional: Optional: - `critical` (String) Defines the threshold for the alert to transition to a Critical (more severe) status. +- `critical_duration_ms` (Number) Critical threshold must be breached for this duration before the status changes. - `warning` (String) Defines the threshold for the alert to transition to a Warning (less severe) status. +- `warning_duration_ms` (Number) Critical threshold must be breached for this duration before the status changes. diff --git a/docs/resources/metric_condition.md b/docs/resources/metric_condition.md index 74dc1079..a9f1ec5f 100644 --- a/docs/resources/metric_condition.md +++ b/docs/resources/metric_condition.md @@ -120,6 +120,7 @@ Optional: - `is_multi` (Boolean) When false, send a single notification whenever any number of group_by values exceeds the alert threshold. When true, send individual notifications for each distinct group_by value that exceeds the threshold. - `is_no_data` (Boolean) If true, a notification is sent when the alert query returns no data. If false, notifications aren't sent in this scenario. +- `no_data_duration_ms` (Number) No data must be seen for this duration before the status changes. - `operand` (String) Required when at least one threshold (Critical, Warning) is defined. Indicates whether the alert triggers when the value is above the threshold or below the threshold. - `thresholds` (Block List, Max: 1) Optional values defining the thresholds at which this alert transitions into Critical or Warning states. If a particular threshold is not specified, the alert never transitions into that state. (see [below for nested schema](#nestedblock--expression--thresholds)) @@ -129,7 +130,9 @@ Optional: Optional: - `critical` (String) Defines the threshold for the alert to transition to a Critical (more severe) status. +- `critical_duration_ms` (Number) Critical threshold must be breached for this duration before the status changes. - `warning` (String) Defines the threshold for the alert to transition to a Warning (less severe) status. +- `warning_duration_ms` (Number) Critical threshold must be breached for this duration before the status changes. From d46779d9e2f60811eda562dceea9e4cf789df2b1 Mon Sep 17 00:00:00 2001 From: Carmody Date: Tue, 2 Jan 2024 21:50:33 -0700 Subject: [PATCH 9/9] fix test --- lightstep/resource_alert_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lightstep/resource_alert_test.go b/lightstep/resource_alert_test.go index 4128a46b..52121791 100644 --- a/lightstep/resource_alert_test.go +++ b/lightstep/resource_alert_test.go @@ -1137,9 +1137,9 @@ resource "lightstep_alert" "test" { operand = "above" thresholds { critical = 10 - critical_duration_ms = 120000 + critical_duration_ms = 180000 warning = 5 - warning_duration_ms = 180000 + warning_duration_ms = 120000 } } @@ -1147,7 +1147,7 @@ resource "lightstep_alert" "test" { query_name = "a" hidden = false display = "line" - query_string = "metric requests | rate 1h | filter "service_name" == "frontend" | group_by ["method"], mean" + query_string = "metric requests | rate 1h | filter service_name == frontend | group_by [method], mean" } } `