1use std::time::Duration;
2
3use reqwest::Certificate;
4use url::Url;
5
6use crate::identity::AnonymousDistinctId;
7use crate::storage::Storage;
8use crate::transport::{Transport, TransportsError};
9use crate::{DeviceId, DistinctId, Map, system_snapshot::SystemSnapshotter};
10use crate::{Groups, Recorder, Worker};
11
12#[derive(Default, Clone)]
13pub struct Builder {
14 device_id: Option<DeviceId>,
15 distinct_id: Option<DistinctId>,
16 anonymous_distinct_id: Option<AnonymousDistinctId>,
17 enable_reporting: bool,
18 endpoint: Option<String>,
19 facts: Option<Map>,
20 groups: Option<Groups>,
21 proxy: Option<Url>,
22 certificate: Option<Certificate>,
23 timeout: Option<Duration>,
24}
25
26impl Builder {
27 pub fn new() -> Self {
28 Builder {
29 device_id: None,
30 distinct_id: None,
31 anonymous_distinct_id: None,
32 enable_reporting: true,
33 endpoint: None,
34 facts: None,
35 groups: None,
36 proxy: None,
37 certificate: None,
38 timeout: None,
39 }
40 }
41
42 pub fn anonymous_distinct_id(
43 mut self,
44 anonymous_distinct_id: Option<AnonymousDistinctId>,
45 ) -> Self {
46 self.set_anonymous_distinct_id(anonymous_distinct_id);
47 self
48 }
49
50 pub fn set_anonymous_distinct_id(
51 &mut self,
52 anonymous_distinct_id: Option<AnonymousDistinctId>,
53 ) -> &mut Self {
54 self.anonymous_distinct_id = anonymous_distinct_id;
55 self
56 }
57
58 pub fn distinct_id(mut self, distinct_id: Option<DistinctId>) -> Self {
59 self.set_distinct_id(distinct_id);
60 self
61 }
62
63 pub fn set_distinct_id(&mut self, distinct_id: Option<DistinctId>) -> &mut Self {
64 self.distinct_id = distinct_id;
65 self
66 }
67
68 pub fn device_id(mut self, device_id: Option<DeviceId>) -> Self {
69 self.set_device_id(device_id);
70 self
71 }
72
73 pub fn set_device_id(&mut self, device_id: Option<DeviceId>) -> &mut Self {
74 self.device_id = device_id;
75 self
76 }
77
78 pub fn facts(mut self, facts: Option<Map>) -> Self {
79 self.set_facts(facts);
80 self
81 }
82
83 pub fn set_facts(&mut self, facts: Option<Map>) -> &mut Self {
84 self.facts = facts;
85 self
86 }
87
88 pub fn groups(mut self, groups: Option<Groups>) -> Self {
89 self.set_groups(groups);
90 self
91 }
92
93 pub fn set_groups(&mut self, groups: Option<Groups>) -> &mut Self {
94 self.groups = groups;
95 self
96 }
97
98 pub fn fact(mut self, key: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
99 self.set_fact(key, value);
100 self
101 }
102
103 pub fn set_fact(
104 &mut self,
105 key: impl Into<String>,
106 value: impl Into<serde_json::Value>,
107 ) -> &mut Self {
108 self.facts
109 .get_or_insert_with(Default::default)
110 .insert(key.into(), value.into());
111 self
112 }
113
114 pub fn endpoint(mut self, endpoint: Option<String>) -> Self {
115 self.set_endpoint(endpoint);
116 self
117 }
118
119 pub fn set_endpoint(&mut self, endpoint: Option<String>) -> &mut Self {
120 self.endpoint = endpoint;
121 self
122 }
123
124 pub fn enable_reporting(mut self, enable_reporting: bool) -> Self {
146 self.set_enable_reporting(enable_reporting);
147 self
148 }
149
150 pub fn set_enable_reporting(&mut self, enable_reporting: bool) -> &mut Self {
151 self.enable_reporting = enable_reporting;
152 self
153 }
154
155 pub fn timeout(mut self, duration: Option<Duration>) -> Self {
156 self.set_timeout(duration);
157 self
158 }
159
160 pub fn set_timeout(&mut self, duration: Option<Duration>) -> &mut Self {
161 self.timeout = duration;
162 self
163 }
164
165 pub fn certificate(mut self, certificate: Option<Certificate>) -> Self {
166 self.set_certificate(certificate);
167 self
168 }
169
170 pub fn set_certificate(&mut self, certificate: Option<Certificate>) -> &mut Self {
171 self.certificate = certificate;
172 self
173 }
174
175 pub fn proxy(mut self, proxy: Option<Url>) -> Self {
176 self.set_proxy(proxy);
177 self
178 }
179
180 pub fn set_proxy(&mut self, proxy: Option<Url>) -> &mut Self {
181 self.proxy = proxy;
182 self
183 }
184
185 #[tracing::instrument(skip(self))]
186 pub async fn try_build(mut self) -> Result<(Recorder, Worker), TransportsError> {
187 let transport = self.transport().await?;
188
189 Ok(self
190 .build_with(
191 transport,
192 crate::system_snapshot::Generic::default(),
193 crate::storage::DefaultStorageChain::new().await,
194 )
195 .await)
196 }
197
198 #[tracing::instrument(skip(self))]
199 pub async fn build_or_default(mut self) -> (Recorder, Worker) {
200 let transport = self.transport_or_default().await;
201
202 self.build_with(
203 transport,
204 crate::system_snapshot::Generic::default(),
205 crate::storage::DefaultStorageChain::new().await,
206 )
207 .await
208 }
209
210 #[tracing::instrument(skip(self, snapshotter, storage))]
211 pub async fn try_build_with<S: SystemSnapshotter, P: Storage>(
212 mut self,
213 snapshotter: S,
214 storage: P,
215 ) -> Result<(Recorder, Worker), TransportsError> {
216 let transport = self.transport().await?;
217
218 Ok(self.build_with(transport, snapshotter, storage).await)
219 }
220
221 #[tracing::instrument(skip(self, snapshotter, storage))]
222 pub async fn build_or_default_with<S: SystemSnapshotter, P: Storage>(
223 mut self,
224 snapshotter: S,
225 storage: P,
226 ) -> (Recorder, Worker) {
227 let transport = self.transport_or_default().await;
228
229 self.build_with(transport, snapshotter, storage).await
230 }
231
232 #[tracing::instrument(skip(self, transport, snapshotter, storage))]
233 pub(crate) async fn build_with<T: Transport, S: SystemSnapshotter, P: Storage>(
234 &mut self,
235 transport: T,
236 snapshotter: S,
237 storage: P,
238 ) -> (Recorder, Worker) {
239 Worker::new(
240 self.anonymous_distinct_id.take(),
241 self.distinct_id.take(),
242 self.device_id.take(),
243 self.facts.take(),
244 self.groups.take(),
245 snapshotter,
246 storage,
247 transport,
248 )
249 .await
250 }
251
252 async fn transport_or_default(&mut self) -> crate::transport::Transports {
253 match self.transport().await {
254 Ok(t) => {
255 return t;
256 }
257 Err(e) => {
258 tracing::warn!(%e, "Failed to construct the transport as configured, falling back to the default");
259 }
260 }
261
262 match crate::transport::Transports::try_new(
263 None,
264 self.timeout
265 .take()
266 .unwrap_or_else(|| Duration::from_secs(3)),
267 None,
268 None,
269 )
270 .await
271 {
272 Ok(t) => {
273 return t;
274 }
275 Err(e) => {
276 tracing::warn!(%e, "Failed to construct the default transport, falling back to none");
277 }
278 }
279
280 crate::transport::Transports::none()
281 }
282
283 async fn transport(&mut self) -> Result<crate::transport::Transports, TransportsError> {
284 if self.enable_reporting {
285 crate::transport::Transports::try_new(
286 self.endpoint.take(),
287 self.timeout.unwrap_or_else(|| Duration::from_secs(3)),
288 self.certificate.take(),
289 self.proxy.take(),
290 )
291 .await
292 } else {
293 Ok(crate::transport::Transports::none())
294 }
295 }
296}