Skip to content

Commit 335e9e5

Browse files
bors-voyager[bot]sgrifcarols10cents
committed
Merge #1498
1498: Add infrastructure for pagerduty integration r=carols10cents a=sgrif Right our pagerduty notifications come from heroku email alerts and a pingdom integration. We want to start paging on more specific metrics. So far we've discussed: - When no crate is uploaded for N period of time (likely 4 hours) - When a background job has failed N times (likely 5) - When the background queue has N jobs (likely 5) In order to do this we need to have some code in place that actually starts an incident and pages whoever is on call. We'd also like to test this code before we start relying on it, so I've added a binary we can use to make sure everything is configured correctly. Co-authored-by: Sean Griffin <[email protected]> Co-authored-by: Carol (Nichols || Goulding) <[email protected]>
2 parents 4ba9fdb + 0fcd6d1 commit 335e9e5

File tree

3 files changed

+140
-30
lines changed

3 files changed

+140
-30
lines changed

Cargo.lock

Lines changed: 31 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/bin/on_call/mod.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
extern crate cargo_registry;
2+
extern crate reqwest;
3+
4+
use self::reqwest::{header, StatusCode as Status};
5+
use std::env;
6+
7+
use self::cargo_registry::util::*;
8+
9+
#[derive(Serialize, Debug)]
10+
#[serde(rename_all = "snake_case", tag = "event_type")]
11+
pub enum Event {
12+
Trigger {
13+
incident_key: Option<String>,
14+
description: String,
15+
},
16+
Acknowledge {
17+
incident_key: String,
18+
description: Option<String>,
19+
},
20+
Resolve {
21+
incident_key: String,
22+
description: Option<String>,
23+
},
24+
}
25+
26+
impl Event {
27+
/// Sends the event to pagerduty.
28+
///
29+
/// If the variant is `Trigger`, this will page whoever is on call
30+
/// (potentially waking them up at 3 AM).
31+
pub fn send(self) -> CargoResult<()> {
32+
let api_token = env::var("PAGERDUTY_API_TOKEN")?;
33+
let service_key = env::var("PAGERDUTY_INTEGRATION_KEY")?;
34+
35+
let mut response = reqwest::Client::new()
36+
.post("https://events.pagerduty.com/generic/2010-04-15/create_event.json")
37+
.header(header::ACCEPT, "application/vnd.pagerduty+json;version=2")
38+
.header(header::AUTHORIZATION, format!("Token token={}", api_token))
39+
.json(&FullEvent {
40+
service_key,
41+
event: self,
42+
}).send()?;
43+
44+
match response.status() {
45+
s if s.is_success() => Ok(()),
46+
Status::BAD_REQUEST => {
47+
let error = response.json::<InvalidEvent>()?;
48+
Err(internal(&format_args!("pagerduty error: {:?}", error)))
49+
}
50+
Status::FORBIDDEN => Err(internal("rate limited by pagerduty")),
51+
n => Err(internal(&format_args!(
52+
"Got a non 200 response code from pagerduty: {} with {:?}",
53+
n, response
54+
))),
55+
}
56+
}
57+
}
58+
59+
#[derive(Serialize, Debug)]
60+
struct FullEvent {
61+
service_key: String,
62+
#[serde(flatten)]
63+
event: Event,
64+
}
65+
66+
#[derive(Deserialize, Debug)]
67+
struct InvalidEvent {
68+
message: String,
69+
errors: Vec<String>,
70+
}

src/bin/test-pagerduty.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//! Send a test event to pagerduty
2+
//!
3+
//! Usage:
4+
//! cargo run --bin test-pagerduty event_type [description]
5+
//!
6+
//! Event type can be trigger, acknowledge, or resolve
7+
8+
#![deny(warnings)]
9+
10+
#[macro_use]
11+
extern crate serde_derive;
12+
13+
mod on_call;
14+
15+
use std::env::args;
16+
17+
fn main() {
18+
let args = args().collect::<Vec<_>>();
19+
20+
let event_type = &*args[1];
21+
let description = args.get(2).cloned();
22+
23+
let event = match event_type {
24+
"trigger" => on_call::Event::Trigger {
25+
incident_key: Some("test".into()),
26+
description: description.unwrap_or_else(|| "Test event".into()),
27+
},
28+
"acknowledge" => on_call::Event::Acknowledge {
29+
incident_key: "test".into(),
30+
description,
31+
},
32+
"resolve" => on_call::Event::Resolve {
33+
incident_key: "test".into(),
34+
description,
35+
},
36+
_ => panic!("Event type must be trigger, acknowledge, or resolve"),
37+
};
38+
event.send().unwrap()
39+
}

0 commit comments

Comments
 (0)