statsig_rust/event_logging_adapter/
log_event_payload.rs

1use serde::{Deserialize, Serialize};
2use serde_json::{from_value, json, Value};
3use std::collections::HashSet;
4
5use crate::{event_logging::statsig_event_internal::StatsigEventInternal, StatsigErr};
6
7#[derive(Clone, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase")]
9pub struct LogEventPayload {
10    pub events: Value,
11    pub statsig_metadata: Value,
12}
13
14#[derive(Serialize, Deserialize)]
15#[serde(rename_all = "camelCase")]
16pub struct LogEventRequest {
17    pub payload: LogEventPayload,
18    pub event_count: u64,
19}
20
21impl LogEventRequest {
22    pub fn merge(&mut self, other: &LogEventRequest) -> Result<(), StatsigErr> {
23        let right = parse_events(&self.payload.events)?;
24        let left = parse_events(&other.payload.events)?;
25
26        let mut expo_keys = HashSet::new();
27        let mut merged_events = vec![];
28
29        merge_event_into(right, &mut expo_keys, &mut merged_events);
30        merge_event_into(left, &mut expo_keys, &mut merged_events);
31
32        self.payload.events = json!(merged_events);
33        self.event_count = merged_events.len() as u64;
34
35        Ok(())
36    }
37}
38
39fn parse_events(events: &Value) -> Result<Vec<StatsigEventInternal>, StatsigErr> {
40    match from_value(events.clone()) {
41        Ok(events) => Ok(events),
42        Err(e) => Err(StatsigErr::JsonParseError(
43            stringify!(Vec<StatsigEventInternal>).to_string(),
44            e.to_string(),
45        )),
46    }
47}
48
49fn merge_event_into(
50    events: Vec<StatsigEventInternal>,
51    expo_keys: &mut HashSet<String>,
52    merged_events: &mut Vec<StatsigEventInternal>,
53) {
54    for event in events {
55        if event.is_exposure_event() {
56            let key = create_merge_key(&event);
57            if expo_keys.contains(&key) {
58                continue;
59            }
60            expo_keys.insert(key);
61        }
62
63        merged_events.push(event);
64    }
65}
66
67fn create_merge_key(event: &StatsigEventInternal) -> String {
68    let mut metadata_string = String::new();
69    if let Some(metadata) = &event.event_data.metadata {
70        metadata_string = metadata
71            .values()
72            .cloned()
73            .collect::<Vec<String>>()
74            .join(",");
75    }
76
77    format!(
78        "{}|{}|{}",
79        event.event_data.event_name, event.user.value, metadata_string
80    )
81}