feat(alerts): adds support for signal_seasonality for NRQL baseline conditions#2844
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2844 +/- ##
==========================================
- Coverage 30.58% 30.55% -0.03%
==========================================
Files 104 104
Lines 28631 28687 +56
==========================================
+ Hits 8756 8765 +9
- Misses 19701 19746 +45
- Partials 174 176 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
df717f0 to
06c81df
Compare
| DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { | ||
| return strings.EqualFold(old, new) // Case fold this attribute when diffing | ||
| // If a value is not provided and the condition uses the default value, don't show a diff. Also case insensitive. | ||
| return (strings.EqualFold(old, "NEW_RELIC_CALCULATION") && new == "") || strings.EqualFold(old, new) |
There was a problem hiding this comment.
Use case for this is:
- User creates a baseline condition with no signal seasonality specified.
- We default to "NEW_RELIC_CALCULATION" in the backend
- User updates a different field, say
enabled - Without this diff suppress function, there would be a diff of
"NEW_RELIC_CALCULATION" ~> nullwhich wouldn't actually doing anything to the condition but it might confuser the user.
|
All is well with the integration tests and lint checks :) (as of the latest commit, 723e61b which references newrelic/newrelic-client-go@8671fd0 in the New Relic Go Client) foreman run go test -v ./newrelic -tags integration -run '^TestAccNewRelicNrqlAlertCondition'integration_test_run_2844_723e61bd4c883184816011344036499a54840155.mov |
|
🚧 |
| ValidateFunc: validation.StringInSlice([]string{"NEW_RELIC_CALCULATION", "HOURLY", "DAILY", "WEEKLY", "NONE"}, true), | ||
| DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { | ||
| // If a value is not provided and the condition uses the default value, don't show a diff. Also case insensitive. | ||
| return (strings.EqualFold(old, "NEW_RELIC_CALCULATION") && new == "") || strings.EqualFold(old, new) | ||
| }, |
There was a problem hiding this comment.
| ValidateFunc: validation.StringInSlice([]string{"NEW_RELIC_CALCULATION", "HOURLY", "DAILY", "WEEKLY", "NONE"}, true), | |
| DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { | |
| // If a value is not provided and the condition uses the default value, don't show a diff. Also case insensitive. | |
| return (strings.EqualFold(old, "NEW_RELIC_CALCULATION") && new == "") || strings.EqualFold(old, new) | |
| }, | |
| ValidateFunc: validation.StringInSlice( | |
| []string{ | |
| string(alerts.NrqlSignalSeasonalities.NewRelicCalculation), | |
| string(alerts.NrqlSignalSeasonalities.Hourly), | |
| string(alerts.NrqlSignalSeasonalities.Daily), | |
| string(alerts.NrqlSignalSeasonalities.Weekly), | |
| string(alerts.NrqlSignalSeasonalities.None), | |
| }, | |
| true, | |
| ), | |
| DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { | |
| // If a value is not provided and the condition uses the default value, don't show a diff. Also case insensitive. | |
| return (strings.EqualFold(old, string(alerts.NrqlSignalSeasonalities.NewRelicCalculation)) && new == "") || strings.EqualFold(old, new) | |
| }, |
There was a problem hiding this comment.
just wanted to replace hard coded references to each of these strings with references in the client as a good practice so as to facilitate easier modifications to the values corresponding to each of these types (if any) in the future :)
| if conditionType == "baseline" { | ||
| if attr, ok := d.GetOk("signal_seasonality"); ok { | ||
| seasonality := alerts.NrqlSignalSeasonality(strings.ToUpper(attr.(string))) | ||
| input.SignalSeasonality = &seasonality | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
| if conditionType == "baseline" { | |
| if attr, ok := d.GetOk("signal_seasonality"); ok { | |
| seasonality := alerts.NrqlSignalSeasonality(strings.ToUpper(attr.(string))) | |
| input.SignalSeasonality = &seasonality | |
| } | |
| } | |
| if conditionType == "baseline" { | |
| if attr, ok := d.GetOk("signal_seasonality"); ok { | |
| seasonality := alerts.NrqlSignalSeasonality(strings.ToUpper(attr.(string))) | |
| input.SignalSeasonality = &seasonality | |
| } else { | |
| seasonality := alerts.NrqlSignalSeasonalities.NewRelicCalculation | |
| input.SignalSeasonality = &seasonality | |
| } | |
| } |
I'll explain why I suggest this modification in the following comment (just under this).
| if conditionType == "baseline" { | ||
| if attr, ok := d.GetOk("signal_seasonality"); ok { | ||
| seasonality := alerts.NrqlSignalSeasonality(strings.ToUpper(attr.(string))) | ||
| input.SignalSeasonality = &seasonality | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
| if conditionType == "baseline" { | |
| if attr, ok := d.GetOk("signal_seasonality"); ok { | |
| seasonality := alerts.NrqlSignalSeasonality(strings.ToUpper(attr.(string))) | |
| input.SignalSeasonality = &seasonality | |
| } | |
| } | |
| if conditionType == "baseline" { | |
| if attr, ok := d.GetOk("signal_seasonality"); ok { | |
| seasonality := alerts.NrqlSignalSeasonality(strings.ToUpper(attr.(string))) | |
| input.SignalSeasonality = &seasonality | |
| } else { | |
| seasonality := alerts.NrqlSignalSeasonalities.NewRelicCalculation | |
| input.SignalSeasonality = &seasonality | |
| } | |
| } |
I'd like to explain why I suggest this change here, and also a similar change in the function handling create (the above comment). While we have handled all discrepancies we've noticed by
- restoring
omitemptywith the discussed datatypes in the client, - introducing a new
NEW_RELIC_CALCULATIONtype instead ofnull(which led to the problem with anomitemptynot existing), and - handling diff suppression in the provider here to suppress diffs if the API returns
NEW_RELIC_CALCULATIONagainstsignal_seasonalitybut the value in the configuration isnull,
one of the downsides I'm seeing with the current code in the provider and the client is the fact that because omitempty is back, it becomes impossible for customers who could have already set a valid signal_seasonality (e.g. DAILY) to remove it entirely (in API terms, move it back to NEW_RELIC_CALCULATION); while the API does this under the hoodbased on what you shared earlier when there is no signalSeasonality in the request, it doesn't seem so since a diff is shown after trying to remove an already configured signal_seasonality = DAILY and performing an apply, which is leaving a diff upon the next plan suggesting that DAILY was never gone.
We can visit more details on why this happens later, but I believe a simpler solution to this problem (as you've implemented everything else like the diff suppression along the lines of this problem :)) is to add an else condition to wherever we're adding signalSeasonality in the create/update handlers, to say that if there is a non-null signal_seasonality in the state, that is picked and sent to the API, else, NEW_RELIC_CALCULATION is sent to the API; by which means "all" baseline conditions created/updated will have a signalSeasonality for sure, which will help keep the experience consistent and prevent such drift - this is basically a way of making NEW_RELIC_CALCULATION the default signal_seasonality on baseline NRQL conditions, unless a different value is specified.
To better understand what I mean, you can try compiling these changes (without my suggestions), try applying an NRQL alert condition with signal_seasonality = DAILY, then removing it and trying to apply again; the expected behaviour of the subsequent plan after this would be to see no drift, but we'd see a drift as I've explained above. You can then add these suggestions, and the drift would be seen.
I'd like you to review if these changes sound apt to you and add them accordingly :)
There was a problem hiding this comment.
This makes sense. I actually did notice this in my testing but I figured that instead of removing the signalSeasonality entirely on update, a user could just set it to NEW_RELIC_CALCULATION which is effectively the same. I didn't think to do this, and I think this is a good idea!
|
|
||
| # baseline type only | ||
| baseline_direction = "upper_only" | ||
| signal_seasonality = "none" |
There was a problem hiding this comment.
how about adding a valid signal_seasonality here like HOURLY or DAILY? @akane0915
There was a problem hiding this comment.
NONE is a valid signal_seasonality but I can update it anyways.
| // Null is equivalent to the default value of `NEW_RELIC_CALCULATION` in the API | ||
| // so this effectively allows the user to null out the signal seasonality on update |
|
Integration tests work fine with the latest changes too. We should be good to proceed as all requested changes have been handled. |
Description
signal_seasonalityfor baseline NRQL conditionsRelated to Go Client PR
Type of change
Please delete options that are not relevant.
Checklist:
Please delete options that are not relevant.
How to test this change?
Please describe how to test your changes. Include any relevant steps in the UI, HCL file(s), commands, etc
newrelic_nrql_alert_conditionof typebaseline.signal_seasonalitysuccessfully.newrelic_nrql_alert_conditionof typestaticwithoutsignal_seasonality.E.g.