Skip to content

Commit

Permalink
Add CustomDetails field to PagerDuty (#65)
Browse files Browse the repository at this point in the history
* add CustomDetails to PagerDuty

* test cases for custom details

* CustomDetails -> Details, test cases for PagerDuty payload

* remove custom_details if the payload size is too large

* rename test case

* comment about logic taken from upstream AM
  • Loading branch information
santihernandezc authored Mar 15, 2023
1 parent 42b0b0b commit d1e3c68
Show file tree
Hide file tree
Showing 6 changed files with 424 additions and 168 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/grafana/alerting
go 1.18

require (
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137
github.com/go-kit/log v0.2.1
github.com/go-openapi/strfmt v0.21.3
github.com/pkg/errors v0.9.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
Expand Down
45 changes: 28 additions & 17 deletions receivers/pagerduty/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,41 @@ const (
DefaultClient = "Grafana"
)

func defaultCustomDetails() map[string]string {
return map[string]string{
"firing": `{{ template "__text_alert_list" .Alerts.Firing }}`,
"resolved": `{{ template "__text_alert_list" .Alerts.Resolved }}`,
"num_firing": `{{ .Alerts.Firing | len }}`,
"num_resolved": `{{ .Alerts.Resolved | len }}`,
var defaultDetails = map[string]string{
"firing": `{{ template "__text_alert_list" .Alerts.Firing }}`,
"resolved": `{{ template "__text_alert_list" .Alerts.Resolved }}`,
"num_firing": `{{ .Alerts.Firing | len }}`,
"num_resolved": `{{ .Alerts.Resolved | len }}`,
}

// mergeDetails merges the default details with the user-defined ones.
// Default values get overwritten in case of duplicate keys.
func mergeDetails(userDefinedDetails map[string]string) map[string]string {
mergedDetails := make(map[string]string)
for k, v := range defaultDetails {
mergedDetails[k] = v
}
for k, v := range userDefinedDetails {
mergedDetails[k] = v
}
return mergedDetails
}

var getHostname = func() (string, error) {
return os.Hostname()
}

type Config struct {
Key string `json:"integrationKey,omitempty" yaml:"integrationKey,omitempty"`
Severity string `json:"severity,omitempty" yaml:"severity,omitempty"`
CustomDetails map[string]string `json:"-" yaml:"-"` // TODO support the settings in the config
Class string `json:"class,omitempty" yaml:"class,omitempty"`
Component string `json:"component,omitempty" yaml:"component,omitempty"`
Group string `json:"group,omitempty" yaml:"group,omitempty"`
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
Source string `json:"source,omitempty" yaml:"source,omitempty"`
Client string `json:"client,omitempty" yaml:"client,omitempty"`
ClientURL string `json:"client_url,omitempty" yaml:"client_url,omitempty"`
Key string `json:"integrationKey,omitempty" yaml:"integrationKey,omitempty"`
Severity string `json:"severity,omitempty" yaml:"severity,omitempty"`
Details map[string]string `json:"details,omitempty" yaml:"details,omitempty"`
Class string `json:"class,omitempty" yaml:"class,omitempty"`
Component string `json:"component,omitempty" yaml:"component,omitempty"`
Group string `json:"group,omitempty" yaml:"group,omitempty"`
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
Source string `json:"source,omitempty" yaml:"source,omitempty"`
Client string `json:"client,omitempty" yaml:"client,omitempty"`
ClientURL string `json:"client_url,omitempty" yaml:"client_url,omitempty"`
}

func NewConfig(jsonData json.RawMessage, decryptFn receivers.DecryptFunc) (Config, error) {
Expand All @@ -55,7 +66,7 @@ func NewConfig(jsonData json.RawMessage, decryptFn receivers.DecryptFunc) (Confi
return Config{}, errors.New("could not find integration key property in settings")
}

settings.CustomDetails = defaultCustomDetails()
settings.Details = mergeDetails(settings.Details)

if settings.Severity == "" {
settings.Severity = DefaultSeverity
Expand Down
241 changes: 156 additions & 85 deletions receivers/pagerduty/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,16 @@ func TestNewConfig(t *testing.T) {
name: "Minimal valid configuration",
settings: `{"integrationKey": "test-api-key" }`,
expectedConfig: Config{
Key: "test-api-key",
Severity: DefaultSeverity,
CustomDetails: defaultCustomDetails(),
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
Key: "test-api-key",
Severity: DefaultSeverity,
Details: defaultDetails,
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
},
},
{
Expand All @@ -63,16 +63,16 @@ func TestNewConfig(t *testing.T) {
"integrationKey": []byte("test-api-key"),
},
expectedConfig: Config{
Key: "test-api-key",
Severity: DefaultSeverity,
CustomDetails: defaultCustomDetails(),
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
Key: "test-api-key",
Severity: DefaultSeverity,
Details: defaultDetails,
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
},
},
{
Expand All @@ -82,16 +82,16 @@ func TestNewConfig(t *testing.T) {
"integrationKey": []byte("test-api-key"),
},
expectedConfig: Config{
Key: "test-api-key",
Severity: DefaultSeverity,
CustomDetails: defaultCustomDetails(),
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
Key: "test-api-key",
Severity: DefaultSeverity,
Details: defaultDetails,
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
},
},
{
Expand All @@ -111,75 +111,146 @@ func TestNewConfig(t *testing.T) {
"client_url": ""
}`,
expectedConfig: Config{
Key: "test-api-key",
Severity: DefaultSeverity,
CustomDetails: defaultCustomDetails(),
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
Key: "test-api-key",
Severity: DefaultSeverity,
Details: defaultDetails,
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
},
},
{
name: "Extract all fields",
settings: FullValidConfigForTesting,
expectedConfig: Config{
Key: "test-api-key",
Severity: "test-severity",
CustomDetails: defaultCustomDetails(),
Class: "test-class",
Component: "test-component",
Group: "test-group",
Summary: "test-summary",
Source: "test-source",
Client: "test-client",
ClientURL: "test-client-url",
Key: "test-api-key",
Severity: "test-severity",
Details: defaultDetails,
Class: "test-class",
Component: "test-component",
Group: "test-group",
Summary: "test-summary",
Source: "test-source",
Client: "test-client",
ClientURL: "test-client-url",
},
},
{
name: "Extract all fields + override from secrets",
settings: FullValidConfigForTesting,
secureSettings: receiversTesting.ReadSecretsJSONForTesting(FullValidSecretsForTesting),
expectedConfig: Config{
Key: "test-secret-api-key",
Severity: "test-severity",
CustomDetails: defaultCustomDetails(),
Class: "test-class",
Component: "test-component",
Group: "test-group",
Summary: "test-summary",
Source: "test-source",
Client: "test-client",
ClientURL: "test-client-url",
Key: "test-secret-api-key",
Severity: "test-severity",
Details: defaultDetails,
Class: "test-class",
Component: "test-component",
Group: "test-group",
Summary: "test-summary",
Source: "test-source",
Client: "test-client",
ClientURL: "test-client-url",
},
},
{
name: "Should ignore custom details",
name: "Should merge default details with user-defined ones",
secureSettings: map[string][]byte{
"integrationKey": []byte("test-api-key"),
},
settings: `{
"custom_details" : {
"test" : "test"
"details" : {
"test-field" : "test",
"test-field-2": "test-2"
}
}`,
expectedConfig: Config{
Key: "test-api-key",
Severity: DefaultSeverity,
Details: map[string]string{
"firing": `{{ template "__text_alert_list" .Alerts.Firing }}`,
"resolved": `{{ template "__text_alert_list" .Alerts.Resolved }}`,
"num_firing": `{{ .Alerts.Firing | len }}`,
"num_resolved": `{{ .Alerts.Resolved | len }}`,
"test-field": "test",
"test-field-2": "test-2",
},
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
},
},
{
name: "Should overwrite default details with user-defined ones when keys are duplicated",
secureSettings: map[string][]byte{
"integrationKey": []byte("test-api-key"),
},
settings: `{
"details" : {
"firing" : "test",
"resolved": "maybe",
"num_firing": "a lot",
"num_resolved": "just a few"
}
}`,
expectedConfig: Config{
Key: "test-api-key",
Severity: DefaultSeverity,
Details: map[string]string{
"firing": "test",
"resolved": "maybe",
"num_firing": "a lot",
"num_resolved": "just a few",
},
"CustomDetails" : {
"test" : "test"
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
},
},
{
name: "Custom details should be case-sensitive",
secureSettings: map[string][]byte{
"integrationKey": []byte("test-api-key"),
},
settings: `{
"details" : {
"Firing" : "test",
"Resolved": "maybe",
"nuM_firing": "a lot",
"num_reSolved": "just a few"
}
}`,
expectedConfig: Config{
Key: "test-api-key",
Severity: DefaultSeverity,
CustomDetails: defaultCustomDetails(),
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
Key: "test-api-key",
Severity: DefaultSeverity,
Details: map[string]string{
"firing": `{{ template "__text_alert_list" .Alerts.Firing }}`,
"resolved": `{{ template "__text_alert_list" .Alerts.Resolved }}`,
"num_firing": `{{ .Alerts.Firing | len }}`,
"num_resolved": `{{ .Alerts.Resolved | len }}`,
"Firing": "test",
"Resolved": "maybe",
"nuM_firing": "a lot",
"num_reSolved": "just a few",
},
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: hostName,
Client: DefaultClient,
ClientURL: "{{ .ExternalURL }}",
},
},
{
Expand All @@ -194,16 +265,16 @@ func TestNewConfig(t *testing.T) {
return "", errors.New("test")
},
expectedConfig: Config{
Key: "test-api-key",
Severity: DefaultSeverity,
CustomDetails: defaultCustomDetails(),
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: "test-client",
Client: "test-client",
ClientURL: "{{ .ExternalURL }}",
Key: "test-api-key",
Severity: DefaultSeverity,
Details: defaultDetails,
Class: DefaultClass,
Component: "Grafana",
Group: DefaultGroup,
Summary: templates.DefaultMessageTitleEmbed,
Source: "test-client",
Client: "test-client",
ClientURL: "{{ .ExternalURL }}",
},
},
}
Expand Down
Loading

0 comments on commit d1e3c68

Please sign in to comment.