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

Commit

Permalink
Add PagerDuty support package (#1)
Browse files Browse the repository at this point in the history
* Add PagerDuty code

* Adding files

* remove test file

* go fmt

* Address PR comments

* Add new files

* remove api key

* Add comments

* move function around

* Fix tests

* Add pagerduty test for details

* json marshal test detail struct

* Edit comment

* Pointer receiver

* Address PR comments
  • Loading branch information
Le Cheng Fan authored and nikhilsaraf committed Oct 24, 2018
1 parent 9e9a804 commit 5e46ae0
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ vendor/
.vscode/
build/
bin/
.idea
6 changes: 6 additions & 0 deletions api/alert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package api

// Alert interface is used for the various monitoring and alerting tools for Kelp.
type Alert interface {
Trigger(description string, details interface{}) error
}
6 changes: 6 additions & 0 deletions cmd/trade.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/lightyeario/kelp/model"
"github.com/lightyeario/kelp/plugins"
"github.com/lightyeario/kelp/support/monitoring"
"github.com/lightyeario/kelp/support/utils"
"github.com/lightyeario/kelp/trader"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -74,6 +75,10 @@ func init() {
HTTP: http.DefaultClient,
}

alert, e := monitoring.MakeAlert(botConfig.ALERT_TYPE, botConfig.ALERT_API_KEY)
if e != nil {
log.Printf("Unable to set up monitoring for alert type '%s' with the given API key\n", botConfig.ALERT_TYPE)
}
// --- start initialization of objects ----
sdex := plugins.MakeSDEX(
client,
Expand Down Expand Up @@ -105,6 +110,7 @@ func init() {
strat,
botConfig.TICK_INTERVAL_SECONDS,
dataKey,
alert,
)
// --- end initialization of objects ---

Expand Down
10 changes: 8 additions & 2 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ import:
- clients/horizon
- support/config
- support/errors
- package: github.com/PagerDuty/go-pagerduty
version: 635c5ce271490fba94880e62cde4eea3c1c184b9
17 changes: 17 additions & 0 deletions support/monitoring/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package monitoring

import (
"fmt"

"github.com/lightyeario/kelp/api"
)

// MakeAlert creates an Alert based on the type of the service (eg Pager Duty) and its corresponding API key.
func MakeAlert(alertType string, apiKey string) (api.Alert, error) {
switch alertType {
case "PagerDuty":
return makePagerDuty(apiKey)
default:
return nil, fmt.Errorf("cannot make alert - invalid alert type: %s", alertType)
}
}
39 changes: 39 additions & 0 deletions support/monitoring/pagerDuty.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package monitoring

import (
"fmt"
"log"

"github.com/PagerDuty/go-pagerduty"
"github.com/lightyeario/kelp/api"
)

type pagerDuty struct {
serviceKey string
}

// ensure pagerDuty implements the api.Alert interface
var _ api.Alert = &pagerDuty{}

func makePagerDuty(serviceKey string) (api.Alert, error) {
return &pagerDuty{
serviceKey: serviceKey,
}, nil
}

// Trigger creates a PagerDuty trigger. The description is required and cannot be empty. Supplementary
// details can be optionally provided as key-value pairs as part of the details parameter.
func (p *pagerDuty) Trigger(description string, details interface{}) error {
event := pagerduty.Event{
ServiceKey: p.serviceKey,
Type: "trigger",
Description: description,
Details: details,
}
response, e := pagerduty.CreateEvent(event)
if e != nil {
return fmt.Errorf("encountered an error while sending a PagerDuty alert: %s", e)
}
log.Printf("Triggered PagerDuty alert. Incident key for reference: %s\n", response.IncidentKey)
return nil
}
69 changes: 69 additions & 0 deletions support/monitoring/pagerDuty_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package monitoring

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestTriggerPagerDuty(t *testing.T) {
const kelpServiceKey = "" // Fill in pager duty service key here during testing.
testCases := []struct {
testName string
serviceKey string
description string
details interface{}
errorExpected bool
}{
{
testName: "Tests that a Pager Duty alert was triggered successfully",
serviceKey: kelpServiceKey,
description: "Testing monitoring package. Not a real incident!",
details: nil,
errorExpected: false,
},
// Description cannot be empty
{
testName: "Tests that a missing description causes an error",
serviceKey: kelpServiceKey,
description: "",
details: nil,
errorExpected: true,
},
// Service key is invalid
{
testName: "Tests that an invalid API key causes an error",
serviceKey: "",
description: "Testing monitoring package. Not a real incident!",
details: nil,
errorExpected: true,
},
{
testName: "Tests that details can be passed through",
serviceKey: kelpServiceKey,
description: "Testing monitoring package. Not a real incident!",
details: struct {
LoadAvg float64 `json:"load_avg"`
NumRequests int `json:"num_requests"`
}{
LoadAvg: 0.5,
NumRequests: 100,
},
errorExpected: false,
},
}
for _, tc := range testCases {
t.Run(tc.testName, func(t *testing.T) {
pagerDutyAlert, e := MakeAlert("PagerDuty", tc.serviceKey)
if !assert.Nil(t, e) {
return
}
e = pagerDutyAlert.Trigger(tc.description, tc.details)
if tc.errorExpected {
assert.NotNil(t, e)
} else {
assert.Nil(t, e)
}
})
}
}
2 changes: 2 additions & 0 deletions trader/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ type BotConfig struct {
ISSUER_B string `valid:"-"`
TICK_INTERVAL_SECONDS int32 `valid:"-"`
HORIZON_URL string `valid:"-"`
ALERT_TYPE string `valid:"-"`
ALERT_API_KEY string `valid:"-"`

tradingAccount *string
sourceAccount *string // can be nil
Expand Down
3 changes: 3 additions & 0 deletions trader/trader.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Trader struct {
strat api.Strategy // the instance of this bot is bound to this strategy
tickIntervalSeconds int32
dataKey *model.BotKey
alert api.Alert

// uninitialized
maxAssetA float64
Expand All @@ -47,6 +48,7 @@ func MakeBot(
strat api.Strategy,
tickIntervalSeconds int32,
dataKey *model.BotKey,
alert api.Alert,
) *Trader {
return &Trader{
api: api,
Expand All @@ -57,6 +59,7 @@ func MakeBot(
strat: strat,
tickIntervalSeconds: tickIntervalSeconds,
dataKey: dataKey,
alert: alert,
}
}

Expand Down

0 comments on commit 5e46ae0

Please sign in to comment.