1use std::sync::Arc;
2
3use reqwest::Method;
4
5use crate::{
6 Config, Result,
7 list_opts::{ListOptions, ListResponse},
8 types::Log,
9};
10
11#[derive(Clone, Debug)]
13pub struct LogsSvc(pub(crate) Arc<Config>);
14
15impl LogsSvc {
16 #[maybe_async::maybe_async]
20 pub async fn get(&self, log_id: &str) -> Result<Log> {
21 let path = format!("/logs/{log_id}");
22
23 let request = self.0.build(Method::GET, &path);
24 let response = self.0.send(request).await?;
25 let content = response.json::<Log>().await?;
26
27 Ok(content)
28 }
29
30 #[maybe_async::maybe_async]
36 pub async fn list<T>(&self, list_opts: ListOptions<T>) -> Result<ListResponse<Log>> {
37 let request = self.0.build(Method::GET, "/logs").query(&list_opts);
38 let response = self.0.send(request).await?;
39 let content = response.json::<ListResponse<Log>>().await?;
40
41 Ok(content)
42 }
43}
44
45#[allow(unreachable_pub)]
46pub mod types {
47 use std::num::NonZeroU16;
48
49 use serde::{Deserialize, Serialize};
50
51 crate::define_id_type!(LogId);
52
53 #[must_use]
54 #[derive(Debug, Clone, Serialize, Deserialize)]
55 pub struct Log {
56 pub id: LogId,
57 pub created_at: String,
58 pub endpoint: String,
59 pub method: String,
60 pub response_status: NonZeroU16,
61 pub user_agent: Option<String>,
62 #[serde(default)]
63 pub request_body: serde_json::Value,
64 #[serde(default)]
65 pub response_body: serde_json::Value,
66 }
67}
68
69#[cfg(test)]
70#[allow(clippy::needless_return, clippy::unwrap_used)]
71mod test {
72 #[cfg(not(feature = "blocking"))]
73 use crate::{
74 list_opts::ListOptions,
75 test::{CLIENT, DebugResult},
76 };
77
78 #[tokio_shared_rt::test(shared = true)]
79 #[serial_test::serial]
80 #[cfg(not(feature = "blocking"))]
81 async fn all() -> DebugResult<()> {
82 let resend = &*CLIENT;
83
84 let logs = resend.logs.list(ListOptions::default()).await?;
86 assert!(!logs.data.is_empty());
87
88 let head = logs.data.first().unwrap();
90
91 let _log = resend.logs.get(&head.id).await?;
92
93 Ok(())
94 }
95}