Skip to content

Commit d073586

Browse files
authored
Add USDT probes for Nexus background tasks (#8567)
Partially closes #8424
1 parent 459c005 commit d073586

File tree

5 files changed

+86
-1
lines changed

5 files changed

+86
-1
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

nexus/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ tokio-postgres = { workspace = true, features = ["with-serde_json-1"] }
110110
tokio-util = { workspace = true, features = ["codec"] }
111111
tough.workspace = true
112112
tufaceous-artifact.workspace = true
113+
usdt.workspace = true
113114
uuid.workspace = true
114115

115116
nexus-auth.workspace = true

nexus/src/app/background/driver.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
//! None of this file is specific to Nexus or any of the specific background
88
//! tasks in Nexus, although the design is pretty bespoke for what Nexus needs.
99
10+
use crate::app::background::probes;
11+
1012
use super::BackgroundTask;
1113
use super::TaskName;
1214
use assert_matches::assert_matches;
@@ -129,6 +131,7 @@ impl Driver {
129131
name.clone(),
130132
)]));
131133
let task_exec = TaskExec::new(
134+
&name,
132135
taskdef.period,
133136
taskdef.task_impl,
134137
activator.clone(),
@@ -234,6 +237,8 @@ pub struct TaskDefinition<'a, N: ToString, D: ToString> {
234237
/// Encapsulates state needed by the background tokio task to manage activation
235238
/// of the background task
236239
struct TaskExec {
240+
/// the name of this background task
241+
name: String,
237242
/// how often the background task should be activated
238243
period: Duration,
239244
/// impl of the background task
@@ -251,13 +256,23 @@ struct TaskExec {
251256

252257
impl TaskExec {
253258
fn new(
259+
name: impl ToString,
254260
period: Duration,
255261
imp: Box<dyn BackgroundTask>,
256262
activation: Activator,
257263
opctx: OpContext,
258264
status_tx: watch::Sender<TaskStatus>,
259265
) -> TaskExec {
260-
TaskExec { period, imp, activation, opctx, status_tx, iteration: 0 }
266+
let name = name.to_string();
267+
TaskExec {
268+
name,
269+
period,
270+
imp,
271+
activation,
272+
opctx,
273+
status_tx,
274+
iteration: 0,
275+
}
261276
}
262277

263278
/// Body of the tokio task that manages activation of this background task
@@ -318,10 +333,16 @@ impl TaskExec {
318333
});
319334

320335
// Do it!
336+
probes::background__task__activate__start!(|| {
337+
(&self.name, self.iteration, format!("{reason:?}"))
338+
});
321339
let details = self.imp.activate(&self.opctx).await;
322340
let details_str = serde_json::to_string(&details).unwrap_or_else(|e| {
323341
format!("<<failed to serialize task status: {}>>", e)
324342
});
343+
probes::background__task__activate__done!(|| {
344+
(&self.name, self.iteration, &details_str)
345+
});
325346

326347
let elapsed = start_instant.elapsed();
327348

nexus/src/app/background/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,22 @@ impl TaskName {
166166
&self.0
167167
}
168168
}
169+
170+
#[usdt::provider(provider = "nexus")]
171+
mod probes {
172+
/// Fires just before running the activate method of the named task.
173+
fn background__task__activate__start(
174+
task_name: &str,
175+
iteration: u64,
176+
reason: &str,
177+
) {
178+
}
179+
180+
/// Fires just after completing the task, with the result as JSON.
181+
fn background__task__activate__done(
182+
task_name: &str,
183+
iteration: u64,
184+
details: &str,
185+
) {
186+
}
187+
}

tools/dtrace/nexus/trace-bgtasks.d

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/sbin/dtrace -Zqs
2+
3+
/* This script prints the result of every background task's activation.
4+
* It includes the task name, its iteration, the reason the task ran,
5+
* and the result and duration of the execution. Here's an example:
6+
*
7+
* task_name="dns_servers_internal" iteration=2 reason=Signaled details={"addresses":["[::1]:56144"]} duration=22054us
8+
* task_name="dns_servers_external" iteration=2 reason=Signaled details={"addresses":["[::1]:56161"]} duration=21254us
9+
* task_name="dns_propagation_internal" iteration=2 reason=Dependency details={"error":"no config"} duration=511us
10+
* task_name="dns_propagation_external" iteration=2 reason=Dependency details={"error":"no config"} duration=19us
11+
* task_name="v2p_manager" iteration=13 reason=Signaled details={} duration=432252us
12+
* task_name="dns_servers_internal" iteration=2 reason=Signaled details={"addresses":["[::1]:36483"]} duration=21347us
13+
* task_name="dns_servers_external" iteration=2 reason=Signaled details={"addresses":["[::1]:50606"]} duration=20789us
14+
* task_name="dns_propagation_internal" iteration=2 reason=Dependency details={"error":"no config"} duration=38us
15+
* task_name="dns_propagation_external" iteration=2 reason=Dependency details={"error":"no config"} duration=11us
16+
* task_name="vpc_route_manager" iteration=10 reason=Signaled details={} duration=485381us
17+
*/
18+
19+
nexus*:::background-task-activate-start
20+
{
21+
this->task_name = copyinstr(arg0);
22+
iters[this->task_name] = arg1;
23+
reasons[this->task_name] = copyinstr(arg2);
24+
ts[this->task_name] = timestamp;
25+
}
26+
27+
nexus*:::background-task-activate-done
28+
/iters[copyinstr(arg0)] == arg1/
29+
{
30+
this->task_name = copyinstr(arg0);
31+
this->duration = timestamp - ts[this->task_name];
32+
printf(
33+
"task_name=\"%s\" iteration=%d reason=%s details=%s duration=%dus\n",
34+
this->task_name,
35+
iters[this->task_name],
36+
reasons[this->task_name],
37+
copyinstr(arg2),
38+
this->duration / 1000
39+
);
40+
iters[this->task_name] = 0;
41+
reasons[this->task_name] = 0;
42+
ts[this->task_name] = 0;
43+
}

0 commit comments

Comments
 (0)