Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
fix: ProblemEventHandler forwards wrong events (#664)
Browse files Browse the repository at this point in the history
* Send correct events

Signed-off-by: Arthur Pitman <[email protected]>

* Remove redundant comments

Signed-off-by: Arthur Pitman <[email protected]>

* Add basic tests

Signed-off-by: Arthur Pitman <[email protected]>
  • Loading branch information
arthurpitman authored Jan 5, 2022
1 parent 23ddde5 commit 1663b77
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 5 deletions.
7 changes: 2 additions & 5 deletions internal/problem/problem_event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,13 @@ func (eh ProblemEventHandler) HandleEvent() error {
return nil
}

// Log the problem ID and state for better troubleshooting
log.WithFields(
log.Fields{
"PID": eh.event.GetPID(),
"problemId": eh.event.GetProblemID(),
"state": eh.event.GetState(),
}).Info("Received event")

// ignore problem events if they are closed
if eh.event.IsResolved() {
return eh.handleClosedProblemFromDT()
}
Expand All @@ -127,7 +125,7 @@ func (eh ProblemEventHandler) HandleEvent() error {
}

func (eh ProblemEventHandler) handleClosedProblemFromDT() error {
err := eh.sendEvent(NewRemediationTriggeredEventFactory(eh.event))
err := eh.sendEvent(NewProblemClosedEventFactory(eh.event))
if err != nil {
return err
}
Expand All @@ -137,8 +135,7 @@ func (eh ProblemEventHandler) handleClosedProblemFromDT() error {
}

func (eh ProblemEventHandler) handleOpenedProblemFromDT() error {
// Send a sh.keptn.event.${STAGE}.remediation.triggered event
err := eh.sendEvent(NewProblemClosedEventFactory(eh.event))
err := eh.sendEvent(NewRemediationTriggeredEventFactory(eh.event))
if err != nil {
return err
}
Expand Down
99 changes: 99 additions & 0 deletions internal/problem/problem_event_handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package problem

import (
"encoding/json"
"fmt"
"io/ioutil"
"testing"

cloudevents "github.com/cloudevents/sdk-go/v2"
"github.com/keptn-contrib/dynatrace-service/internal/adapter"
"github.com/keptn-contrib/dynatrace-service/internal/keptn"
keptnv2 "github.com/keptn/go-utils/pkg/lib/v0_2_0"
"github.com/stretchr/testify/assert"
)

func TestProblemEventHandler_HandleEvent(t *testing.T) {

tests := []struct {
name string
receivedEvent *cloudevents.Event
expectedEmittedEvent *cloudevents.Event
}{
{
name: "open problem event",
receivedEvent: readCloudEventFromFile("./testdata/open_problem/received_ce.json"),
expectedEmittedEvent: readCloudEventFromFile("./testdata/open_problem/expected_emitted_ce.json"),
},
{
name: "open problem event with tags",
receivedEvent: readCloudEventFromFile("./testdata/open_problem_with_tags/received_ce.json"),
expectedEmittedEvent: readCloudEventFromFile("./testdata/open_problem_with_tags/expected_emitted_ce.json"),
},
{
name: "closed problem event",
receivedEvent: readCloudEventFromFile("./testdata/closed_problem/received_ce.json"),
expectedEmittedEvent: readCloudEventFromFile("./testdata/closed_problem/expected_emitted_ce.json"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

adapter, err := NewProblemAdapterFromEvent(*tt.receivedEvent)
if !assert.NoError(t, err) {
return
}

kClient := &keptnClientMock{}
ph := NewProblemEventHandler(adapter, kClient)

err = ph.HandleEvent()

assert.NoError(t, err)
if assert.EqualValues(t, 1, len(kClient.eventSink)) {
assert.EqualValues(t, tt.expectedEmittedEvent, kClient.eventSink[0])
}
})
}
}

type keptnClientMock struct {
eventSink []*cloudevents.Event
}

func (m *keptnClientMock) GetCustomQueries(project string, stage string, service string) (*keptn.CustomQueries, error) {
panic("GetCustomQueries() should not be needed in this mock!")
}

func (m *keptnClientMock) GetShipyard() (*keptnv2.Shipyard, error) {
panic("GetShipyard() should not be needed in this mock!")
}

func (m *keptnClientMock) SendCloudEvent(factory adapter.CloudEventFactoryInterface) error {
// simulate errors while creating cloud event
if factory == nil {
return fmt.Errorf("missing factory")
}

ce, err := factory.CreateCloudEvent()
if err != nil {
return err
}

m.eventSink = append(m.eventSink, ce)
return nil
}

func readCloudEventFromFile(fileName string) *cloudevents.Event {
fileContent, err := ioutil.ReadFile(fileName)
if err != nil {
panic("could not load local test file: " + fileName)
}

ce := cloudevents.Event{}
err = json.Unmarshal(fileContent, &ce)
if err != nil {
panic("Cannot make cloud event: " + err.Error())
}
return &ce
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"specversion":"1.0","id":"","source":"dynatrace-service","type":"sh.keptn.events.problem","datacontenttype":"application/json","data":{"State":"CLOSED","ProblemID":"P-22013994","ProblemTitle":"Browser monitor global outage","ProblemDetails":{"displayName":"P-22013994","endTime":1641223766597,"hasRootCause":false,"id":"-6478017825120311599_1641223491837V2","impactLevel":"APPLICATION","severityLevel":"AVAILABILITY","startTime":1641223491837,"status":"CLOSED"},"PID":"-6478017825120311599_1641223491837V2","ProblemURL":"https://test.com/#problems/problemdetails;pid=-6478017825120311599_1641223491837V2","ImpactedEntity":"Browser monitor global outage for Synthetic monitor Third Party Monitor","project":"shop","stage":"production","service":"carts","labels":{"Problem URL":"https://test.com/#problems/problemdetails;pid=-6478017825120311599_1641223491837V2"}},"shkeptncontext":"2d363437-3830-4137-b832-353132303331"}
89 changes: 89 additions & 0 deletions internal/problem/testdata/closed_problem/received_ce.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"data": {
"ImpactedEntities": [
{
"entity": "SYNTHETIC_TEST-7DA5E1111C898644",
"name": "Third Party Monitor",
"type": "SYNTHETIC_TEST"
}
],
"ImpactedEntity": "Browser monitor global outage for Synthetic monitor Third Party Monitor",
"KeptnProject": "shop",
"KeptnStage": "production",
"KeptnService": "carts",
"PID": "-6478017825120311599_1641223491837V2",
"ProblemDetails": {
"affectedCounts": {
"APPLICATION": 0,
"ENVIRONMENT": 0,
"INFRASTRUCTURE": 0,
"SERVICE": 0
},
"commentCount": 0,
"displayName": "P-22013994",
"endTime": 1641223766597,
"hasRootCause": false,
"id": "-6478017825120311599_1641223491837V2",
"impactLevel": "APPLICATION",
"rankedEvents": [
{
"affectedSyntheticActions": [
"click on \"Explore the options\""
],
"affectedSyntheticLocations": [
"East"
],
"correlationId": "beecbeb9f0e01479",
"effectiveEntity": "Third Party Monitor",
"endTime": 1641223766597,
"entityId": "SYNTHETIC_TEST-7DA5E1111C898644",
"entityName": "Third Party Monitor",
"eventType": "WEB_CHECK_GLOBAL_OUTAGE",
"impactLevel": "APPLICATION",
"isRootCause": false,
"resourceId": "APPLICATION-0E22A1B967830BCF",
"resourceName": "Third Party Monitor",
"severities": [],
"severityLevel": "AVAILABILITY",
"startTime": 1641223491837,
"status": "CLOSED",
"syntheticErrorType": [
"Validate text match failed"
]
}
],
"rankedImpacts": [
{
"entityId": "SYNTHETIC_TEST-7DA5E1111C898644",
"entityName": "Third Party Monitor",
"eventType": "WEB_CHECK_GLOBAL_OUTAGE",
"impactLevel": "APPLICATION",
"resourceId": "APPLICATION-0E22A1B967830BCF",
"resourceName": "Third Party Monitor",
"severityLevel": "AVAILABILITY"
}
],
"recoveredCounts": {
"APPLICATION": 1,
"ENVIRONMENT": 0,
"INFRASTRUCTURE": 0,
"SERVICE": 0
},
"severityLevel": "AVAILABILITY",
"startTime": 1641223491837,
"status": "CLOSED",
"tagsOfAffectedEntities": []
},
"ProblemID": "P-22013994",
"ProblemTitle": "Browser monitor global outage",
"ProblemURL": "https://test.com/#problems/problemdetails;pid=-6478017825120311599_1641223491837V2",
"State": "RESOLVED"
},
"id": "ed5566ef-8c28-4b23-ad3e-03fc5ee41688",
"source": "dynatrace",
"specversion": "1.0",
"time": "2022-01-03T15:30:27.397Z",
"type": "sh.keptn.events.problem",
"shkeptncontext": "2d363437-3830-4137-b832-353132303331",
"shkeptnspecversion": "0.2.3"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"specversion":"1.0","id":"","source":"dynatrace-service","type":"sh.keptn.event.production.remediation.triggered","datacontenttype":"application/json","data":{"project":"shop","stage":"production","service":"carts","labels":{"Problem URL":"https://example.com"},"problem":{"State":"OPEN","ProblemID":"999","ProblemTitle":"Dynatrace problem notification test run","ProblemDetails":{"displayName":"","endTime":0,"hasRootCause":false,"id":"99999","impactLevel":"","severityLevel":"","startTime":0,"status":""},"PID":"99999","ProblemURL":"https://example.com","ImpactedEntity":"Myhost1, Myservice1","Tags":"testtag1, testtag2"}},"shkeptncontext":"39393939-3920-4020-a020-202020202020"}
36 changes: 36 additions & 0 deletions internal/problem/testdata/open_problem/received_ce.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"data": {
"ImpactedEntities": [
{
"entity": "HOST-XXXXXXXXXXXXX",
"name": "MyHost1",
"type": "HOST"
},
{
"entity": "SERVICE-XXXXXXXXXXXXX",
"name": "MyService1",
"type": "SERVICE"
}
],
"ImpactedEntity": "Myhost1, Myservice1",
"KeptnProject": "shop",
"KeptnStage": "production",
"KeptnService": "carts",
"PID": "99999",
"ProblemDetails": {
"id": "99999"
},
"ProblemID": "999",
"ProblemTitle": "Dynatrace problem notification test run",
"ProblemURL": "https://example.com",
"State": "OPEN",
"Tags": "testtag1, testtag2"
},
"id": "343cd015-72ac-4e10-b241-1136a22e4cd0",
"source": "dynatrace",
"specversion": "1.0",
"time": "2022-01-04T21:58:45.263Z",
"type": "sh.keptn.events.problem",
"shkeptncontext": "39393939-3920-4020-a020-202020202020",
"shkeptnspecversion": "0.2.3"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"specversion":"1.0","id":"","source":"dynatrace-service","type":"sh.keptn.event.production2.remediation.triggered","datacontenttype":"application/json","data":{"project":"shop2","stage":"production2","service":"carts2","labels":{"Problem URL":"https://example.com"},"problem":{"State":"OPEN","ProblemID":"999","ProblemTitle":"Dynatrace problem notification test run","ProblemDetails":{"displayName":"","endTime":0,"hasRootCause":false,"id":"99999","impactLevel":"","severityLevel":"","startTime":0,"status":""},"PID":"99999","ProblemURL":"https://example.com","ImpactedEntity":"Myhost1, Myservice1","Tags":"keptn_project:shop2,keptn_stage:production2,keptn_service:carts2"}},"shkeptncontext":"39393939-3920-4020-a020-202020202020"}
36 changes: 36 additions & 0 deletions internal/problem/testdata/open_problem_with_tags/received_ce.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"data": {
"ImpactedEntities": [
{
"entity": "HOST-XXXXXXXXXXXXX",
"name": "MyHost1",
"type": "HOST"
},
{
"entity": "SERVICE-XXXXXXXXXXXXX",
"name": "MyService1",
"type": "SERVICE"
}
],
"ImpactedEntity": "Myhost1, Myservice1",
"KeptnProject": "shop",
"KeptnStage": "production",
"KeptnService": "carts",
"PID": "99999",
"ProblemDetails": {
"id": "99999"
},
"ProblemID": "999",
"ProblemTitle": "Dynatrace problem notification test run",
"ProblemURL": "https://example.com",
"State": "OPEN",
"Tags": "keptn_project:shop2,keptn_stage:production2,keptn_service:carts2"
},
"id": "343cd015-72ac-4e10-b241-1136a22e4cd0",
"source": "dynatrace",
"specversion": "1.0",
"time": "2022-01-04T21:58:45.263Z",
"type": "sh.keptn.events.problem",
"shkeptncontext": "39393939-3920-4020-a020-202020202020",
"shkeptnspecversion": "0.2.3"
}

0 comments on commit 1663b77

Please sign in to comment.