statsig_rust/event_logging/event_queue/
queued_event.rs1use super::{
2 queued_config_expo::QueuedConfigExposureEvent,
3 queued_experiment_expo::QueuedExperimentExposureEvent, queued_expo::QueuedExposureEvent,
4 queued_gate_expo::QueuedGateExposureEvent,
5 queued_layer_param_expo::QueuedLayerParamExposureEvent,
6 queued_secondary_expo::QueuedSecondaryExposureAsPrimaryEvent,
7};
8use crate::{
9 evaluation::evaluation_types::ExtraExposureInfo,
10 event_logging::{
11 exposure_sampling::{EvtSamplingDecision, ExposureSamplingKey},
12 statsig_event_internal::StatsigEventInternal,
13 },
14 user::StatsigUserLoggable,
15 SecondaryExposure,
16};
17
18pub trait EnqueueOperation {
19 fn as_exposure(&self) -> Option<&impl QueuedExposure<'_>>;
20 fn into_queued_event(self, sampling_decision: EvtSamplingDecision) -> QueuedEvent;
21}
22
23pub trait QueuedExposure<'a> {
24 fn create_exposure_sampling_key(&self) -> ExposureSamplingKey;
25 fn get_rule_id_ref(&'a self) -> &'a str;
26 fn get_extra_exposure_info_ref(&'a self) -> Option<&'a ExtraExposureInfo>;
27}
28
29pub enum QueuedEvent {
30 Exposure(QueuedExposureEvent),
31 Passthrough(StatsigEventInternal),
32
33 GateExposure(QueuedGateExposureEvent),
35 ConfigExposure(QueuedConfigExposureEvent),
36 ExperimentExposure(QueuedExperimentExposureEvent),
37 LayerParamExposure(QueuedLayerParamExposureEvent),
38 SecondaryExposureAsPrimary(QueuedSecondaryExposureAsPrimaryEvent),
39}
40
41impl QueuedEvent {
42 pub fn into_statsig_event_internal(self) -> StatsigEventInternal {
43 match self {
44 QueuedEvent::Exposure(event) => event.into_statsig_event_internal(),
45 QueuedEvent::Passthrough(event) => event,
46
47 QueuedEvent::GateExposure(event) => event.into_statsig_event_internal(),
48 QueuedEvent::ConfigExposure(event) => event.into_statsig_event_internal(),
49 QueuedEvent::ExperimentExposure(event) => event.into_statsig_event_internal(),
50 QueuedEvent::LayerParamExposure(event) => event.into_statsig_event_internal(),
51 QueuedEvent::SecondaryExposureAsPrimary(event) => event.into_statsig_event_internal(),
52 }
53 }
54
55 pub fn exposure_time(&self) -> Option<u64> {
56 match self {
57 QueuedEvent::Exposure(event) => Some(event.data.exposure_time),
58 QueuedEvent::GateExposure(event) => Some(event.exposure_time),
59 QueuedEvent::ConfigExposure(event) => Some(event.exposure_time),
60 QueuedEvent::ExperimentExposure(event) => Some(event.exposure_time),
61 QueuedEvent::LayerParamExposure(event) => Some(event.exposure_time),
62 QueuedEvent::SecondaryExposureAsPrimary(event) => Some(event.exposure_time),
63 QueuedEvent::Passthrough(_) => None,
64 }
65 }
66
67 pub fn user_for_secondary_exposures(&self) -> Option<StatsigUserLoggable> {
68 match self {
69 QueuedEvent::Exposure(event) => Some(event.user.clone()),
70 QueuedEvent::GateExposure(event) => Some(event.user.clone()),
71 QueuedEvent::ConfigExposure(event) => Some(event.user.clone()),
72 QueuedEvent::ExperimentExposure(event) => Some(event.user.clone()),
73 QueuedEvent::LayerParamExposure(event) => Some(event.user.clone()),
74 QueuedEvent::SecondaryExposureAsPrimary(event) => Some(event.user.clone()),
75 QueuedEvent::Passthrough(_) => None,
76 }
77 }
78
79 pub fn take_secondary_exposures_for_primary_logging(&mut self) -> Vec<SecondaryExposure> {
80 match self {
81 QueuedEvent::Exposure(event) => event.take_secondary_exposures_for_primary_logging(),
82 QueuedEvent::GateExposure(event) => {
83 take_non_empty_secondary_exposures(&mut event.secondary_exposures)
84 }
85 QueuedEvent::ConfigExposure(event) => {
86 take_non_empty_secondary_exposures(&mut event.secondary_exposures)
87 }
88 QueuedEvent::ExperimentExposure(event) => {
89 take_non_empty_secondary_exposures(&mut event.secondary_exposures)
90 }
91 QueuedEvent::LayerParamExposure(event) => {
92 take_non_empty_secondary_exposures(&mut event.secondary_exposures)
93 }
94 QueuedEvent::Passthrough(_) | QueuedEvent::SecondaryExposureAsPrimary(_) => Vec::new(),
95 }
96 }
97}
98
99pub(crate) fn take_non_empty_secondary_exposures(
100 secondary_exposures: &mut Option<Vec<SecondaryExposure>>,
101) -> Vec<SecondaryExposure> {
102 match secondary_exposures.take() {
103 Some(exposures) if !exposures.is_empty() => {
104 *secondary_exposures = Some(Vec::new());
105 exposures
106 }
107 original => {
108 *secondary_exposures = original;
109 Vec::new()
110 }
111 }
112}