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