1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use std::error::Error;

use reqwest::{Client, StatusCode, Url};

use crate::models::structured_data::{IngestStructuredDataError, StructuredLogsIngestRequest};

#[derive(Clone)]
pub struct LogScaleClient {
    logscale_url: Url,
    ingest_token: String,
    http_client: Client,
    ingest_token_header_value: String,
}

impl LogScaleClient {
    pub fn from_url(logscale_url: &str, ingest_token: String) -> Result<Self, Box<dyn Error>> {
        let url = Url::parse(logscale_url)?;

        Ok(Self {
            logscale_url: url,
            ingest_token: ingest_token.clone(),
            http_client: Client::default(),
            ingest_token_header_value: format!("Bearer {}", &ingest_token),
        })
    }

    pub async fn ingest_structured<'b>(
        &self,
        request: &[StructuredLogsIngestRequest<'b>],
    ) -> Result<(), IngestStructuredDataError> {
        let url = self
            .logscale_url
            .join("api/v1/ingest/humio-structured")
            .unwrap();

        if let Ok(response) = self
            .http_client
            .post(url)
            .header("Authorization", &self.ingest_token_header_value)
            .json(&request)
            .send()
            .await
        {
            let response_status_code = response.status();

            if response_status_code == StatusCode::OK {
                Ok(())
            } else {
                Err(
                    IngestStructuredDataError::RequestStatusCodeDidNotIndicateSuccess(
                        response_status_code,
                    ),
                )
            }
        } else {
            Err(IngestStructuredDataError::FailedSendingRequest)
        }
    }
}

unsafe impl Send for LogScaleClient {}
unsafe impl Sync for LogScaleClient {}