antithesis_sdk/lifecycle.rs
1#[cfg(feature = "full")]
2use crate::{details, internal};
3use serde::Serialize;
4#[cfg(feature = "full")]
5use serde_json::{json, Map, Value};
6
7#[cfg(feature = "full")]
8#[derive(Serialize, Debug)]
9struct AntithesisSetupData<'a> {
10 status: &'a str,
11 #[serde(skip_serializing_if = "Option::is_none")]
12 details: Option<Map<String, Value>>,
13}
14
15#[cfg(feature = "full")]
16#[derive(Serialize, Debug)]
17struct SetupCompleteData<'a> {
18 antithesis_setup: AntithesisSetupData<'a>,
19}
20
21/// Indicates to Antithesis that setup has completed. Call this function when
22/// your system and workload are fully initialized. After this function is
23/// called, Antithesis will take a snapshot of your system and begin
24/// [injecting faults]( https://antithesis.com/docs/environment/fault_injection/).
25///
26/// Calling this function multiple times or from multiple processes will have no
27/// effect. Antithesis will treat the first time any process called this
28/// function as the moment that the setup was completed.
29///
30/// Details may be any borrowed value implementing `Serialize`. Objects are
31/// preserved; other non-null JSON values are wrapped under `"value"`, for
32/// example `3` becomes `{"value": 3}`. Pass `&()` or `&Value::Null` for no
33/// details; an explicit empty object is preserved. Serialization errors emit an
34/// `antithesis_error` message and omit details; the setup event is still
35/// emitted. With the `full` feature disabled, details are not serialized.
36///
37/// # Example
38///
39/// ```
40/// use serde_json::{json, Value};
41/// use antithesis_sdk::lifecycle;
42///
43/// let (num_nodes, main_id) = (10, "n-001");
44///
45/// let startup_data: Value = json!({
46/// "num_nodes": num_nodes,
47/// "main_node_id": main_id,
48/// });
49///
50/// lifecycle::setup_complete(&startup_data);
51/// ```
52pub fn setup_complete<T: Serialize + ?Sized>(details: &T) {
53 #[cfg(feature = "full")]
54 {
55 let antithesis_setup = AntithesisSetupData {
56 status: "complete",
57 details: details::object(details, "setup_complete"),
58 };
59 internal::dispatch_output(&SetupCompleteData { antithesis_setup });
60 }
61 #[cfg(not(feature = "full"))]
62 let _ = details;
63}
64
65/// Indicates to Antithesis that a certain event has been reached. It sends a
66/// structured log message to Antithesis that you may later use to aid
67/// debugging.
68///
69/// In addition to ``details``, you also provide ``name``, which is the name of
70/// the event that you are logging.
71///
72/// Details may be any borrowed value implementing `Serialize`. Objects are
73/// preserved; other non-null JSON values are wrapped under `"value"`, for
74/// example `3` becomes `{"value": 3}`. Null and serialization errors produce an
75/// empty event body `{}`. Serialization errors also emit an `antithesis_error`
76/// message. With the `full` feature disabled, details are not serialized.
77///
78/// # Example
79///
80/// ```
81/// use serde_json::{json, Value};
82/// use antithesis_sdk::lifecycle;
83///
84/// let info_value: Value = json!({
85/// "month": "July",
86/// "day": 17
87/// });
88///
89/// lifecycle::send_event("start_day", &info_value);
90/// ```
91pub fn send_event<T: Serialize + ?Sized>(name: &str, details: &T) {
92 // The name is passed through verbatim, like every other SDK: renaming
93 // or trimming here would make the same program emit different events
94 // depending on which SDK it was written against.
95 #[cfg(feature = "full")]
96 {
97 let json_event = json!({ name: details::object(details, name).unwrap_or_default() });
98 internal::dispatch_output(&json_event);
99 }
100 #[cfg(not(feature = "full"))]
101 let _ = (name, details);
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 use serde_json::{json, Value};
108
109 #[test]
110 fn setup_complete_without_details() {
111 eprintln!("setup_complete");
112 let details: Value = json!({});
113 setup_complete(&details);
114 }
115
116 #[test]
117 fn setup_complete_with_details() {
118 let details: Value = json!({
119 "name": "Meow Cat",
120 "age": 11,
121 "phones": [
122 "+1 2126581356",
123 "+1 2126581384"
124 ]
125 });
126 setup_complete(&details);
127 }
128
129 #[test]
130 fn send_event_without_details() {
131 let details: Value = json!({});
132 send_event("my event", &details);
133 }
134
135 #[test]
136 fn send_event_with_details() {
137 let details: Value = json!({
138 "name": "Tweety Bird",
139 "age": 4,
140 "phones": [
141 "+1 9734970340"
142 ]
143 });
144 send_event("my event 2", &details);
145 }
146
147 #[test]
148 fn send_event_unnamed_without_details() {
149 let details: Value = json!({});
150 send_event("", &details);
151 }
152
153 #[test]
154 fn send_event_unnamed_with_details() {
155 let details: Value = json!({
156 "color": "red"
157 });
158 send_event(" ", &details);
159 }
160}