Skip to content

Commit 1b027e5

Browse files
perf: build telemetry client in background
1 parent c7264c3 commit 1b027e5

File tree

2 files changed

+60
-38
lines changed
  • crates

2 files changed

+60
-38
lines changed

crates/turborepo-lib/src/cli/mod.rs

+10-16
Original file line numberDiff line numberDiff line change
@@ -1188,22 +1188,16 @@ fn initialize_telemetry_client(
11881188
color_config: ColorConfig,
11891189
version: &str,
11901190
) -> Option<TelemetryHandle> {
1191-
let mut telemetry_handle: Option<TelemetryHandle> = None;
1192-
match AnonAPIClient::new("https://telemetry.vercel.com", 250, version) {
1193-
Ok(anonymous_api_client) => {
1194-
let handle = init_telemetry(anonymous_api_client, color_config);
1195-
match handle {
1196-
Ok(h) => telemetry_handle = Some(h),
1197-
Err(error) => {
1198-
debug!("failed to start telemetry: {:?}", error)
1199-
}
1200-
}
1201-
}
1202-
Err(error) => {
1203-
debug!("Failed to create AnonAPIClient: {:?}", error);
1204-
}
1205-
}
1206-
telemetry_handle
1191+
// initialize telemetry
1192+
let client_version = version.to_string();
1193+
let client_builder = move || {
1194+
AnonAPIClient::new("https://telemetry.vercel.com", 250, &client_version)
1195+
.inspect_err(|e| debug!("failed setting up client: {e}"))
1196+
.ok()
1197+
};
1198+
init_telemetry(client_builder, color_config)
1199+
.inspect_err(|err| debug!("failed to start telemetry: {err}"))
1200+
.ok()
12071201
}
12081202

12091203
#[derive(PartialEq)]

crates/turborepo-telemetry/src/lib.rs

+50-22
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,14 @@ pub fn telem(event: events::TelemetryEvent) {
7575
}
7676
}
7777

