datadog_api_client/datadogV2/api/
api_synthetics.rs

1// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
2// This product includes software developed at Datadog (https://www.datadoghq.com/).
3// Copyright 2019-Present Datadog, Inc.
4use crate::datadog;
5use flate2::{
6    write::{GzEncoder, ZlibEncoder},
7    Compression,
8};
9use reqwest::header::{HeaderMap, HeaderValue};
10use serde::{Deserialize, Serialize};
11use std::io::Write;
12
13/// GetOnDemandConcurrencyCapError is a struct for typed errors of method [`SyntheticsAPI::get_on_demand_concurrency_cap`]
14#[derive(Debug, Clone, Serialize, Deserialize)]
15#[serde(untagged)]
16pub enum GetOnDemandConcurrencyCapError {
17    APIErrorResponse(crate::datadogV2::model::APIErrorResponse),
18    UnknownValue(serde_json::Value),
19}
20
21/// SetOnDemandConcurrencyCapError is a struct for typed errors of method [`SyntheticsAPI::set_on_demand_concurrency_cap`]
22#[derive(Debug, Clone, Serialize, Deserialize)]
23#[serde(untagged)]
24pub enum SetOnDemandConcurrencyCapError {
25    APIErrorResponse(crate::datadogV2::model::APIErrorResponse),
26    UnknownValue(serde_json::Value),
27}
28
29/// Datadog Synthetics uses simulated user requests and browser rendering to help you ensure uptime,
30/// identify regional issues, and track your application performance. Datadog Synthetics tests come in
31/// two different flavors, [API tests](<https://docs.datadoghq.com/synthetics/api_tests/>)
32/// and [browser tests](<https://docs.datadoghq.com/synthetics/browser_tests>). You can use Datadog’s API to
33/// manage both test types programmatically.
34///
35/// For more information about Synthetics, see the [Synthetics overview](<https://docs.datadoghq.com/synthetics/>).
36#[derive(Debug, Clone)]
37pub struct SyntheticsAPI {
38    config: datadog::Configuration,
39    client: reqwest_middleware::ClientWithMiddleware,
40}
41
42impl Default for SyntheticsAPI {
43    fn default() -> Self {
44        Self::with_config(datadog::Configuration::default())
45    }
46}
47
48impl SyntheticsAPI {
49    pub fn new() -> Self {
50        Self::default()
51    }
52    pub fn with_config(config: datadog::Configuration) -> Self {
53        let mut reqwest_client_builder = reqwest::Client::builder();
54
55        if let Some(proxy_url) = &config.proxy_url {
56            let proxy = reqwest::Proxy::all(proxy_url).expect("Failed to parse proxy URL");
57            reqwest_client_builder = reqwest_client_builder.proxy(proxy);
58        }
59
60        let mut middleware_client_builder =
61            reqwest_middleware::ClientBuilder::new(reqwest_client_builder.build().unwrap());
62
63        if config.enable_retry {
64            struct RetryableStatus;
65            impl reqwest_retry::RetryableStrategy for RetryableStatus {
66                fn handle(
67                    &self,
68                    res: &Result<reqwest::Response, reqwest_middleware::Error>,
69                ) -> Option<reqwest_retry::Retryable> {
70                    match res {
71                        Ok(success) => reqwest_retry::default_on_request_success(success),
72                        Err(_) => None,
73                    }
74                }
75            }
76            let backoff_policy = reqwest_retry::policies::ExponentialBackoff::builder()
77                .build_with_max_retries(config.max_retries);
78
79            let retry_middleware =
80                reqwest_retry::RetryTransientMiddleware::new_with_policy_and_strategy(
81                    backoff_policy,
82                    RetryableStatus,
83                );
84
85            middleware_client_builder = middleware_client_builder.with(retry_middleware);
86        }
87
88        let client = middleware_client_builder.build();
89
90        Self { config, client }
91    }
92
93    pub fn with_client_and_config(
94        config: datadog::Configuration,
95        client: reqwest_middleware::ClientWithMiddleware,
96    ) -> Self {
97        Self { config, client }
98    }
99
100    /// Get the on-demand concurrency cap.
101    pub async fn get_on_demand_concurrency_cap(
102        &self,
103    ) -> Result<
104        crate::datadogV2::model::OnDemandConcurrencyCapResponse,
105        datadog::Error<GetOnDemandConcurrencyCapError>,
106    > {
107        match self.get_on_demand_concurrency_cap_with_http_info().await {
108            Ok(response_content) => {
109                if let Some(e) = response_content.entity {
110                    Ok(e)
111                } else {
112                    Err(datadog::Error::Serde(serde::de::Error::custom(
113                        "response content was None",
114                    )))
115                }
116            }
117            Err(err) => Err(err),
118        }
119    }
120
121    /// Get the on-demand concurrency cap.
122    pub async fn get_on_demand_concurrency_cap_with_http_info(
123        &self,
124    ) -> Result<
125        datadog::ResponseContent<crate::datadogV2::model::OnDemandConcurrencyCapResponse>,
126        datadog::Error<GetOnDemandConcurrencyCapError>,
127    > {
128        let local_configuration = &self.config;
129        let operation_id = "v2.get_on_demand_concurrency_cap";
130
131        let local_client = &self.client;
132
133        let local_uri_str = format!(
134            "{}/api/v2/synthetics/settings/on_demand_concurrency_cap",
135            local_configuration.get_operation_host(operation_id)
136        );
137        let mut local_req_builder =
138            local_client.request(reqwest::Method::GET, local_uri_str.as_str());
139
140        // build headers
141        let mut headers = HeaderMap::new();
142        headers.insert("Accept", HeaderValue::from_static("application/json"));
143
144        // build user agent
145        match HeaderValue::from_str(local_configuration.user_agent.as_str()) {
146            Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent),
147            Err(e) => {
148                log::warn!("Failed to parse user agent header: {e}, falling back to default");
149                headers.insert(
150                    reqwest::header::USER_AGENT,
151                    HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()),
152                )
153            }
154        };
155
156        // build auth
157        if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") {
158            headers.insert(
159                "DD-API-KEY",
160                HeaderValue::from_str(local_key.key.as_str())
161                    .expect("failed to parse DD-API-KEY header"),
162            );
163        };
164        if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") {
165            headers.insert(
166                "DD-APPLICATION-KEY",
167                HeaderValue::from_str(local_key.key.as_str())
168                    .expect("failed to parse DD-APPLICATION-KEY header"),
169            );
170        };
171
172        local_req_builder = local_req_builder.headers(headers);
173        let local_req = local_req_builder.build()?;
174        log::debug!("request content: {:?}", local_req.body());
175        let local_resp = local_client.execute(local_req).await?;
176
177        let local_status = local_resp.status();
178        let local_content = local_resp.text().await?;
179        log::debug!("response content: {}", local_content);
180
181        if !local_status.is_client_error() && !local_status.is_server_error() {
182            match serde_json::from_str::<crate::datadogV2::model::OnDemandConcurrencyCapResponse>(
183                &local_content,
184            ) {
185                Ok(e) => {
186                    return Ok(datadog::ResponseContent {
187                        status: local_status,
188                        content: local_content,
189                        entity: Some(e),
190                    })
191                }
192                Err(e) => return Err(datadog::Error::Serde(e)),
193            };
194        } else {
195            let local_entity: Option<GetOnDemandConcurrencyCapError> =
196                serde_json::from_str(&local_content).ok();
197            let local_error = datadog::ResponseContent {
198                status: local_status,
199                content: local_content,
200                entity: local_entity,
201            };
202            Err(datadog::Error::ResponseError(local_error))
203        }
204    }
205
206    /// Save new value for on-demand concurrency cap.
207    pub async fn set_on_demand_concurrency_cap(
208        &self,
209        body: crate::datadogV2::model::OnDemandConcurrencyCapAttributes,
210    ) -> Result<
211        crate::datadogV2::model::OnDemandConcurrencyCapResponse,
212        datadog::Error<SetOnDemandConcurrencyCapError>,
213    > {
214        match self
215            .set_on_demand_concurrency_cap_with_http_info(body)
216            .await
217        {
218            Ok(response_content) => {
219                if let Some(e) = response_content.entity {
220                    Ok(e)
221                } else {
222                    Err(datadog::Error::Serde(serde::de::Error::custom(
223                        "response content was None",
224                    )))
225                }
226            }
227            Err(err) => Err(err),
228        }
229    }
230
231    /// Save new value for on-demand concurrency cap.
232    pub async fn set_on_demand_concurrency_cap_with_http_info(
233        &self,
234        body: crate::datadogV2::model::OnDemandConcurrencyCapAttributes,
235    ) -> Result<
236        datadog::ResponseContent<crate::datadogV2::model::OnDemandConcurrencyCapResponse>,
237        datadog::Error<SetOnDemandConcurrencyCapError>,
238    > {
239        let local_configuration = &self.config;
240        let operation_id = "v2.set_on_demand_concurrency_cap";
241
242        let local_client = &self.client;
243
244        let local_uri_str = format!(
245            "{}/api/v2/synthetics/settings/on_demand_concurrency_cap",
246            local_configuration.get_operation_host(operation_id)
247        );
248        let mut local_req_builder =
249            local_client.request(reqwest::Method::POST, local_uri_str.as_str());
250
251        // build headers
252        let mut headers = HeaderMap::new();
253        headers.insert("Content-Type", HeaderValue::from_static("application/json"));
254        headers.insert("Accept", HeaderValue::from_static("application/json"));
255
256        // build user agent
257        match HeaderValue::from_str(local_configuration.user_agent.as_str()) {
258            Ok(user_agent) => headers.insert(reqwest::header::USER_AGENT, user_agent),
259            Err(e) => {
260                log::warn!("Failed to parse user agent header: {e}, falling back to default");
261                headers.insert(
262                    reqwest::header::USER_AGENT,
263                    HeaderValue::from_static(datadog::DEFAULT_USER_AGENT.as_str()),
264                )
265            }
266        };
267
268        // build auth
269        if let Some(local_key) = local_configuration.auth_keys.get("apiKeyAuth") {
270            headers.insert(
271                "DD-API-KEY",
272                HeaderValue::from_str(local_key.key.as_str())
273                    .expect("failed to parse DD-API-KEY header"),
274            );
275        };
276        if let Some(local_key) = local_configuration.auth_keys.get("appKeyAuth") {
277            headers.insert(
278                "DD-APPLICATION-KEY",
279                HeaderValue::from_str(local_key.key.as_str())
280                    .expect("failed to parse DD-APPLICATION-KEY header"),
281            );
282        };
283
284        // build body parameters
285        let output = Vec::new();
286        let mut ser = serde_json::Serializer::with_formatter(output, datadog::DDFormatter);
287        if body.serialize(&mut ser).is_ok() {
288            if let Some(content_encoding) = headers.get("Content-Encoding") {
289                match content_encoding.to_str().unwrap_or_default() {
290                    "gzip" => {
291                        let mut enc = GzEncoder::new(Vec::new(), Compression::default());
292                        let _ = enc.write_all(ser.into_inner().as_slice());
293                        match enc.finish() {
294                            Ok(buf) => {
295                                local_req_builder = local_req_builder.body(buf);
296                            }
297                            Err(e) => return Err(datadog::Error::Io(e)),
298                        }
299                    }
300                    "deflate" => {
301                        let mut enc = ZlibEncoder::new(Vec::new(), Compression::default());
302                        let _ = enc.write_all(ser.into_inner().as_slice());
303                        match enc.finish() {
304                            Ok(buf) => {
305                                local_req_builder = local_req_builder.body(buf);
306                            }
307                            Err(e) => return Err(datadog::Error::Io(e)),
308                        }
309                    }
310                    "zstd1" => {
311                        let mut enc = zstd::stream::Encoder::new(Vec::new(), 0).unwrap();
312                        let _ = enc.write_all(ser.into_inner().as_slice());
313                        match enc.finish() {
314                            Ok(buf) => {
315                                local_req_builder = local_req_builder.body(buf);
316                            }
317                            Err(e) => return Err(datadog::Error::Io(e)),
318                        }
319                    }
320                    _ => {
321                        local_req_builder = local_req_builder.body(ser.into_inner());
322                    }
323                }
324            } else {
325                local_req_builder = local_req_builder.body(ser.into_inner());
326            }
327        }
328
329        local_req_builder = local_req_builder.headers(headers);
330        let local_req = local_req_builder.build()?;
331        log::debug!("request content: {:?}", local_req.body());
332        let local_resp = local_client.execute(local_req).await?;
333
334        let local_status = local_resp.status();
335        let local_content = local_resp.text().await?;
336        log::debug!("response content: {}", local_content);
337
338        if !local_status.is_client_error() && !local_status.is_server_error() {
339            match serde_json::from_str::<crate::datadogV2::model::OnDemandConcurrencyCapResponse>(
340                &local_content,
341            ) {
342                Ok(e) => {
343                    return Ok(datadog::ResponseContent {
344                        status: local_status,
345                        content: local_content,
346                        entity: Some(e),
347                    })
348                }
349                Err(e) => return Err(datadog::Error::Serde(e)),
350            };
351        } else {
352            let local_entity: Option<SetOnDemandConcurrencyCapError> =
353                serde_json::from_str(&local_content).ok();
354            let local_error = datadog::ResponseContent {
355                status: local_status,
356                content: local_content,
357                entity: local_entity,
358            };
359            Err(datadog::Error::ResponseError(local_error))
360        }
361    }
362}