From 67715745a1860326c9df63f6f31132c738bceea6 Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Thu, 11 Dec 2025 15:39:32 -0800 Subject: [PATCH 1/4] Add parsing for perf list JSON output to extract hardware and power events Signed-off-by: Harper, Jason M --- cmd/metrics/metadata.go | 41 +++++++++++++++++++++++++++++++++++++---- cmd/metrics/summary.go | 9 +-------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/cmd/metrics/metadata.go b/cmd/metrics/metadata.go index 51d6c6f1..14400024 100644 --- a/cmd/metrics/metadata.go +++ b/cmd/metrics/metadata.go @@ -401,10 +401,43 @@ func getMetadataScripts(noRoot bool, noSystemSummary bool, numGPCounters int) (m Superuser: !noRoot, }, { - Name: "perf supported events", - ScriptTemplate: "perf list", - Superuser: !noRoot, - Depends: []string{"perf"}, + Name: "perf supported events", + ScriptTemplate: `# Parse perf list JSON output to extract Hardware events and cstate/power events +./perf list --json 2>/dev/null | awk ' +BEGIN { + in_hardware_event = 0 + event_name = "" +} + +# Capture EventName +/"EventName":/ { + # Extract the value between quotes after "EventName": + match($0, /"EventName": "([^"]+)"/, arr) + event_name = arr[1] +} + +# Check if EventType is Hardware event +/"EventType": "Hardware event"/ { + in_hardware_event = 1 +} + +# At end of object (closing brace), check if we should print +/^}/ { + if (in_hardware_event || + event_name ~ /^cstate_/ || + event_name ~ /^power/) { + if (event_name != "") { + print event_name + } + } + # Reset for next object + in_hardware_event = 0 + event_name = "" +} +' # end of awk +`, + Superuser: !noRoot, + Depends: []string{"perf"}, }, { Name: "list uncore devices", diff --git a/cmd/metrics/summary.go b/cmd/metrics/summary.go index 2b27b867..c08a231c 100644 --- a/cmd/metrics/summary.go +++ b/cmd/metrics/summary.go @@ -16,7 +16,6 @@ import ( "os" "path/filepath" "perfspect/internal/cpus" - "regexp" "slices" "strconv" texttemplate "text/template" // nosemgrep @@ -628,13 +627,7 @@ func (mg *MetricGroup) loadHTMLTemplateValues(metadata Metadata, metricDefinitio if err != nil { return } - // remove PerfSupportedEvents from json - re := regexp.MustCompile(`"PerfSupportedEvents":".*?",`) - jsonMetadataPurged := re.ReplaceAll(jsonMetadata, []byte("")) - // remove SystemSummaryFields from json - re = regexp.MustCompile(`,"SystemSummaryFields":\[\[.*?\]\]`) - jsonMetadataPurged = re.ReplaceAll(jsonMetadataPurged, []byte("")) - templateVals["METADATA"] = string(jsonMetadataPurged) + templateVals["METADATA"] = string(jsonMetadata) // system info tab jsonSystemInfo, err := json.Marshal(metadata.SystemSummaryFields) From 964c2df93ff6e344539b06654012732e9af3e539 Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Fri, 12 Dec 2025 08:52:14 -0800 Subject: [PATCH 2/4] portable awk script Signed-off-by: Harper, Jason M --- cmd/metrics/metadata.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/cmd/metrics/metadata.go b/cmd/metrics/metadata.go index 14400024..6ee13d3a 100644 --- a/cmd/metrics/metadata.go +++ b/cmd/metrics/metadata.go @@ -403,8 +403,8 @@ func getMetadataScripts(noRoot bool, noSystemSummary bool, numGPCounters int) (m { Name: "perf supported events", ScriptTemplate: `# Parse perf list JSON output to extract Hardware events and cstate/power events -./perf list --json 2>/dev/null | awk ' -BEGIN { +perf list --json 2>/dev/null | awk ' +BEGIN { in_hardware_event = 0 event_name = "" } @@ -412,8 +412,10 @@ BEGIN { # Capture EventName /"EventName":/ { # Extract the value between quotes after "EventName": - match($0, /"EventName": "([^"]+)"/, arr) - event_name = arr[1] + line = $0 + sub(/.*"EventName": "/, "", line) + sub(/".*/, "", line) + event_name = line } # Check if EventType is Hardware event @@ -423,9 +425,10 @@ BEGIN { # At end of object (closing brace), check if we should print /^}/ { - if (in_hardware_event || - event_name ~ /^cstate_/ || - event_name ~ /^power/) { + if (in_hardware_event || + event_name ~ /^cstate_core\// || + event_name ~ /^cstate_pkg\// || + event_name ~ /^power\//) { if (event_name != "") { print event_name } From 42e1f2450ee117aed057cdf609b2a5deb8d7f608 Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Thu, 11 Dec 2025 15:39:32 -0800 Subject: [PATCH 3/4] Add parsing for perf list JSON output to extract hardware and power events Signed-off-by: Harper, Jason M --- cmd/metrics/metadata.go | 41 +++++++++++++++++++++++++++++++++++++---- cmd/metrics/summary.go | 9 +-------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/cmd/metrics/metadata.go b/cmd/metrics/metadata.go index 51d6c6f1..14400024 100644 --- a/cmd/metrics/metadata.go +++ b/cmd/metrics/metadata.go @@ -401,10 +401,43 @@ func getMetadataScripts(noRoot bool, noSystemSummary bool, numGPCounters int) (m Superuser: !noRoot, }, { - Name: "perf supported events", - ScriptTemplate: "perf list", - Superuser: !noRoot, - Depends: []string{"perf"}, + Name: "perf supported events", + ScriptTemplate: `# Parse perf list JSON output to extract Hardware events and cstate/power events +./perf list --json 2>/dev/null | awk ' +BEGIN { + in_hardware_event = 0 + event_name = "" +} + +# Capture EventName +/"EventName":/ { + # Extract the value between quotes after "EventName": + match($0, /"EventName": "([^"]+)"/, arr) + event_name = arr[1] +} + +# Check if EventType is Hardware event +/"EventType": "Hardware event"/ { + in_hardware_event = 1 +} + +# At end of object (closing brace), check if we should print +/^}/ { + if (in_hardware_event || + event_name ~ /^cstate_/ || + event_name ~ /^power/) { + if (event_name != "") { + print event_name + } + } + # Reset for next object + in_hardware_event = 0 + event_name = "" +} +' # end of awk +`, + Superuser: !noRoot, + Depends: []string{"perf"}, }, { Name: "list uncore devices", diff --git a/cmd/metrics/summary.go b/cmd/metrics/summary.go index 2b27b867..c08a231c 100644 --- a/cmd/metrics/summary.go +++ b/cmd/metrics/summary.go @@ -16,7 +16,6 @@ import ( "os" "path/filepath" "perfspect/internal/cpus" - "regexp" "slices" "strconv" texttemplate "text/template" // nosemgrep @@ -628,13 +627,7 @@ func (mg *MetricGroup) loadHTMLTemplateValues(metadata Metadata, metricDefinitio if err != nil { return } - // remove PerfSupportedEvents from json - re := regexp.MustCompile(`"PerfSupportedEvents":".*?",`) - jsonMetadataPurged := re.ReplaceAll(jsonMetadata, []byte("")) - // remove SystemSummaryFields from json - re = regexp.MustCompile(`,"SystemSummaryFields":\[\[.*?\]\]`) - jsonMetadataPurged = re.ReplaceAll(jsonMetadataPurged, []byte("")) - templateVals["METADATA"] = string(jsonMetadataPurged) + templateVals["METADATA"] = string(jsonMetadata) // system info tab jsonSystemInfo, err := json.Marshal(metadata.SystemSummaryFields) From ca22e304b40d9e6bfa507cee0cb2f2ed4ce26b10 Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Fri, 12 Dec 2025 08:52:14 -0800 Subject: [PATCH 4/4] portable awk script Signed-off-by: Harper, Jason M --- cmd/metrics/metadata.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/cmd/metrics/metadata.go b/cmd/metrics/metadata.go index 14400024..6ee13d3a 100644 --- a/cmd/metrics/metadata.go +++ b/cmd/metrics/metadata.go @@ -403,8 +403,8 @@ func getMetadataScripts(noRoot bool, noSystemSummary bool, numGPCounters int) (m { Name: "perf supported events", ScriptTemplate: `# Parse perf list JSON output to extract Hardware events and cstate/power events -./perf list --json 2>/dev/null | awk ' -BEGIN { +perf list --json 2>/dev/null | awk ' +BEGIN { in_hardware_event = 0 event_name = "" } @@ -412,8 +412,10 @@ BEGIN { # Capture EventName /"EventName":/ { # Extract the value between quotes after "EventName": - match($0, /"EventName": "([^"]+)"/, arr) - event_name = arr[1] + line = $0 + sub(/.*"EventName": "/, "", line) + sub(/".*/, "", line) + event_name = line } # Check if EventType is Hardware event @@ -423,9 +425,10 @@ BEGIN { # At end of object (closing brace), check if we should print /^}/ { - if (in_hardware_event || - event_name ~ /^cstate_/ || - event_name ~ /^power/) { + if (in_hardware_event || + event_name ~ /^cstate_core\// || + event_name ~ /^cstate_pkg\// || + event_name ~ /^power\//) { if (event_name != "") { print event_name }