use std::str::FromStr;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use crate::types;
#[derive(Debug)]
pub struct GetMetrics {
pub from: usize,
pub host: Option<String>,
pub tag_filter: Option<String>,
pub version: types::version::ApiVersion,
pub headers: reqwest::header::HeaderMap,
pub body: reqwest::Body,
}
#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)]
pub struct GetMetricsResponse {
pub from: String,
pub metrics: Vec<String>,
}
impl Default for GetMetrics {
fn default() -> Self {
Self {
from: 0,
host: None,
tag_filter: None,
version: types::version::ApiVersion::V2,
headers: reqwest::header::HeaderMap::new(),
body: reqwest::Body::from(""),
}
}
}
impl TryFrom<types::version::ApiVersion> for GetMetrics {
type Error = &'static str;
fn try_from(v: types::version::ApiVersion) -> Result<Self, Self::Error> {
match v {
types::version::ApiVersion::V1 => Ok(Self::default()),
_ => Err("Unsupported API Version"),
}
}
}
impl GetMetrics {
pub fn new(from: usize, host: Option<String>, tag_filter: Option<String>) -> Self {
tracing::info!(target: "/v1/metrics", "Route Created");
Self {
from,
host,
tag_filter,
version: types::version::ApiVersion::V1,
headers: reqwest::header::HeaderMap::new(),
body: reqwest::Body::from(""),
}
}
pub fn set_from(mut self, from: usize) -> Self {
tracing::info!(target: "/v1/metrics", "Metrics from set to {}", from);
self.from = from;
self
}
pub fn set_host(mut self, host: String) -> Self {
tracing::info!(target: "/v1/metrics", "Metrics host set to {}", host);
self.host = Some(host);
self
}
pub fn set_tag_filter(mut self, tag_filter: String) -> Self {
tracing::info!(target: "/v1/metrics", "Metrics tag filter set to {}", tag_filter);
self.tag_filter = Some(tag_filter);
self
}
pub fn target() -> String {
String::from("v1/metrics")
}
}
#[async_trait]
impl types::route::Route<GetMetricsResponse> for GetMetrics {
fn path(&self) -> String {
String::from("v1/metrics")
}
fn route(self, _: String) -> Self {
self
}
fn with_header(mut self, key: &str, value: &str) -> Self {
self.headers.insert(
reqwest::header::HeaderName::from_str(key).unwrap(),
reqwest::header::HeaderValue::from_str(value).unwrap(),
);
self
}
fn headers(mut self, headers: Vec<(&str, &str)>) -> Self {
for (key, value) in headers {
self.headers.insert(
reqwest::header::HeaderName::from_str(key).unwrap(),
reqwest::header::HeaderValue::from_str(value).unwrap(),
);
}
self
}
fn with_api_key(mut self, key: &str) -> Self {
self.headers.insert(
reqwest::header::HeaderName::from_str("DD-API-KEY").unwrap(),
reqwest::header::HeaderValue::from_str(key).unwrap(),
);
self
}
fn with_application_key(mut self, key: &str) -> Self {
self.headers.insert(
reqwest::header::HeaderName::from_str("DD-APPLICATION-KEY").unwrap(),
reqwest::header::HeaderValue::from_str(key).unwrap(),
);
self
}
fn body<T: Into<reqwest::Body>>(mut self, body: T) -> Self {
self.body = body.into();
self
}
async fn execute(
self,
) -> (
reqwest::StatusCode,
Result<GetMetricsResponse, Option<reqwest::Error>>,
) {
let url = format!(
"{}/{}?from={}&host={}&tag_filter={}",
types::base::BASE_API_URL,
self.path(),
self.from,
self.host.unwrap_or_else(|| "".to_string()),
self.tag_filter.unwrap_or_else(|| "".to_string())
);
tracing::info!(target: "/v1/metrics", "Sending Request to {}", url);
let mut req_builder: reqwest::RequestBuilder = reqwest::Client::new().get(url);
req_builder = req_builder.headers(self.headers.clone());
let response = req_builder.send().await;
match response {
Ok(r) => {
let status_code = r.status();
if status_code != reqwest::StatusCode::from_u16(200).unwrap() {
tracing::error!(target: "/v1/metrics", "Received non-ok status code {:?}", status_code);
return (status_code, Err(None));
}
match r.json::<GetMetricsResponse>().await {
Ok(s) => {
tracing::info!(target: "/v1/metrics", "Succesfully parsed response from tags route {:?}", s);
return (status_code, Ok(s));
}
Err(e) => {
tracing::error!(target: "/v1/metrics", "Failed to parse response as a GetMetricsResponse with error {:?}", e);
return (reqwest::StatusCode::BAD_REQUEST, Err(Some(e)));
}
}
}
Err(e) => {
tracing::error!(target: "/v1/metrics", "Request failed with error {:?}", e);
return (
e.status().unwrap_or(reqwest::StatusCode::BAD_REQUEST),
Err(Some(e)),
);
}
}
}
}