cx_sdk/client/
integrations.rs

1// Copyright 2025 Coralogix Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::str::FromStr;
16
17use crate::{
18    auth::AuthContext,
19    error::{
20        Result,
21        SdkApiError,
22        SdkError,
23    },
24    metadata::CallProperties,
25    util::make_request_with_metadata,
26};
27
28use cx_api::proto::com::coralogix::integrations::v1::{
29    DeleteIntegrationRequest,
30    DeleteIntegrationResponse,
31    GenericIntegrationParameters,
32    GetDeployedIntegrationRequest,
33    GetDeployedIntegrationResponse,
34    GetIntegrationDefinitionRequest,
35    GetIntegrationDefinitionResponse,
36    GetIntegrationDetailsRequest,
37    GetIntegrationDetailsResponse,
38    GetIntegrationsRequest,
39    GetIntegrationsResponse,
40    GetManagedIntegrationStatusRequest,
41    GetManagedIntegrationStatusResponse,
42    GetRumApplicationVersionDataRequest,
43    GetRumApplicationVersionDataResponse,
44    GetTemplateRequest,
45    GetTemplateResponse,
46    IntegrationMetadata,
47    SaveIntegrationRequest,
48    SaveIntegrationResponse,
49    SyncRumDataRequest,
50    SyncRumDataResponse,
51    TestIntegrationRequest,
52    TestIntegrationResponse,
53    UpdateIntegrationRequest,
54    UpdateIntegrationResponse,
55    integration_metadata::SpecificData,
56    integration_service_client::IntegrationServiceClient,
57};
58
59pub use cx_api::proto::com::coralogix::integrations::v1::{
60    Parameter,
61    integration_details::default_integration_details::*,
62    integration_details::*,
63    parameter::*,
64    test_integration_result::Result as TestResult,
65};
66
67use tokio::sync::Mutex;
68use tonic::{
69    metadata::MetadataMap,
70    transport::{
71        Channel,
72        ClientTlsConfig,
73        Endpoint,
74    },
75};
76
77use crate::CoralogixRegion;
78
79const INTEGRATIONS_FEATURE_GROUP_ID: &str = "integrations";
80
81/// The Integration API client.
82/// Read more at <https://coralogix.com/docs/user-team-management/>
83pub struct IntegrationsClient {
84    metadata_map: MetadataMap,
85    service_client: Mutex<IntegrationServiceClient<Channel>>,
86}
87
88impl IntegrationsClient {
89    /// Creates a new client for the Integrations API.
90    ///
91    /// # Arguments
92    /// * `auth_context` - The [`AuthContext`] to use for authentication.
93    /// * `region` - The [`CoralogixRegion`] to connect to.
94    pub fn new(auth_context: AuthContext, region: CoralogixRegion) -> Result<Self> {
95        let channel: Channel = Endpoint::from_str(region.grpc_endpoint().as_str())?
96            .tls_config(ClientTlsConfig::new().with_native_roots())?
97            .connect_lazy();
98        let request_metadata: CallProperties = (&auth_context.team_level_api_key).into();
99        Ok(Self {
100            metadata_map: request_metadata.to_metadata_map(),
101            service_client: Mutex::new(IntegrationServiceClient::new(channel)),
102        })
103    }
104
105    /// Creates a new Integration in the organization.
106    ///
107    /// # Arguments
108    /// * `integration_key` - The key of the integration to update.
109    /// * `version` - The version of the integration to update.
110    /// * `parameters` - The parameters of the integration to update.
111    pub async fn create(
112        &self,
113        integration_key: String,
114        version: Option<String>,
115        parameters: Option<Vec<Parameter>>,
116    ) -> Result<SaveIntegrationResponse> {
117        let request = make_request_with_metadata(
118            SaveIntegrationRequest {
119                metadata: Some(IntegrationMetadata {
120                    integration_key: Some(integration_key),
121                    version,
122                    specific_data: parameters.map(|p| {
123                        SpecificData::IntegrationParameters(GenericIntegrationParameters {
124                            parameters: p,
125                        })
126                    }),
127                }),
128            },
129            &self.metadata_map,
130        );
131        self.service_client
132            .lock()
133            .await
134            .save_integration(request)
135            .await
136            .map(|r| r.into_inner())
137            .map_err(|status| {
138                SdkError::ApiError(SdkApiError {
139                    status,
140                    endpoint:
141                        "/com.coralogixapis.integrations.v1.IntegrationService/SaveIntegration"
142                            .into(),
143                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
144                })
145            })
146    }
147
148    /// Update the Integration identified by its id.
149    ///
150    /// # Arguments
151    /// * `id` - The id of the integration to update.
152    /// * `integration_key` - The key of the integration to update.
153    /// * `version` - The version of the integration to update.
154    /// * `parameters` - The parameters of the integration to update.
155    pub async fn update(
156        &self,
157        id: String,
158        integration_key: String,
159        version: Option<String>,
160        parameters: Option<Vec<Parameter>>,
161    ) -> Result<UpdateIntegrationResponse> {
162        let request = make_request_with_metadata(
163            UpdateIntegrationRequest {
164                id: Some(id),
165                metadata: Some(IntegrationMetadata {
166                    integration_key: Some(integration_key),
167                    version,
168                    specific_data: parameters.map(|p| {
169                        SpecificData::IntegrationParameters(GenericIntegrationParameters {
170                            parameters: p,
171                        })
172                    }),
173                }),
174            },
175            &self.metadata_map,
176        );
177        self.service_client
178            .lock()
179            .await
180            .update_integration(request)
181            .await
182            .map(|r| r.into_inner())
183            .map_err(|status| {
184                SdkError::ApiError(SdkApiError {
185                    status,
186                    endpoint:
187                        "/com.coralogixapis.integrations.v1.IntegrationService/UpdateIntegration"
188                            .into(),
189                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
190                })
191            })
192    }
193
194    /// Deletes the Integration identified by its id.
195    ///
196    /// # Arguments
197    /// * `id` - The id of the integration to delete.
198    pub async fn delete(&self, id: String) -> Result<DeleteIntegrationResponse> {
199        let request = make_request_with_metadata(
200            DeleteIntegrationRequest {
201                integration_id: Some(id),
202            },
203            &self.metadata_map,
204        );
205
206        self.service_client
207            .lock()
208            .await
209            .delete_integration(request)
210            .await
211            .map(|r| r.into_inner())
212            .map_err(|status| {
213                SdkError::ApiError(SdkApiError {
214                    status,
215                    endpoint:
216                        "/com.coralogixapis.integrations.v1.IntegrationService/DeleteIntegration"
217                            .into(),
218                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
219                })
220            })
221    }
222
223    /// Retrieves the Integration identified by its id.
224    ///
225    /// # Arguments
226    /// * `id` - The id of the integration to retrieve.
227    /// * `include_testing_revision` - Whether to include the testing revision.
228    pub async fn get_details(
229        &self,
230        id: String,
231        include_testing_revision: bool,
232    ) -> Result<GetIntegrationDetailsResponse> {
233        let request = make_request_with_metadata(
234            GetIntegrationDetailsRequest {
235                id: Some(id),
236                include_testing_revision: Some(include_testing_revision),
237            },
238            &self.metadata_map,
239        );
240
241        self.service_client
242            .lock()
243            .await
244            .get_integration_details(request)
245            .await
246            .map(|r| r.into_inner())
247            .map_err(
248                |status| SdkError::ApiError(SdkApiError {
249                    status,
250                    endpoint: "/com.coralogixapis.integrations.v1.IntegrationService/GetIntegrationDetails"
251                        .into(),
252                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
253                }),
254            )
255    }
256
257    /// Retrieves the Deployed Integration identified by its id.
258    ///
259    /// # Arguments
260    /// * `id` - The id of the deployed integration to retrieve.
261    pub async fn get(&self, id: String) -> Result<GetDeployedIntegrationResponse> {
262        let request = make_request_with_metadata(
263            GetDeployedIntegrationRequest {
264                integration_id: Some(id),
265            },
266            &self.metadata_map,
267        );
268
269        self.service_client
270            .lock()
271            .await
272            .get_deployed_integration(request)
273            .await
274            .map(|r| r.into_inner())
275            .map_err(
276                |status| SdkError::ApiError(SdkApiError {
277                    status,
278                    endpoint: "/com.coralogixapis.integrations.v1.IntegrationService/GetDeployedIntegration"
279                        .into(),
280                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
281                }),
282            )
283    }
284
285    /// Retrieves the Integration definition identified by its id.
286    ///
287    /// # Arguments
288    /// * `id` - The id of the integration to retrieve.
289    /// * `include_testing_revision` - Whether to include the testing revision.
290    pub async fn get_definitions(
291        &self,
292        id: String,
293        include_testing_revision: bool,
294    ) -> Result<GetIntegrationDefinitionResponse> {
295        let request = make_request_with_metadata(
296            GetIntegrationDefinitionRequest {
297                id: Some(id),
298                include_testing_revision: Some(include_testing_revision),
299            },
300            &self.metadata_map,
301        );
302
303        self.service_client
304            .lock()
305            .await
306            .get_integration_definition(request)
307            .await
308            .map(|r| r.into_inner())
309            .map_err(
310                |status| SdkError::ApiError(SdkApiError {
311                    status,
312                    endpoint: "/com.coralogixapis.integrations.v1.IntegrationService/GetIntegrationDefinition"
313                        .into(),
314                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
315                }),
316            )
317    }
318
319    /// Retrieves the Integration status identified by its id.
320    ///
321    /// # Arguments
322    /// * `id` - The id of the integration to retrieve.
323    pub async fn get_integration_status(
324        &self,
325        id: String,
326    ) -> Result<GetManagedIntegrationStatusResponse> {
327        let request = make_request_with_metadata(
328            GetManagedIntegrationStatusRequest { integration_id: id },
329            &self.metadata_map,
330        );
331
332        self.service_client
333            .lock()
334            .await
335            .get_managed_integration_status(request)
336            .await
337            .map(|r| r.into_inner())
338            .map_err(
339                |status| SdkError::ApiError(SdkApiError {
340                    status,
341                    endpoint: "/com.coralogixapis.integrations.v1.IntegrationService/GetManagedIntegrationStatus"
342                        .into(),
343                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
344                }),
345            )
346    }
347
348    /// Retrieves the Integration template identified by its id.
349    ///
350    /// # Arguments
351    /// * `id` - The id of the integration to retrieve.
352    pub async fn get_template(&self, id: String) -> Result<GetTemplateResponse> {
353        let request = make_request_with_metadata(
354            GetTemplateRequest {
355                integration_id: Some(id),
356                extra_params: Default::default(), // TODO: expose these parameters somehow?
357            },
358            &self.metadata_map,
359        );
360
361        self.service_client
362            .lock()
363            .await
364            .get_template(request)
365            .await
366            .map(|r| r.into_inner())
367            .map_err(|status| {
368                SdkError::ApiError(SdkApiError {
369                    status,
370                    endpoint: "/com.coralogixapis.integrations.v1.IntegrationService/GetTemplate"
371                        .into(),
372                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
373                })
374            })
375    }
376
377    /// Retrieves the RUM application version data.
378    ///
379    /// # Arguments
380    /// * `application_name` - The name of the application.
381    pub async fn get_rum_application_version_data(
382        &self,
383        application_name: String,
384    ) -> Result<GetRumApplicationVersionDataResponse> {
385        let request = make_request_with_metadata(
386            GetRumApplicationVersionDataRequest {
387                application_name: Some(application_name),
388            },
389            &self.metadata_map,
390        );
391
392        self.service_client
393            .lock()
394            .await
395            .get_rum_application_version_data(request)
396            .await
397            .map(|r| r.into_inner())
398            .map_err(
399                |status| SdkError::ApiError(SdkApiError {
400                    status,
401                    endpoint: "/com.coralogixapis.integrations.v1.IntegrationService/GetRumApplicationVersionData"
402                        .into(),
403                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
404                }),
405            )
406    }
407
408    /// Synchronizes the RUM data.
409    ///
410    /// # Arguments
411    /// * `force` - Whether to force the synchronization.
412    pub async fn sync_rum_data(&self, force: bool) -> Result<SyncRumDataResponse> {
413        let request = make_request_with_metadata(
414            SyncRumDataRequest { force: Some(force) },
415            &self.metadata_map,
416        );
417
418        self.service_client
419            .lock()
420            .await
421            .sync_rum_data(request)
422            .await
423            .map(|r| r.into_inner())
424            .map_err(|status| {
425                SdkError::ApiError(SdkApiError {
426                    status,
427                    endpoint: "/com.coralogixapis.integrations.v1.IntegrationService/SyncRumData"
428                        .into(),
429                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
430                })
431            })
432    }
433
434    /// Tests the Integration identified by its id.
435    ///
436    /// # Arguments
437    /// * `id` - The id of the integration to test.
438    /// * `integration_key` - The key of the integration to test.
439    /// * `version` - The version of the integration to test.
440    /// * `parameters` - The parameters of the integration to test.
441    pub async fn test_integration(
442        &self,
443        integration_id: Option<String>,
444        integration_key: String,
445        version: Option<String>,
446        parameters: Option<Vec<Parameter>>,
447    ) -> Result<TestIntegrationResponse> {
448        let request = make_request_with_metadata(
449            TestIntegrationRequest {
450                integration_id,
451                integration_data: Some(IntegrationMetadata {
452                    integration_key: Some(integration_key),
453                    version,
454                    specific_data: parameters.map(|p| {
455                        SpecificData::IntegrationParameters(GenericIntegrationParameters {
456                            parameters: p,
457                        })
458                    }),
459                }),
460            },
461            &self.metadata_map,
462        );
463
464        self.service_client
465            .lock()
466            .await
467            .test_integration(request)
468            .await
469            .map(|r| r.into_inner())
470            .map_err(|status| {
471                SdkError::ApiError(SdkApiError {
472                    status,
473                    endpoint:
474                        "/com.coralogixapis.integrations.v1.IntegrationService/TestIntegration"
475                            .into(),
476                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
477                })
478            })
479    }
480
481    /// Retrieves a list of all Integrations.
482    ///     
483    /// # Returns
484    /// A list of all Integrations.
485    pub async fn list(&self, include_testing_revision: bool) -> Result<GetIntegrationsResponse> {
486        let request = make_request_with_metadata(
487            GetIntegrationsRequest {
488                include_testing_revision: Some(include_testing_revision),
489            },
490            &self.metadata_map,
491        );
492
493        self.service_client
494            .lock()
495            .await
496            .get_integrations(request)
497            .await
498            .map(|r| r.into_inner())
499            .map_err(|status| {
500                SdkError::ApiError(SdkApiError {
501                    status,
502                    endpoint:
503                        "/com.coralogixapis.integrations.v1.IntegrationService/GetIntegrations"
504                            .into(),
505                    feature_group: INTEGRATIONS_FEATURE_GROUP_ID.into(),
506                })
507            })
508    }
509}