portkey_sdk/service/
logs.rs

1use std::future::Future;
2
3#[cfg(feature = "tracing")]
4use crate::TRACING_TARGET_SERVICE;
5use crate::client::PortkeyClient;
6use crate::error::Result;
7use crate::model::{
8    CreateLogExportRequest, CreateLogExportResponse, DownloadLogExportResponse, ExportTaskResponse,
9    InsertLogRequest, InsertLogResponse, ListLogExportsParams, ListLogExportsResponse, LogExport,
10    UpdateLogExportRequest, UpdateLogExportResponse,
11};
12
13/// Service trait for managing log exports.
14///
15/// This trait provides methods for creating, retrieving, starting, canceling,
16/// and downloading log exports from Portkey.
17///
18/// # Example
19///
20/// ```rust,no_run
21/// use portkey_sdk::{PortkeyConfig, Result};
22/// use portkey_sdk::service::LogsService;
23/// use portkey_sdk::builder::AuthMethod;
24/// use portkey_sdk::model::{CreateLogExportRequest, GenerationsFilter, LogExportField};
25///
26/// #[tokio::main]
27/// async fn main() -> Result<()> {
28///     let client = PortkeyConfig::builder()
29///         .with_api_key("your-portkey-api-key")
30///         .with_auth_method(AuthMethod::virtual_key("your-virtual-key"))
31///         .build_client()?;
32///
33///     // Create a log export
34///     let filters = GenerationsFilter {
35///         time_of_generation_min: Some("2024-10-20".to_string()),
36///         time_of_generation_max: Some("2024-10-30".to_string()),
37///         ..Default::default()
38///     };
39///
40///     let request = CreateLogExportRequest {
41///         workspace_id: Some("workspace-123".to_string()),
42///         filters,
43///         requested_data: vec![
44///             LogExportField::Id,
45///             LogExportField::TraceId,
46///             LogExportField::CreatedAt,
47///         ],
48///         description: Some("Export for October 2024".to_string()),
49///     };
50///
51///     let export = client.create_log_export(request).await?;
52///     println!("Created export: {}", export.id);
53///
54///     // Start the export
55///     client.start_log_export(&export.id).await?;
56///
57///     // Retrieve export status
58///     let status = client.get_log_export(&export.id).await?;
59///     println!("Export status: {:?}", status.status);
60///
61///     // Download when ready
62///     let download = client.download_log_export(&export.id).await?;
63///     println!("Download URL: {}", download.signed_url);
64///
65///     Ok(())
66/// }
67/// ```
68pub trait LogsService {
69    /// Creates a new log export.
70    ///
71    /// # Arguments
72    ///
73    /// * `request` - The export configuration with filters and requested fields
74    ///
75    /// # Returns
76    ///
77    /// Returns a `CreateLogExportResponse` with the export ID and total count.
78    ///
79    /// # Errors
80    ///
81    /// Returns an error if the API request fails or the response cannot be parsed.
82    fn create_log_export(
83        &self,
84        request: CreateLogExportRequest,
85    ) -> impl Future<Output = Result<CreateLogExportResponse>>;
86
87    /// Retrieves a log export by ID.
88    ///
89    /// # Arguments
90    ///
91    /// * `export_id` - The unique identifier of the export
92    ///
93    /// # Returns
94    ///
95    /// Returns a `LogExport` with full export details.
96    ///
97    /// # Errors
98    ///
99    /// Returns an error if the export is not found or the API request fails.
100    fn get_log_export(&self, export_id: &str) -> impl Future<Output = Result<LogExport>>;
101
102    /// Starts processing a log export.
103    ///
104    /// # Arguments
105    ///
106    /// * `export_id` - The unique identifier of the export to start
107    ///
108    /// # Returns
109    ///
110    /// Returns an `ExportTaskResponse` with status message.
111    ///
112    /// # Errors
113    ///
114    /// Returns an error if the export cannot be started or the API request fails.
115    fn start_log_export(&self, export_id: &str)
116    -> impl Future<Output = Result<ExportTaskResponse>>;
117
118    /// Cancels a running log export.
119    ///
120    /// # Arguments
121    ///
122    /// * `export_id` - The unique identifier of the export to cancel
123    ///
124    /// # Returns
125    ///
126    /// Returns an `ExportTaskResponse` with status message.
127    ///
128    /// # Errors
129    ///
130    /// Returns an error if the export cannot be canceled or the API request fails.
131    fn cancel_log_export(
132        &self,
133        export_id: &str,
134    ) -> impl Future<Output = Result<ExportTaskResponse>>;
135
136    /// Downloads a completed log export.
137    ///
138    /// # Arguments
139    ///
140    /// * `export_id` - The unique identifier of the export to download
141    ///
142    /// # Returns
143    ///
144    /// Returns a `DownloadLogExportResponse` with a pre-signed URL.
145    ///
146    /// # Errors
147    ///
148    /// Returns an error if the export is not ready or the API request fails.
149    fn download_log_export(
150        &self,
151        export_id: &str,
152    ) -> impl Future<Output = Result<DownloadLogExportResponse>>;
153
154    /// Inserts one or more custom logs.
155    ///
156    /// # Arguments
157    ///
158    /// * `request` - Either a single log or multiple logs to insert
159    ///
160    /// # Returns
161    ///
162    /// Returns an `InsertLogResponse` with status and log IDs.
163    ///
164    /// # Errors
165    ///
166    /// Returns an error if the API request fails or the response cannot be parsed.
167    fn insert_log(
168        &self,
169        request: InsertLogRequest,
170    ) -> impl Future<Output = Result<InsertLogResponse>>;
171
172    /// Updates an existing log export.
173    ///
174    /// # Arguments
175    ///
176    /// * `export_id` - The unique identifier of the export to update
177    /// * `request` - The updated export configuration
178    ///
179    /// # Returns
180    ///
181    /// Returns an `UpdateLogExportResponse` with the updated export ID and count.
182    ///
183    /// # Errors
184    ///
185    /// Returns an error if the export is not found or the API request fails.
186    fn update_log_export(
187        &self,
188        export_id: &str,
189        request: UpdateLogExportRequest,
190    ) -> impl Future<Output = Result<UpdateLogExportResponse>>;
191
192    /// Lists all log exports with optional workspace filter.
193    ///
194    /// # Arguments
195    ///
196    /// * `params` - Optional parameters for filtering exports
197    ///
198    /// # Returns
199    ///
200    /// Returns a `ListLogExportsResponse` with all matching exports.
201    ///
202    /// # Errors
203    ///
204    /// Returns an error if the API request fails or the response cannot be parsed.
205    fn list_log_exports(
206        &self,
207        params: Option<ListLogExportsParams>,
208    ) -> impl Future<Output = Result<ListLogExportsResponse>>;
209}
210
211impl LogsService for PortkeyClient {
212    async fn create_log_export(
213        &self,
214        request: CreateLogExportRequest,
215    ) -> Result<CreateLogExportResponse> {
216        #[cfg(feature = "tracing")]
217        tracing::debug!(
218            target: TRACING_TARGET_SERVICE,
219            workspace_id = ?request.workspace_id,
220            requested_data_count = request.requested_data.len(),
221            "Creating log export"
222        );
223
224        let response = self
225            .send_json(reqwest::Method::POST, "/logs/exports", &request)
226            .await?;
227        let response = response.error_for_status()?;
228        let export_response: CreateLogExportResponse = response.json().await?;
229
230        Ok(export_response)
231    }
232
233    async fn get_log_export(&self, export_id: &str) -> Result<LogExport> {
234        #[cfg(feature = "tracing")]
235        tracing::debug!(
236            target: TRACING_TARGET_SERVICE,
237            export_id = %export_id,
238            "Retrieving log export"
239        );
240
241        let path = format!("/logs/exports/{}", export_id);
242        let response = self.send(reqwest::Method::GET, &path).await?;
243        let response = response.error_for_status()?;
244        let export: LogExport = response.json().await?;
245
246        Ok(export)
247    }
248
249    async fn start_log_export(&self, export_id: &str) -> Result<ExportTaskResponse> {
250        #[cfg(feature = "tracing")]
251        tracing::debug!(
252            target: TRACING_TARGET_SERVICE,
253            export_id = %export_id,
254            "Starting log export"
255        );
256
257        let path = format!("/logs/exports/{}/start", export_id);
258        let response = self.send(reqwest::Method::POST, &path).await?;
259        let response = response.error_for_status()?;
260        let task_response: ExportTaskResponse = response.json().await?;
261
262        Ok(task_response)
263    }
264
265    async fn cancel_log_export(&self, export_id: &str) -> Result<ExportTaskResponse> {
266        #[cfg(feature = "tracing")]
267        tracing::debug!(
268            target: TRACING_TARGET_SERVICE,
269            export_id = %export_id,
270            "Canceling log export"
271        );
272
273        let path = format!("/logs/exports/{}/cancel", export_id);
274        let response = self.send(reqwest::Method::POST, &path).await?;
275        let response = response.error_for_status()?;
276        let task_response: ExportTaskResponse = response.json().await?;
277
278        Ok(task_response)
279    }
280
281    async fn download_log_export(&self, export_id: &str) -> Result<DownloadLogExportResponse> {
282        #[cfg(feature = "tracing")]
283        tracing::debug!(
284            target: TRACING_TARGET_SERVICE,
285            export_id = %export_id,
286            "Downloading log export"
287        );
288
289        let path = format!("/logs/exports/{}/download", export_id);
290        let response = self.send(reqwest::Method::GET, &path).await?;
291        let response = response.error_for_status()?;
292        let download_response: DownloadLogExportResponse = response.json().await?;
293
294        Ok(download_response)
295    }
296
297    async fn insert_log(&self, request: InsertLogRequest) -> Result<InsertLogResponse> {
298        #[cfg(feature = "tracing")]
299        tracing::debug!(
300            target: TRACING_TARGET_SERVICE,
301            "Inserting custom log(s)"
302        );
303
304        let response = self
305            .send_json(reqwest::Method::POST, "/logs", &request)
306            .await?;
307        let response = response.error_for_status()?;
308        let insert_response: InsertLogResponse = response.json().await?;
309
310        Ok(insert_response)
311    }
312
313    async fn update_log_export(
314        &self,
315        export_id: &str,
316        request: UpdateLogExportRequest,
317    ) -> Result<UpdateLogExportResponse> {
318        #[cfg(feature = "tracing")]
319        tracing::debug!(
320            target: TRACING_TARGET_SERVICE,
321            export_id = %export_id,
322            workspace_id = ?request.workspace_id,
323            "Updating log export"
324        );
325
326        let path = format!("/logs/exports/{}", export_id);
327        let response = self
328            .send_json(reqwest::Method::PUT, &path, &request)
329            .await?;
330        let response = response.error_for_status()?;
331        let update_response: UpdateLogExportResponse = response.json().await?;
332
333        Ok(update_response)
334    }
335
336    async fn list_log_exports(
337        &self,
338        params: Option<ListLogExportsParams>,
339    ) -> Result<ListLogExportsResponse> {
340        #[cfg(feature = "tracing")]
341        tracing::debug!(
342            target: TRACING_TARGET_SERVICE,
343            workspace_id = ?params.as_ref().and_then(|p| p.workspace_id.as_ref()),
344            "Listing log exports"
345        );
346
347        let response = if let Some(p) = params
348            && let Some(workspace_id) = p.workspace_id
349        {
350            self.send_with_params(
351                reqwest::Method::GET,
352                "/logs/exports",
353                &[("workspace_id", workspace_id.as_str())],
354            )
355            .await?
356        } else {
357            self.send(reqwest::Method::GET, "/logs/exports").await?
358        };
359
360        let response = response.error_for_status()?;
361        let list_response: ListLogExportsResponse = response.json().await?;
362
363        Ok(list_response)
364    }
365}