Skip to content

Commit

Permalink
feat(alerts): add support for ignoreOnExpectedTermination in `expir…
Browse files Browse the repository at this point in the history
…ation` to NRQL alert conditions (#1180)
  • Loading branch information
corinnekunze authored Aug 12, 2024
1 parent 9d143de commit 4acfff3
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 5 deletions.
2 changes: 2 additions & 0 deletions pkg/alerts/nrql_conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type AlertsNrqlConditionExpiration struct {
ExpirationDuration *int `json:"expirationDuration"`
CloseViolationsOnExpiration bool `json:"closeViolationsOnExpiration"`
OpenViolationOnExpiration bool `json:"openViolationOnExpiration"`
IgnoreOnExpectedTermination bool `json:"ignoreOnExpectedTermination"`
}

// AlertsNrqlConditionSignal - Configuration that defines the signal that the NRQL condition will use to evaluate.
Expand Down Expand Up @@ -740,6 +741,7 @@ const (
closeViolationsOnExpiration
expirationDuration
openViolationOnExpiration
ignoreOnExpectedTermination
}
signal {
aggregationWindow
Expand Down
109 changes: 104 additions & 5 deletions pkg/alerts/nrql_conditions_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -732,10 +732,10 @@ func TestIntegrationNrqlConditions_DataAccountId(t *testing.T) {
}

var nrqlConditionCreateWithDataAccountId = NrqlConditionCreateBase{
Enabled: true,
Name: fmt.Sprintf("test-nrql-condition-%s", testNrqlConditionRandomString),
Enabled: true,
Name: fmt.Sprintf("test-nrql-condition-%s", testNrqlConditionRandomString),
Nrql: NrqlConditionCreateQuery{
Query: "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
Query: "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
DataAccountId: &testAccountID,
},
Terms: []NrqlConditionTerm{
Expand All @@ -759,8 +759,8 @@ func TestIntegrationNrqlConditions_DataAccountId(t *testing.T) {
}

var (
randStr = mock.RandSeq(5)
createDataAccountIdInput = NrqlConditionCreateInput{
randStr = mock.RandSeq(5)
createDataAccountIdInput = NrqlConditionCreateInput{
NrqlConditionCreateBase: nrqlConditionCreateWithDataAccountId,
}
)
Expand Down Expand Up @@ -797,3 +797,102 @@ func TestIntegrationNrqlConditions_DataAccountId(t *testing.T) {
}
}()
}

func TestIntegrationNrqlConditions_IgnoreOnExpectedTermination(t *testing.T) {
t.Parallel()

testAccountID, err := mock.GetTestAccountID()
if err != nil {
t.Skipf("%s", err)
}

var (
randStr = mock.RandSeq(5)
conditionName = fmt.Sprintf("test-nrql-condition-%s", randStr)
conditionInput = NrqlConditionCreateInput{
NrqlConditionCreateBase: NrqlConditionCreateBase{
Description: "test description",
Enabled: true,
Name: conditionName,
Nrql: NrqlConditionCreateQuery{
Query: "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
},
RunbookURL: "test.com",
Terms: []NrqlConditionTerm{
{
Threshold: &nrqlConditionBaseThresholdZeroValue,
ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
ThresholdDuration: 600,
Operator: AlertsNRQLConditionTermsOperatorTypes.ABOVE,
Priority: NrqlConditionPriorities.Critical,
},
},
Expiration: &AlertsNrqlConditionExpiration{
CloseViolationsOnExpiration: true,
ExpirationDuration: &nrqlConditionBaseExpirationDuration,
OpenViolationOnExpiration: false,
IgnoreOnExpectedTermination: true,
},
ViolationTimeLimitSeconds: 3600,
},
}
updateInput = NrqlConditionUpdateInput{
NrqlConditionUpdateBase: NrqlConditionUpdateBase{
Description: "test description",
Enabled: true,
Name: conditionName,
Nrql: NrqlConditionUpdateQuery{
Query: "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
},
RunbookURL: "test.com",
Terms: []NrqlConditionTerm{
{
Threshold: &nrqlConditionBaseThresholdZeroValue,
ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
ThresholdDuration: 600,
Operator: AlertsNRQLConditionTermsOperatorTypes.ABOVE,
Priority: NrqlConditionPriorities.Critical,
},
},
ViolationTimeLimitSeconds: 3600,
// this part is updated
Expiration: &AlertsNrqlConditionExpiration{
CloseViolationsOnExpiration: true,
ExpirationDuration: &nrqlConditionBaseExpirationDuration,
OpenViolationOnExpiration: false,
IgnoreOnExpectedTermination: false,
},
},
}
)

// Setup
client := newIntegrationTestClient(t)
testPolicy := AlertsPolicyInput{
IncidentPreference: AlertsIncidentPreferenceTypes.PER_POLICY,
Name: fmt.Sprintf("test-alert-policy-%s", randStr),
}
policy, err := client.CreatePolicyMutation(testAccountID, testPolicy)
require.NoError(t, err)

// Test: Create (static condition with expected termination field)
createdCondition, err := client.CreateNrqlConditionStaticMutation(testAccountID, policy.ID, conditionInput)
require.NoError(t, err)
require.NotNil(t, createdCondition)
require.NotNil(t, createdCondition.ID)
require.NotNil(t, createdCondition.PolicyID)
require.NotNil(t, createdCondition.Expiration)
require.Equal(t, true, createdCondition.Expiration.IgnoreOnExpectedTermination)

updatedCondition, err := client.UpdateNrqlConditionStaticMutation(testAccountID, createdCondition.ID, updateInput)
require.NoError(t, err)
require.Equal(t, false, updatedCondition.Expiration.IgnoreOnExpectedTermination)

// Deferred teardown
defer func() {
_, err := client.DeletePolicyMutation(testAccountID, policy.ID)
if err != nil {
t.Logf("error cleaning up alert policy %s (%s): %s", policy.ID, policy.Name, err)
}
}()
}

0 comments on commit 4acfff3

Please sign in to comment.