feldera-cloud1-client 0.1.3

Telemetry Client for Feldera Cloud1
Documentation
//! Telemetry events format exchanged between platform and telemetry service.

use crate::source_error;
use reqwest::StatusCode;
use serde::{Deserialize, Serialize};
use thiserror::Error as ThisError;
use utoipa::ToSchema;

/// Request to register a telemetry event.
/// Shared type between client and server.
#[derive(Serialize, Deserialize, Debug, ToSchema)]
pub struct RegisterTelemetryEventRequest {
    pub account_id: String,
    pub license_key: String,
    pub event: TelemetryEvent,
}

#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
pub enum TelemetryEvent {
    /// Pipeline provisioning succeeded.
    PipelineProvisioned { id_hash: String },
    /// Pipeline shutdown finished successfully.
    PipelineShutdownFinished { id_hash: String },
    /// Statistics update about a deployed pipeline.
    PipelineStatistics {
        id_hash: String,
        statistics: serde_json::Value,
    },
}

/// Enumeration of the errors that can occur during registering a telemetry event.
#[derive(ThisError, Clone, Debug, PartialEq)]
pub enum RegisterTelemetryEventError {
    #[error("failed to serialize request to JSON due to {error}")]
    SerializeRequestToJsonFailed { error: String },
    #[error("failed to send request due to {error}")]
    SendRequestFailed { error: String },
    #[error("HTTP status code ({0}) received back with the response is unexpected")]
    UnexpectedResponseStatusCode(StatusCode),
}

/// Registers a telemetry event at the API endpoint.
pub async fn register_telemetry_event(
    // HTTP client
    client: &reqwest::Client,
    // Cloud API endpoint
    cloud_api_endpoint: &str,
    // Identifier of the account to which the license belongs
    account_id: &str,
    // License key
    license_key: &str,
    // Event that occurred
    event: TelemetryEvent,
) -> Result<(), RegisterTelemetryEventError> {
    let endpoint = format!("{cloud_api_endpoint}/telemetry/event");

    match serde_json::to_value(RegisterTelemetryEventRequest {
        account_id: account_id.to_string(),
        license_key: license_key.to_string(),
        event,
    }) {
        Ok(request) => {
            let result = client.post(&endpoint).json(&request).send().await;
            match result {
                Ok(response) => {
                    let status_code = response.status();
                    if status_code == StatusCode::OK {
                        Ok(())
                    } else {
                        Err(RegisterTelemetryEventError::UnexpectedResponseStatusCode(
                            status_code,
                        ))
                    }
                }
                Err(e) => {
                    let source_err = source_error(&e);
                    let error = format!("{e}, source: {source_err}");
                    Err(RegisterTelemetryEventError::SendRequestFailed { error })
                }
            }
        }
        Err(e) => Err(RegisterTelemetryEventError::SerializeRequestToJsonFailed {
            error: e.to_string(),
        }),
    }
}