Skip to content

Commit 00a330b

Browse files
authored
fix get power stats from turbostat for telemetry (#504)
Signed-off-by: Harper, Jason M <[email protected]>
1 parent 45ceffa commit 00a330b

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

internal/report/table_helpers_turbostat.go

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
// Each map represents a row, with column names as keys and values as strings.
1717
// Adds a "timestamp" key to each row, if TIME and INTERVAL are included in
1818
// the output by the collection script.
19+
// Only the Summary and Packages rows are returned, i.e., rows for individual cores/CPUs are ignored.
1920
func parseTurbostatOutput(output string) ([]map[string]string, error) {
2021
var (
2122
headers []string
@@ -85,7 +86,9 @@ func parseTurbostatOutput(output string) ([]map[string]string, error) {
8586
return rows, nil
8687
}
8788

88-
// turbostatPlatformRows parses the output of the turbostat script and returns a slice of rows with the specified field names.
89+
// turbostatPlatformRows parses the output of the turbostat script and returns the rows
90+
// for the platform (summary) only, for the specified field names.
91+
// The "platform" rows are those where Package, Die, Core, and CPU are all "-".
8992
// The first column is the sample time, and the rest are the values for the specified fields.
9093
func turbostatPlatformRows(turboStatScriptOutput string, fieldNames []string) ([][]string, error) {
9194
if len(fieldNames) == 0 {
@@ -105,9 +108,7 @@ func turbostatPlatformRows(turboStatScriptOutput string, fieldNames []string) ([
105108
// filter the rows to the summary rows only
106109
var fieldValues [][]string
107110
for _, row := range rows {
108-
if (row["Package"] != "-" && row["Package"] != "") ||
109-
(row["Core"] != "-" && row["Core"] != "") ||
110-
(row["CPU"] != "-" && row["CPU"] != "") {
111+
if !isPlatformRow(row) {
111112
continue
112113
}
113114
// this is a summary row, extract the values for the specified fields
@@ -129,8 +130,21 @@ func turbostatPlatformRows(turboStatScriptOutput string, fieldNames []string) ([
129130
return fieldValues, nil
130131
}
131132

133+
// isPlatformRow returns true if the row represents a platform (summary) row.
134+
// only consider rows where Package, Die, Node, Core, and CPU are "-" (or don't exist), these rows contain the sum of all packages
135+
func isPlatformRow(row map[string]string) bool {
136+
for _, header := range []string{"Package", "Die", "Node", "Core", "CPU"} {
137+
if val, ok := row[header]; ok && val != "-" {
138+
return false
139+
}
140+
}
141+
return true
142+
}
143+
132144
// turbostatPackageRows
133-
// packages -> rows
145+
// parses the output of the turbostat script and returns the rows
146+
// for each package, for the specified field names.
147+
// The first column is the sample time, and the rest are the values for the specified fields.
134148
func turbostatPackageRows(turboStatScriptOutput string, fieldNames []string) ([][][]string, error) {
135149
if len(fieldNames) == 0 {
136150
err := fmt.Errorf("no field names provided")
@@ -146,16 +160,19 @@ func turbostatPackageRows(turboStatScriptOutput string, fieldNames []string) ([]
146160
return nil, err
147161
}
148162
var packageRows [][][]string
149-
prevPackage := ""
150163
for _, row := range rows {
151-
// the first row with a new package number is the package row
152-
if row["Package"] == "" || row["Package"] == "-" {
153-
continue // skip rows that are not package rows
164+
// not all instances of turbostat output include a Package column
165+
// if it is missing assume 1 package, set it to 0 for rows where CPU is 0
166+
if _, ok := row["Package"]; !ok {
167+
if row["CPU"] == "0" {
168+
row["Package"] = "0"
169+
} else {
170+
continue // skip rows that are not package rows
171+
}
154172
}
155-
if row["Package"] == prevPackage {
156-
continue // skip rows that are not the first row for this package
173+
if !isPackageRow(row) {
174+
continue
157175
}
158-
prevPackage = row["Package"]
159176
// this is a package row, extract the values for the specified fields
160177
rowValues := make([]string, len(fieldNames)+1) // +1 for the sample time
161178
rowValues[0] = row["timestamp"] // first column is the sample time
@@ -185,6 +202,15 @@ func turbostatPackageRows(turboStatScriptOutput string, fieldNames []string) ([]
185202
return packageRows, nil
186203
}
187204

205+
// isPackageRow returns true if the row represents a package row.
206+
// only consider rows where Package is not "-" or empty
207+
func isPackageRow(row map[string]string) bool {
208+
if val, ok := row["Package"]; ok && val != "-" {
209+
return true
210+
}
211+
return false
212+
}
213+
188214
// maxTotalPackagePowerFromOutput calculates the maximum total package power from the turbostat output.
189215
func maxTotalPackagePowerFromOutput(turbostatOutput string) string {
190216
rows, err := parseTurbostatOutput(turbostatOutput)

0 commit comments

Comments
 (0)