diagnostics_channel: add USDT probes - #62118
Conversation
|
Review requested:
|
|
|
||
| #### Platform support | ||
|
|
||
| At `./configure` time, Node.js checks for a working `dtrace` tool and |
There was a problem hiding this comment.
We have removed dtrace support long time ago. Wouldn't it require us to include a new suite for testing it on that environment?
There was a problem hiding this comment.
I'm not sure what our build setup looks like now, but yes, everything that was required for the previous incarnation of probes in Node.js would likely be required again with this PR.
There was a problem hiding this comment.
I don't think we tested the dtrace stuff previously. I think when it was removed it had be broken for a while (or maybe that was one of the other non-tested removed features).
There was a problem hiding this comment.
There's a possible path forward here where headers are pre-generated and added to git (much like we do for other cases of generated headers, in dependencies for example), and then a userland, self-contained test (at least on linux) checks for the placement and activation of the probe.
There was a problem hiding this comment.
Alright, I've made some changes (many months later..)
Linux is now default-on with no dtrace build dependency. src/node_provider_linux.h is committed.
It can be regenerated via tools/usdt/generate_headers.py and a --check drift job runs in CI against it.
Default ./configure enables USDT whenever <sys/sdt.h> is present (systemtap-sdt-dev / systemtap-sdt-devel is the only build requirement on Linux).
macOS is opt-in via ./configure --with-dtrace (which at build-time calls dtrace -h -xnolibs).
--without-dtrace still disables everything.
New test-usdt CI job in test-linux.yml:
- default: end-to-end bpftrace test as root (verifies the probe fires with the channel name) plus the committed-header drift check
--without-dtrace: pins the no-op tier
Bench (aarch64 VM, benchmark/diagnostics_channel/publish.js, subscribers=1, avg of 2): default ~282M ops/s vs --without-dtrace ~314M ops/s — ~10% on this microbench.
|
This pull request has been marked as stale due to 90 days of inactivity. |
Implements the approach from the nodejs#62118 review discussion to remove the build-time 'dtrace' dependency on Linux: * Commit the SystemTap-generated probe header (src/node_provider_linux.h, regenerate with tools/usdt/generate_headers.py). USDT support is now on by default on Linux whenever <sys/sdt.h> is available (systemtap-sdt-dev on Debian/Ubuntu, systemtap-sdt-devel on Fedora/RHEL) and never needs a 'dtrace' tool at build time. A committed-header drift check runs in CI. * Make native DTrace opt-in on macOS via the new ./configure --with-dtrace; FreeBSD/illumos remain unsupported pending a 'dtrace -G' link step. --without-dtrace still disables probes everywhere. The always-on <sys/sdt.h> fallback tier is gone. * Add a path-gated test-usdt job to the Linux CI workflow with a default leg that runs the end-to-end bpftrace probe test as root, and a --without-dtrace leg that pins the no-op tier. The generated header is excluded from cpplint like src/node_root_certs.h.
Implements the approach from the nodejs#62118 review discussion to remove the build-time 'dtrace' dependency on Linux: * Commit the SystemTap-generated probe header (src/node_provider_linux.h, regenerate with tools/usdt/generate_headers.py). USDT support is now on by default on Linux whenever <sys/sdt.h> is available (systemtap-sdt-dev on Debian/Ubuntu, systemtap-sdt-devel on Fedora/RHEL) and never needs a 'dtrace' tool at build time. A committed-header drift check runs in CI. * Make native DTrace opt-in on macOS via the new ./configure --with-dtrace; FreeBSD/illumos remain unsupported pending a 'dtrace -G' link step. --without-dtrace still disables probes everywhere. The always-on <sys/sdt.h> fallback tier is gone. * Add a path-gated test-usdt job to the Linux CI workflow with a default leg that runs the end-to-end bpftrace probe test as root, and a --without-dtrace leg that pins the no-op tier. The generated header is excluded from cpplint like src/node_root_certs.h. Signed-off-by: Bryan English <bryan@bryanenglish.com>
d49a2c5 to
22e8015
Compare
Fire a `dc__publish` USDT probe for every diagnostics_channel publish, passing the channel name, so tracers such as bpftrace, perf, or SystemTap can observe publish traffic with near-zero cost when nothing is attached. Probes are enabled by default on Linux; --without-dtrace disables them. The probe semaphore is exposed to JS as a Uint16Array over the native semaphore so the publish hot path can gate on one indexed load instead of a binding call. The array is resolved lazily rather than captured at module load: this module is baked into the startup snapshot, and a view captured while building the snapshot is detached when the snapshot is deserialized. Builds without USDT support keep a branch-only path that never calls the binding. Signed-off-by: Bryan English <bryan@bryanenglish.com> Assisted-by: Pi using GLM-5.3
22e8015 to
4e1213d
Compare
| #define NODE_DC_PUBLISH_PROBE(name, msg) NODE_DC_PUBLISH((name), (msg)) | ||
|
|
||
| // Real semaphore — JS can check it without crossing into C++. | ||
| inline unsigned short* NodeDCPublishSemaphore() { // NOLINT(runtime/int) |
There was a problem hiding this comment.
These aren't in any namespace (e.g. namespace node { ... }) ... is that intentional/necessary? If either, that should be documented here.
There was a problem hiding this comment.
It's intentional, since we're doing all this wrapping and handling of non-namespaced stuff in here. I'll add a comment to clarify.
Remove the build-time dtrace dependency on Linux, following the approach discussed in the PR review: generate the SystemTap provider header once with tools/usdt/generate_headers.py and commit it as src/node_provider_linux.h, so Linux builds need only <sys/sdt.h> and never a dtrace tool. --with-dtrace becomes the opt-in switch for macOS; --without-dtrace disables probes entirely. Add a path-filtered test-usdt job to the Linux CI workflow that installs bpftrace and systemtap-sdt-dev, verifies the committed header stays in sync with the generator, builds with and without dtrace, and runs the USDT tests, including a root-only bpftrace end-to-end test that attaches to the dc__publish probe and asserts the channel name argument. Signed-off-by: Bryan English <bryan@bryanenglish.com> Assisted-by: Pi using GLM-5.3
| NodeDCPublishSemaphore(), | ||
| sizeof(unsigned short), // NOLINT(runtime/int) | ||
| [](void*, size_t, void*) {}, // no-op deleter — memory is static | ||
| nullptr); |
There was a problem hiding this comment.
This might run into issues when v8 sandbox is enabled. @codebytere
There was a problem hiding this comment.
IIUC, arbitrary process memory can't be wrapped/exposed to JS with sandbox enabled. We'll just fall back to non-semaphore mode then (like I'm doing on macOS). Fix incoming.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #62118 +/- ##
==========================================
+ Coverage 90.17% 90.18% +0.01%
==========================================
Files 771 771
Lines 265496 265498 +2
Branches 50483 50468 -15
==========================================
+ Hits 239401 239430 +29
+ Misses 17052 17019 -33
- Partials 9043 9049 +6
🚀 New features to boost your workflow:
|
4e1213d to
5a684c8
Compare
Adds USDT probes that are fired for every diagnostics_channel publish.