pagerduty_rs/
eventsv2async.rs

1use crate::private_types::*;
2use crate::types::*;
3
4use reqwest::header::{
5    HeaderMap, HeaderValue, InvalidHeaderValue, CONTENT_ENCODING, CONTENT_TYPE, USER_AGENT,
6};
7use reqwest::Client;
8use serde::Serialize;
9use std::convert::From;
10use std::error::Error;
11use std::fmt::{Display, Formatter, Result as FmtResult};
12
13const CONTENT_ENCODING_IDENTITY: &str = "identity";
14const CONTENT_TYPE_JSON: &str = "application/json";
15
16#[derive(Debug)]
17pub enum EventsV2Error {
18    ReqwestError(reqwest::Error),
19    InvalidHeaderValue(InvalidHeaderValue),
20
21    //https://developer.pagerduty.com/docs/events-api-v2/overview/#api-response-codes--retry-logic
22    HttpNotAccepted(u16), // NOT 4xx, 5xx or 200 (we expect 202). Contains HTTP response code.
23    HttpError(u16),       // A legit error (4xx or 5xx). Contains HTTP response code.
24}
25
26impl Error for EventsV2Error {}
27impl Display for EventsV2Error {
28    fn fmt(&self, f: &mut Formatter) -> FmtResult {
29        match self {
30            Self::ReqwestError(e) => write!(f, "RequestError: {}", e),
31            Self::InvalidHeaderValue(e) => write!(f, "InvalidHeaderValue: {}", e),
32            Self::HttpNotAccepted(e) => write!(f, "HttpNotAccepted: {}", e),
33            Self::HttpError(e) => write!(f, "HttpError: {}", e),
34        }
35    }
36}
37impl From<reqwest::Error> for EventsV2Error {
38    fn from(err: reqwest::Error) -> Self {
39        Self::ReqwestError(err)
40    }
41}
42impl From<InvalidHeaderValue> for EventsV2Error {
43    fn from(err: InvalidHeaderValue) -> Self {
44        Self::InvalidHeaderValue(err)
45    }
46}
47
48pub type EventsV2Result = Result<(), EventsV2Error>;
49
50/// The main PagerDuty Events V2 API
51pub struct EventsV2 {
52    /// The integration/routing key for a generated PagerDuty service
53    integration_key: String,
54    client: Client,
55}
56
57impl EventsV2 {
58    pub fn new(
59        integration_key: String,
60        user_agent: Option<String>,
61    ) -> Result<EventsV2, EventsV2Error> {
62        let mut headers = HeaderMap::new();
63        headers.insert(CONTENT_TYPE, HeaderValue::from_str(CONTENT_TYPE_JSON)?);
64        headers.insert(
65            CONTENT_ENCODING,
66            HeaderValue::from_str(CONTENT_ENCODING_IDENTITY)?,
67        );
68        if let Some(ua) = user_agent {
69            headers.insert(USER_AGENT, HeaderValue::from_str(ua.as_str())?);
70        }
71
72        let client = Client::builder().default_headers(headers).build()?;
73
74        Ok(EventsV2 {
75            integration_key,
76            client,
77        })
78    }
79
80    pub async fn event<T: Serialize>(&self, event: Event<T>) -> EventsV2Result {
81        match event {
82            Event::Change(c) => self.change(c).await,
83            Event::AlertTrigger(at) => self.alert_trigger(at).await,
84            Event::AlertAcknowledge(aa) => {
85                self.alert_followup(aa.dedup_key, Action::Acknowledge).await
86            }
87            Event::AlertResolve(ar) => self.alert_followup(ar.dedup_key, Action::Resolve).await,
88        }
89    }
90
91    async fn change<T: Serialize>(&self, change: Change<T>) -> EventsV2Result {
92        let sendable_change = SendableChange::from_change(change, self.integration_key.clone());
93
94        self.do_post(
95            "https://events.pagerduty.com/v2/change/enqueue",
96            sendable_change,
97        )
98        .await
99    }
100
101    async fn alert_trigger<T: Serialize>(&self, alert_trigger: AlertTrigger<T>) -> EventsV2Result {
102        let sendable_alert_trigger =
103            SendableAlertTrigger::from_alert_trigger(alert_trigger, self.integration_key.clone());
104
105        self.do_post(
106            "https://events.pagerduty.com/v2/enqueue",
107            sendable_alert_trigger,
108        )
109        .await
110    }
111
112    async fn alert_followup(&self, dedup_key: String, action: Action) -> EventsV2Result {
113        let sendable_alert_followup =
114            SendableAlertFollowup::new(dedup_key, action, self.integration_key.clone());
115
116        self.do_post(
117            "https://events.pagerduty.com/v2/enqueue",
118            sendable_alert_followup,
119        )
120        .await
121    }
122
123    // Make this part Async in the future
124    async fn do_post<T: Serialize>(&self, url: &str, content: T) -> EventsV2Result {
125        let res = self.client.post(url).json(&content).send().await?;
126
127        match res.status().as_u16() {
128            202 => Ok(()),
129            e if e < 400 => Err(EventsV2Error::HttpNotAccepted(e)),
130            e => Err(EventsV2Error::HttpError(e)),
131        }
132    }
133}