78-
fn init(
78+
fn init<C>(
7979
mut config: TelemetryConfig,
80-
client: impl telemetry::TelemetryClient + Clone + Send + Sync + 'static,
80+
client: impl Send + FnOnce() -> Option<C> + 'static,
8181
color_config: ColorConfig,
82-
) -> Result<(TelemetryHandle, TelemetrySender), Box<dyn std::error::Error>> {
82+
) -> Result<(TelemetryHandle, TelemetrySender), Box<dyn std::error::Error>>
83+
where
84+
C: telemetry::TelemetryClient + Clone + Send + Sync + 'static,
85+
{
8386
let (tx, rx) = mpsc::unbounded_channel();
8487
let (cancel_tx, cancel_rx) = oneshot::channel();
8588
config.show_alert(color_config);
@@ -90,13 +93,12 @@ fn init(
9093
buffer: Vec::new(),
9194
senders: FuturesUnordered::new(),
9295
exit_ch: cancel_tx,
93-
client,
9496
session_id: session_id.to_string(),
9597
telemetry_id: config.get_id().to_string(),
9698
enabled: config.is_enabled(),
9799
color_config,
98100
};
99-
let handle = worker.start();
101+
let handle = worker.start(client);
100102

101103
let telemetry_handle = TelemetryHandle {
102104
exit_ch: cancel_rx,
@@ -113,10 +115,13 @@ fn init(
113115
/// We have two different types because the TelemetrySender should be shared
114116
/// across threads (i.e. Clone + Send), while the TelemetryHandle cannot be
115117
/// shared since it contains the structs necessary to shut down the worker.
116-
pub fn init_telemetry(
117-
client: impl telemetry::TelemetryClient + Clone + Send + Sync + 'static,
118+
pub fn init_telemetry<C>(
119+
client: impl Send + FnOnce() -> Option<C> + 'static,
118120
color_config: ColorConfig,
119-
) -> Result<TelemetryHandle, Box<dyn std::error::Error>> {
121+
) -> Result<TelemetryHandle, Box<dyn std::error::Error>>
122+
where
123+
C: telemetry::TelemetryClient + Clone + Send + Sync + 'static,
124+
{
120125
// make sure we're not already initialized
121126
if SENDER_INSTANCE.get().is_some() {
122127
debug!("telemetry already initialized");
@@ -147,22 +152,29 @@ impl TelemetryHandle {
147152
}
148153
}
149154

150-
struct Worker<C> {
155+
struct Worker {
151156
rx: mpsc::UnboundedReceiver<TelemetryEvent>,
152157
buffer: Vec<TelemetryEvent>,
153158
senders: FuturesUnordered<JoinHandle<()>>,
154159
// Used to cancel the worker
155160
exit_ch: oneshot::Sender<()>,
156-
client: C,
157161
telemetry_id: String,
158162
session_id: String,
159163
enabled: bool,
160164
color_config: ColorConfig,
161165
}
162166

163-
impl<C: telemetry::TelemetryClient + Clone + Send + Sync + 'static> Worker<C> {
164-
pub fn start(mut self) -> JoinHandle<()> {
167+
impl Worker {
168+
pub fn start<C>(mut self, client: impl FnOnce() -> Option<C> + Send + 'static) -> JoinHandle<()>
169+
where
170+
C: telemetry::TelemetryClient + Clone + Send + Sync + 'static,
171+
{
165172
tokio::spawn(async move {
173+
// Constructing a HTTPS client is almost always a blocking operation
174+
let Ok(Some(client)) = tokio::task::spawn_blocking(client).await else {
175+
// If constructing telemetry client panics, shut down
176+
return;
177+
};
166178
let mut timeout = tokio::time::sleep(NO_TIMEOUT);
167179
loop {
168180
select! {
@@ -176,22 +188,22 @@ impl<C: telemetry::TelemetryClient + Clone + Send + Sync + 'static> Worker<C> {
176188
break;
177189
}
178190
if self.buffer.len() == BUFFER_THRESHOLD {
179-
self.flush_events();
191+
self.flush_events(&client);
180192
timeout = tokio::time::sleep(NO_TIMEOUT);
181193
} else {
182194
timeout = tokio::time::sleep(EVENT_TIMEOUT);
183195
}
184196
}
185197
_ = timeout => {
186-
self.flush_events();
198+
self.flush_events(&client);
187199
timeout = tokio::time::sleep(NO_TIMEOUT);
188200
}
189201
_ = self.exit_ch.closed() => {
190202
break;
191203
}
192204
}
193205
}
194-
self.flush_events();
206+
self.flush_events(&client);
195207
while let Some(result) = self.senders.next().await {
196208
if let Err(err) = result {
197209
debug!("failed to send telemetry event. error: {}", err)
@@ -200,11 +212,18 @@ impl<C: telemetry::TelemetryClient + Clone + Send + Sync + 'static> Worker<C> {
200212
})
201213
}
202214

203-
pub fn flush_events(&mut self) {
215+
pub fn flush_events<C>(&mut self, client: &C)
216+
where
217+
C: telemetry::TelemetryClient + Clone + Send + Sync + 'static,
218+
{
204219
if !self.buffer.is_empty() {
205220
let events = std::mem::take(&mut self.buffer);
206221
let num_events = events.len();
207-
let handle = self.send_events(events);
222+
debug!(
223+
"Starting telemetry event queue flush (num_events={:?})",
224+
num_events
225+
);
226+
let handle = self.send_events(client, events);
208227
if let Some(handle) = handle {
209228
self.senders.push(handle);
210229
}
@@ -215,7 +234,10 @@ impl<C: telemetry::TelemetryClient + Clone + Send + Sync + 'static> Worker<C> {
215234
}
216235
}
217236

218-
fn send_events(&self, events: Vec<TelemetryEvent>) -> Option<JoinHandle<()>> {
237+
fn send_events<C>(&self, client: &C, events: Vec<TelemetryEvent>) -> Option<JoinHandle<()>>
238+
where
239+
C: telemetry::TelemetryClient + Clone + Send + Sync + 'static,
240+
{
219241
if !self.enabled {
220242
return None;
221243
}
@@ -232,7 +254,7 @@ impl<C: telemetry::TelemetryClient + Clone + Send + Sync + 'static> Worker<C> {
232254
}
233255
}
234256

235-
let client = self.client.clone();
257+
let client = client.clone();
236258
let session_id = self.session_id.clone();
237259
let telemetry_id = self.telemetry_id.clone();
238260
Some(tokio::spawn(async move {
@@ -341,8 +363,10 @@ mod tests {
341363
events: Default::default(),
342364
tx,
343365
};
366+
let client_copy = client.clone();
367+
let client_builder = move || Some(client_copy);
344368

345-
let result = init(config, client.clone(), ColorConfig::new(false));
369+
let result = init(config, client_builder, ColorConfig::new(false));
346370

347371
let (telemetry_handle, telemetry_sender) = result.unwrap();
348372

@@ -381,8 +405,10 @@ mod tests {
381405
events: Default::default(),
382406
tx,
383407
};
408+
let client_copy = client.clone();
409+
let client_builder = move || Some(client_copy);
384410

385-
let result = init(config, client.clone(), ColorConfig::new(false));
411+
let result = init(config, client_builder, ColorConfig::new(false));
386412

387413
let (telemetry_handle, telemetry_sender) = result.unwrap();
388414

@@ -427,8 +453,10 @@ mod tests {
427453
events: Default::default(),
428454
tx,
429455
};
456+
let client_copy = client.clone();
457+
let client_builder = move || Some(client_copy);
430458

431-
let result = init(config, client.clone(), ColorConfig::new(false));
459+
let result = init(config, client_builder, ColorConfig::new(false));
432460

433461
let (telemetry_handle, telemetry_sender) = result.unwrap();
434462

0 commit comments

Comments
 (0)