Skip to content

Commit dadb693

Browse files
committed
[trace] Improve guest traces to contain top spans
- For each call to `internal_dispatch_function` now we create a span manually because instrumenting the function would be redundant because of the call to `new_call` that resets tracing state for each new function call - The same logic is used for `generic_init` to enable it for the initialise call Signed-off-by: Doru Blânzeanu <dblnz@pm.me>
1 parent c5ecf49 commit dadb693

3 files changed

Lines changed: 43 additions & 13 deletions

File tree

src/hyperlight_common/src/flatbuffer_wrappers/function_call.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub enum FunctionCallType {
4141
}
4242

4343
/// `Functioncall` represents a call to a function in the guest or host.
44-
#[derive(Clone)]
44+
#[derive(Clone, Debug)]
4545
pub struct FunctionCall {
4646
/// The function name
4747
pub function_name: String,

src/hyperlight_guest_bin/src/guest_function/call.rs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,25 @@ pub(crate) fn call_guest_function(function_call: FunctionCall) -> Result<Vec<u8>
7575
pub(crate) fn internal_dispatch_function() {
7676
// Read the current TSC to report it to the host with the spans/events
7777
// This helps calculating the timestamps relative to the guest call
78-
#[cfg(feature = "trace_guest")]
79-
{
78+
#[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
79+
let _entered = {
8080
let guest_start_tsc = hyperlight_guest_tracing::invariant_tsc::read_tsc();
8181
// Reset the trace state for the new guest function call with the new start TSC
8282
// This clears any existing spans/events from previous calls ensuring a clean state
8383
hyperlight_guest_tracing::new_call(guest_start_tsc);
84-
}
8584

86-
let handle = unsafe { GUEST_HANDLE };
85+
tracing::span!(tracing::Level::INFO, "internal_dispatch_function").entered()
86+
};
8787

88-
#[cfg(debug_assertions)]
89-
log::trace!("internal_dispatch_function");
88+
let handle = unsafe { GUEST_HANDLE };
9089

9190
let function_call = handle
9291
.try_pop_shared_input_data_into::<FunctionCall>()
9392
.expect("Function call deserialization failed");
9493

94+
#[cfg(debug_assertions)]
95+
tracing::trace!("{:?}", function_call);
96+
9597
let res = call_guest_function(function_call);
9698

9799
match res {
@@ -111,8 +113,20 @@ pub(crate) fn internal_dispatch_function() {
111113
}
112114
}
113115

114-
// Ensure that any tracing output during the call is flushed to
115-
// the host, if necessary.
116+
// All this tracing logic shall be done right before the call to `hlt` which is done after this
117+
// function returns
116118
#[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
117-
hyperlight_guest_tracing::flush();
119+
{
120+
// This span captures the internal dispatch function only, without tracing internals.
121+
// Close the span before flushing to ensure that the `flush` call is not included in the span
122+
// NOTE: This is necessary to avoid closing the span twice. Flush closes all the open
123+
// spans, when preparing to close a guest function call context.
124+
// It is not mandatory, though, but avoids a warning on the host that alerts a spans
125+
// that has not been opened but is being closed.
126+
_entered.exit();
127+
128+
// Ensure that any tracing output during the call is flushed to
129+
// the host, if necessary.
130+
hyperlight_guest_tracing::flush();
131+
}
118132
}

src/hyperlight_guest_bin/src/lib.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,12 @@ pub(crate) extern "C" fn generic_init(
226226
hyperlight_guest_tracing::init_guest_tracing(guest_start_tsc);
227227
}
228228

229+
// Open a span to partly capture the initialization of the guest.
230+
// This is done here because the tracing subscriber is initialized and the guest is in a
231+
// well-known state
232+
#[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
233+
let _entered = tracing::span!(tracing::Level::INFO, "generic_init").entered();
234+
229235
#[cfg(feature = "macros")]
230236
for registration in __private::GUEST_FUNCTION_INIT {
231237
registration();
@@ -235,10 +241,20 @@ pub(crate) extern "C" fn generic_init(
235241
hyperlight_main();
236242
}
237243

238-
// Ensure that any tracing output from the initialisation phase is
239-
// flushed to the host, if necessary.
244+
// All this tracing logic shall be done right before the call to `hlt` which is done after this
245+
// function returns
240246
#[cfg(all(feature = "trace_guest", target_arch = "x86_64"))]
241-
hyperlight_guest_tracing::flush();
247+
{
248+
// NOTE: This is necessary to avoid closing the span twice. Flush closes all the open
249+
// spans, when preparing to close a guest function call context.
250+
// It is not mandatory, though, but avoids a warning on the host that alerts a spans
251+
// that has not been opened but is being closed.
252+
_entered.exit();
253+
254+
// Ensure that any tracing output from the initialisation phase is
255+
// flushed to the host, if necessary.
256+
hyperlight_guest_tracing::flush();
257+
}
242258

243259
dispatch_function as usize as u64
244260
}

0 commit comments

Comments
 (0)