Skip to content

Commit

Permalink
Add support for forecast options in AlertPolicy (#7926) (#14616)
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <[email protected]>
Co-authored-by: James Edouard <[email protected]>
  • Loading branch information
modular-magician and James Edouard authored May 16, 2023
1 parent 6b01786 commit 3892009
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .changelog/7926.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
monitoring: added `forecast_options` field to `google_monitoring_alert_policy` resource
```
74 changes: 74 additions & 0 deletions google/resource_monitoring_alert_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,31 @@ resource labels, and metric labels. This
field may not exceed 2048 Unicode characters
in length.`,
},
"forecast_options": {
Type: schema.TypeList,
Optional: true,
Description: `When this field is present, the 'MetricThreshold'
condition forecasts whether the time series is
predicted to violate the threshold within the
'forecastHorizon'. When this field is not set, the
'MetricThreshold' tests the current value of the
timeseries against the threshold.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"forecast_horizon": {
Type: schema.TypeString,
Required: true,
Description: `The length of time into the future to forecast
whether a timeseries will violate the threshold.
If the predicted value is found to violate the
threshold, and the violation is observed in all
forecasts made for the Configured 'duration',
then the timeseries is considered to be failing.`,
},
},
},
},
"threshold_value": {
Type: schema.TypeFloat,
Optional: true,
Expand Down Expand Up @@ -1518,6 +1543,8 @@ func flattenMonitoringAlertPolicyConditionsConditionThreshold(v interface{}, d *
flattenMonitoringAlertPolicyConditionsConditionThresholdDenominatorAggregations(original["denominatorAggregations"], d, config)
transformed["duration"] =
flattenMonitoringAlertPolicyConditionsConditionThresholdDuration(original["duration"], d, config)
transformed["forecast_options"] =
flattenMonitoringAlertPolicyConditionsConditionThresholdForecastOptions(original["forecastOptions"], d, config)
transformed["comparison"] =
flattenMonitoringAlertPolicyConditionsConditionThresholdComparison(original["comparison"], d, config)
transformed["trigger"] =
Expand Down Expand Up @@ -1579,6 +1606,23 @@ func flattenMonitoringAlertPolicyConditionsConditionThresholdDuration(v interfac
return v
}

func flattenMonitoringAlertPolicyConditionsConditionThresholdForecastOptions(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["forecast_horizon"] =
flattenMonitoringAlertPolicyConditionsConditionThresholdForecastOptionsForecastHorizon(original["forecastHorizon"], d, config)
return []interface{}{transformed}
}
func flattenMonitoringAlertPolicyConditionsConditionThresholdForecastOptionsForecastHorizon(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenMonitoringAlertPolicyConditionsConditionThresholdComparison(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}
Expand Down Expand Up @@ -2124,6 +2168,13 @@ func expandMonitoringAlertPolicyConditionsConditionThreshold(v interface{}, d tp
transformed["duration"] = transformedDuration
}

transformedForecastOptions, err := expandMonitoringAlertPolicyConditionsConditionThresholdForecastOptions(original["forecast_options"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedForecastOptions); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["forecastOptions"] = transformedForecastOptions
}

transformedComparison, err := expandMonitoringAlertPolicyConditionsConditionThresholdComparison(original["comparison"], d, config)
if err != nil {
return nil, err
Expand Down Expand Up @@ -2233,6 +2284,29 @@ func expandMonitoringAlertPolicyConditionsConditionThresholdDuration(v interface
return v, nil
}

func expandMonitoringAlertPolicyConditionsConditionThresholdForecastOptions(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedForecastHorizon, err := expandMonitoringAlertPolicyConditionsConditionThresholdForecastOptionsForecastHorizon(original["forecast_horizon"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedForecastHorizon); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["forecastHorizon"] = transformedForecastHorizon
}

return transformed, nil
}

func expandMonitoringAlertPolicyConditionsConditionThresholdForecastOptionsForecastHorizon(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandMonitoringAlertPolicyConditionsConditionThresholdComparison(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
Expand Down
63 changes: 58 additions & 5 deletions google/resource_monitoring_alert_policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ import (

func TestAccMonitoringAlertPolicy(t *testing.T) {
testCases := map[string]func(t *testing.T){
"basic": testAccMonitoringAlertPolicy_basic,
"full": testAccMonitoringAlertPolicy_full,
"update": testAccMonitoringAlertPolicy_update,
"mql": testAccMonitoringAlertPolicy_mql,
"log": testAccMonitoringAlertPolicy_log,
"basic": testAccMonitoringAlertPolicy_basic,
"full": testAccMonitoringAlertPolicy_full,
"update": testAccMonitoringAlertPolicy_update,
"mql": testAccMonitoringAlertPolicy_mql,
"log": testAccMonitoringAlertPolicy_log,
"forecast": testAccMonitoringAlertPolicy_forecast,
}

for name, tc := range testCases {
Expand Down Expand Up @@ -181,6 +182,29 @@ func testAccCheckAlertPolicyDestroyProducer(t *testing.T) func(s *terraform.Stat
}
}

func testAccMonitoringAlertPolicy_forecast(t *testing.T) {

alertName := fmt.Sprintf("tf-test-%s", RandString(t, 10))
conditionName := fmt.Sprintf("tf-test-%s", RandString(t, 10))
filter := `metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\"`

VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckAlertPolicyDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccMonitoringAlertPolicy_forecastCfg(alertName, conditionName, "ALIGN_RATE", filter),
},
{
ResourceName: "google_monitoring_alert_policy.forecast",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner, filter string) string {
return fmt.Sprintf(`
resource "google_monitoring_alert_policy" "basic" {
Expand Down Expand Up @@ -335,3 +359,32 @@ resource "google_monitoring_alert_policy" "log" {
}
`, alertName, conditionName)
}

func testAccMonitoringAlertPolicy_forecastCfg(alertName, conditionName, aligner, filter string) string {
return fmt.Sprintf(`
resource "google_monitoring_alert_policy" "forecast" {
display_name = "%s"
enabled = true
combiner = "OR"
conditions {
display_name = "%s"
condition_threshold {
aggregations {
alignment_period = "60s"
per_series_aligner = "%s"
}
duration = "60s"
forecast_options {
forecast_horizon = "3600s"
}
comparison = "COMPARISON_GT"
filter = "%s"
threshold_value = "0.5"
}
}
}
`, alertName, conditionName, aligner, filter)
}
49 changes: 49 additions & 0 deletions website/docs/r/monitoring_alert_policy.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,34 @@ resource "google_monitoring_alert_policy" "alert_policy" {
}
}
```
## Example Usage - Monitoring Alert Policy Forecast Options


```hcl
resource "google_monitoring_alert_policy" "alert_policy" {
display_name = "My Alert Policy"
combiner = "OR"
conditions {
display_name = "test condition"
condition_threshold {
filter = "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\""
duration = "60s"
forecast_options {
forecast_horizon = "3600s"
}
comparison = "COMPARISON_GT"
aggregations {
alignment_period = "60s"
per_series_aligner = "ALIGN_RATE"
}
}
}
user_labels = {
foo = "bar"
}
}
```

## Argument Reference

Expand Down Expand Up @@ -427,6 +455,16 @@ The following arguments are supported:
that unhealthy states are detected and
alerted on quickly.

* `forecast_options` -
(Optional)
When this field is present, the `MetricThreshold`
condition forecasts whether the time series is
predicted to violate the threshold within the
`forecastHorizon`. When this field is not set, the
`MetricThreshold` tests the current value of the
timeseries against the threshold.
Structure is [documented below](#nested_forecast_options).

* `comparison` -
(Required)
The comparison to apply between the time
Expand Down Expand Up @@ -580,6 +618,17 @@ The following arguments are supported:
returned.
Possible values are: `REDUCE_NONE`, `REDUCE_MEAN`, `REDUCE_MIN`, `REDUCE_MAX`, `REDUCE_SUM`, `REDUCE_STDDEV`, `REDUCE_COUNT`, `REDUCE_COUNT_TRUE`, `REDUCE_COUNT_FALSE`, `REDUCE_FRACTION_TRUE`, `REDUCE_PERCENTILE_99`, `REDUCE_PERCENTILE_95`, `REDUCE_PERCENTILE_50`, `REDUCE_PERCENTILE_05`.

<a name="nested_forecast_options"></a>The `forecast_options` block supports:

* `forecast_horizon` -
(Required)
The length of time into the future to forecast
whether a timeseries will violate the threshold.
If the predicted value is found to violate the
threshold, and the violation is observed in all
forecasts made for the Configured `duration`,
then the timeseries is considered to be failing.

<a name="nested_trigger"></a>The `trigger` block supports:

* `percent` -
Expand Down

0 comments on commit 3892009

Please sign in to comment.