Skip to content

Commit f67d23a

Browse files
authored
Extract the markName and measureName fields from performance.measure … (#690)
The patch in https://source.chromium.org/chromium/chromium/src/+/453a29751849863627f6cabfe2645dd48c8d6c33 changed how Chrome emits the measure and mark events for ETW. The name of the event is now stored in the `measuredName` and `markName` fields now. For measure events, the name is only stored in the BEGIN phase.
2 parents 914eaec + 53c1166 commit f67d23a

File tree

1 file changed

+52
-2
lines changed

1 file changed

+52
-2
lines changed

samply/src/windows/etw_gecko.rs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::collections::HashMap;
12
use std::convert::TryInto;
23
use std::path::{Path, PathBuf};
34
use std::time::Instant;
@@ -75,6 +76,9 @@ fn process_trace(
7576
let demand_zero_faults = false; //pargs.contains("--demand-zero-faults");
7677
let mut pending_image_info: Option<((u32, u64), PendingImageInfo)> = None;
7778

79+
// Cache for Chrome measure names by (tid, traceId).
80+
let mut measure_name_cache: HashMap<(u32, u64), String> = HashMap::new();
81+
7882
open_trace(etl_file, |e| {
7983
let Ok(s) = schema_locator.event_schema(e) else {
8084
return;
@@ -492,15 +496,61 @@ fn process_trace(
492496
};
493497
let phase: String = parser.try_parse("Phase").unwrap();
494498
let keyword_bitfield = e.EventHeader.EventDescriptor.Keyword; // a bitfield of keywords
499+
500+
let display_name = if marker_name == "performance.measure" {
501+
// Extract user-provided name from User Timing API measure events.
502+
// The name is in "measureName".
503+
let user_timing_measure_name: Option<String> =
504+
parser.try_parse("measureName").ok();
505+
let trace_id: Option<u64> = parser.try_parse("Id").ok();
506+
507+
if let Some(trace_id) = trace_id {
508+
// performance.measure() emits Begin/End pairs with a trace ID.
509+
// The measure name is only present in the Begin event.
510+
if phase == "Begin" {
511+
if let Some(name) = user_timing_measure_name {
512+
measure_name_cache.insert((tid, trace_id), name.clone());
513+
name
514+
} else {
515+
marker_name.to_string()
516+
}
517+
} else if phase == "End" {
518+
// Look up the name we cached from the Begin event
519+
measure_name_cache
520+
.remove(&(tid, trace_id))
521+
.unwrap_or_else(|| marker_name.to_string())
522+
} else {
523+
marker_name.to_string()
524+
}
525+
} else {
526+
user_timing_measure_name.unwrap_or_else(|| marker_name.to_string())
527+
}
528+
} else if marker_name == "performance.mark" {
529+
// Extract user-provided name from User Timing API mark events.
530+
// The name is in the "markName" field.
531+
let user_timing_mark_name: Option<String> = parser.try_parse("markName").ok();
532+
user_timing_mark_name.unwrap_or_else(|| marker_name.to_string())
533+
} else {
534+
// For all other Chrome events, use the marker name as-is.
535+
marker_name.to_string()
536+
};
537+
495538
let text = event_properties_to_string(
496539
&s,
497540
&mut parser,
498-
Some(&["Timestamp", "Phase", "Duration"]),
541+
Some(&[
542+
"Timestamp",
543+
"Phase",
544+
"Duration",
545+
"markName",
546+
"measureName",
547+
"Id",
548+
]),
499549
);
500550
context.handle_chrome_marker(
501551
tid,
502552
timestamp_raw,
503-
marker_name,
553+
&display_name,
504554
timestamp_us,
505555
&phase,
506556
keyword_bitfield,

0 commit comments

Comments
 (0)