Skip to content

Add guest-call-stats feature with ExecutionStats API#33

Open
simongdavies wants to merge 1 commit intomainfrom
add-call-stats
Open

Add guest-call-stats feature with ExecutionStats API#33
simongdavies wants to merge 1 commit intomainfrom
add-call-stats

Conversation

@simongdavies
Copy link
Contributor

Add per-call execution statistics (wall clock, CPU time, termination info) accessible via LoadedJSSandbox::last_call_stats() behind the guest-call-stats feature flag.

Rust API:

  • New ExecutionStats struct with wall_clock, cpu_time, terminated_by fields
  • last_call_stats() getter on LoadedJSSandbox (feature-gated)
  • Stats captured on every handle_event/handle_event_with_monitor call
  • Stats available even when calls error (monitor termination, guest abort)
  • MonitorSet::to_race() now returns winner name for stats integration

Node.js (NAPI) API:

  • CallStats object with wallClockMs, cpuTimeMs, terminatedBy properties
  • lastCallStats getter on LoadedJSSandbox wrapper
  • guest-call-stats enabled by default in js-host-api

Includes:

  • execution_stats example (Rust) with 6 test scenarios
  • 10 integration tests covering all stats paths
  • Updated cpu-timeout.js example with printCallStats helper
  • Documentation updates (execution-monitors.md, READMEs)
  • Justfile: test-monitors includes guest-call-stats, new example recipe

@simongdavies simongdavies added the kind/enhancement New feature or improvement label Mar 3, 2026
Add per-call execution statistics (wall clock, CPU time, termination info)
accessible via LoadedJSSandbox::last_call_stats() behind the guest-call-stats
feature flag.

Rust API:
- New ExecutionStats struct with wall_clock, cpu_time, terminated_by fields
- last_call_stats() getter on LoadedJSSandbox (feature-gated)
- Stats captured on every handle_event/handle_event_with_monitor call
- Stats available even when calls error (monitor termination, guest abort)
- MonitorSet::to_race() now returns winner name for stats integration

Node.js (NAPI) API:
- CallStats object with wallClockMs, cpuTimeMs, terminatedBy properties
- lastCallStats getter on LoadedJSSandbox wrapper
- guest-call-stats enabled by default in js-host-api

Includes:
- execution_stats example (Rust) with 6 test scenarios
- 10 integration tests covering all stats paths
- Updated cpu-timeout.js example with printCallStats helper
- Documentation updates (execution-monitors.md, READMEs)
- Justfile: test-monitors includes guest-call-stats, new example recipe

Signed-off-by: Simon Davies <simongdavies@users.noreply.github.com>
/// resolves. Unlike `poisoned_flag`, this uses a `Mutex` because it
/// stores a struct — but contention is negligible since it's only
/// accessed after the call completes.
last_call_stats: Arc<Mutex<Option<CallStats>>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@dblnz dblnz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!
This is a nice to have feature, although I think we might end up needing this pattern in hyperlight-wasm, hyperlight core and maybe other places. Maybe we could use a #[derive] to automatically add this to a sandbox? (just a thought)

Some comments below. Nothing blocking though.

use hyperlight_js::{SandboxBuilder, Script};

fn main() -> Result<()> {
println!("📊 Execution Stats Example: Guest Call Statistics\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I am not a big fan of emojis in the code 😄 It tends to be too flashy for me. It's not a strong opinion though

let wall_start = std::time::Instant::now();

#[cfg(all(feature = "guest-call-stats", feature = "monitor-cpu-time"))]
let cpu_start = super::monitor::cpu_time::ThreadCpuHandle::for_current_thread()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, getting the TSC time spent in the guest is more accurate than measuring it from the host, do you think having that info would help the end user?

We would rely on a value return from the guest that can be unreliable, though.


ensure-tools:
cargo install cargo-hyperlight --locked --version 0.1.3
cargo install cargo-hyperlight --locked --version 0.1.7
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just use the latest published version?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/enhancement New feature or improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants