Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cmd/report/dimm.go
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,11 @@ func deriveDIMMInfoOther(dimms [][]string, channelsPerSocket int) ([]derivedFiel
err := fmt.Errorf("no DIMMs")
return nil, err
}
dimmType, reBankLoc, reLoc := getDIMMParseInfo((dimms)[0][BankLocatorIdx], (dimms)[0][LocatorIdx])
if len(dimms[0]) <= max(BankLocatorIdx, LocatorIdx) {
err := fmt.Errorf("DIMM data has insufficient fields")
return nil, err
}
dimmType, reBankLoc, reLoc := getDIMMParseInfo(dimms[0][BankLocatorIdx], dimms[0][LocatorIdx])
if dimmType == DIMMTypeUNKNOWN {
err := fmt.Errorf("unknown DIMM identification format")
return nil, err
Expand Down
41 changes: 21 additions & 20 deletions cmd/report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ func benchmarkSummaryFromTableValues(allTableValues []table.TableValues, outputs
memLatTableValues := getTableValues(allTableValues, MemoryBenchmarkTableName)
var bandwidthValues []string
if len(memLatTableValues.Fields) > 1 {
bandwidthValues = getTableValues(allTableValues, MemoryBenchmarkTableName).Fields[1].Values
bandwidthValues = memLatTableValues.Fields[1].Values
}
maxBandwidth := 0.0
for _, bandwidthValue := range bandwidthValues {
Expand Down Expand Up @@ -517,27 +517,28 @@ func summaryHTMLTableRenderer(tv table.TableValues, targetName string) string {
panic(err)
}
// if we have reference data that matches the microarchitecture and sockets, use it
if refData, ok := referenceData[ReferenceDataKey{tv.Fields[uarchFieldIdx].Values[0], tv.Fields[socketsFieldIdx].Values[0]}]; ok {
// remove microarchitecture and sockets fields
fields := tv.Fields[:len(tv.Fields)-2]
refTableValues := table.TableValues{
Fields: []table.Field{
{Name: "CPU Speed", Values: []string{fmt.Sprintf("%.0f Ops/s", refData.CPUSpeed)}},
{Name: "Single-core Maximum frequency", Values: []string{fmt.Sprintf("%.0f MHz", refData.SingleCoreFreq)}},
{Name: "All-core Maximum frequency", Values: []string{fmt.Sprintf("%.0f MHz", refData.AllCoreFreq)}},
{Name: "Maximum Power", Values: []string{fmt.Sprintf("%.0f W", refData.MaxPower)}},
{Name: "Maximum Temperature", Values: []string{fmt.Sprintf("%.0f C", refData.MaxTemp)}},
{Name: "Minimum Power", Values: []string{fmt.Sprintf("%.0f W", refData.MinPower)}},
{Name: "Memory Peak Bandwidth", Values: []string{fmt.Sprintf("%.0f GB/s", refData.MemPeakBandwidth)}},
{Name: "Memory Minimum Latency", Values: []string{fmt.Sprintf("%.0f ns", refData.MemMinLatency)}},
},
if len(tv.Fields[uarchFieldIdx].Values) > 0 && len(tv.Fields[socketsFieldIdx].Values) > 0 {
if refData, ok := referenceData[ReferenceDataKey{tv.Fields[uarchFieldIdx].Values[0], tv.Fields[socketsFieldIdx].Values[0]}]; ok {
// remove microarchitecture and sockets fields
fields := tv.Fields[:len(tv.Fields)-2]
refTableValues := table.TableValues{
Fields: []table.Field{
{Name: "CPU Speed", Values: []string{fmt.Sprintf("%.0f Ops/s", refData.CPUSpeed)}},
{Name: "Single-core Maximum frequency", Values: []string{fmt.Sprintf("%.0f MHz", refData.SingleCoreFreq)}},
{Name: "All-core Maximum frequency", Values: []string{fmt.Sprintf("%.0f MHz", refData.AllCoreFreq)}},
{Name: "Maximum Power", Values: []string{fmt.Sprintf("%.0f W", refData.MaxPower)}},
{Name: "Maximum Temperature", Values: []string{fmt.Sprintf("%.0f C", refData.MaxTemp)}},
{Name: "Minimum Power", Values: []string{fmt.Sprintf("%.0f W", refData.MinPower)}},
{Name: "Memory Peak Bandwidth", Values: []string{fmt.Sprintf("%.0f GB/s", refData.MemPeakBandwidth)}},
{Name: "Memory Minimum Latency", Values: []string{fmt.Sprintf("%.0f ns", refData.MemMinLatency)}},
},
}
return report.RenderMultiTargetTableValuesAsHTML([]table.TableValues{{TableDefinition: tv.TableDefinition, Fields: fields}, refTableValues}, []string{targetName, refData.Description})
}
return report.RenderMultiTargetTableValuesAsHTML([]table.TableValues{{TableDefinition: tv.TableDefinition, Fields: fields}, refTableValues}, []string{targetName, refData.Description})
} else {
// remove microarchitecture and sockets fields
fields := tv.Fields[:len(tv.Fields)-2]
return report.DefaultHTMLTableRendererFunc(table.TableValues{TableDefinition: tv.TableDefinition, Fields: fields})
}
// remove microarchitecture and sockets fields
fields := tv.Fields[:len(tv.Fields)-2]
return report.DefaultHTMLTableRendererFunc(table.TableValues{TableDefinition: tv.TableDefinition, Fields: fields})
}

func summaryXlsxTableRenderer(tv table.TableValues, f *excelize.File, targetName string, row *int) {
Expand Down
32 changes: 21 additions & 11 deletions cmd/report/report_tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -1219,19 +1219,23 @@ func dimmTableInsights(outputs map[string]script.ScriptOutput, tableValues table
for i, speed := range tableValues.Fields[SpeedIndex].Values {
configuredSpeed := tableValues.Fields[ConfiguredSpeedIndex].Values[i]
if speed != "" && configuredSpeed != "" && speed != "Unknown" && configuredSpeed != "Unknown" {
speedVal, err := strconv.Atoi(strings.Split(speed, " ")[0])
if err != nil {
slog.Warn(err.Error())
} else {
configuredSpeedVal, err := strconv.Atoi(strings.Split(configuredSpeed, " ")[0])
speedParts := strings.Split(speed, " ")
configuredSpeedParts := strings.Split(configuredSpeed, " ")
if len(speedParts) > 0 && len(configuredSpeedParts) > 0 {
speedVal, err := strconv.Atoi(speedParts[0])
if err != nil {
slog.Warn(err.Error())
} else {
if speedVal < configuredSpeedVal {
insights = append(insights, table.Insight{
Recommendation: "Consider configuring DIMMs for their maximum speed.",
Justification: fmt.Sprintf("DIMMs configured for %s when their maximum speed is %s.", configuredSpeed, speed),
})
configuredSpeedVal, err := strconv.Atoi(configuredSpeedParts[0])
if err != nil {
slog.Warn(err.Error())
} else {
if speedVal < configuredSpeedVal {
insights = append(insights, table.Insight{
Recommendation: "Consider configuring DIMMs for their maximum speed.",
Justification: fmt.Sprintf("DIMMs configured for %s when their maximum speed is %s.", configuredSpeed, speed),
})
}
}
}
}
Expand Down Expand Up @@ -2033,7 +2037,13 @@ func dimmDetails(dimm []string) (details string) {
}

func dimmTableHTMLRenderer(tableValues table.TableValues, targetName string) string {
if tableValues.Fields[DerivedSocketIdx].Values[0] == "" || tableValues.Fields[DerivedChannelIdx].Values[0] == "" || tableValues.Fields[DerivedSlotIdx].Values[0] == "" {
if len(tableValues.Fields) <= max(DerivedSocketIdx, DerivedChannelIdx, DerivedSlotIdx) ||
len(tableValues.Fields[DerivedSocketIdx].Values) == 0 ||
len(tableValues.Fields[DerivedChannelIdx].Values) == 0 ||
len(tableValues.Fields[DerivedSlotIdx].Values) == 0 ||
tableValues.Fields[DerivedSocketIdx].Values[0] == "" ||
tableValues.Fields[DerivedChannelIdx].Values[0] == "" ||
tableValues.Fields[DerivedSlotIdx].Values[0] == "" {
return report.DefaultHTMLTableRendererFunc(tableValues)
}
htmlColors := []string{"lightgreen", "orange", "aqua", "lime", "yellow", "beige", "magenta", "violet", "salmon", "pink"}
Expand Down
4 changes: 2 additions & 2 deletions cmd/report/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func filesystemFieldValuesFromOutput(outputs map[string]script.ScriptOutput) []t
}
fields := strings.Fields(line)
// "Mounted On" gets split into two fields, rejoin
if i == 0 && fields[len(fields)-2] == "Mounted" && fields[len(fields)-1] == "on" {
if i == 0 && len(fields) >= 2 && fields[len(fields)-2] == "Mounted" && fields[len(fields)-1] == "on" {
fields[len(fields)-2] = "Mounted on"
fields = fields[:len(fields)-1]
for _, field := range fields {
Expand All @@ -126,7 +126,7 @@ func filesystemFieldValuesFromOutput(outputs map[string]script.ScriptOutput) []t
continue
}
match := reFindmnt.FindStringSubmatch(line)
if match != nil {
if match != nil && len(fields) > 5 {
target := match[1]
source := match[2]
if fields[0] == source && fields[5] == target {
Expand Down
7 changes: 5 additions & 2 deletions internal/common/nic.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ func ParseNicInfo(scriptOutput string) []nicInfo {
}
}
// special case for model as it sometimes has additional information in parentheses
nic.Model = strings.TrimSpace(strings.Split(nic.Model, "(")[0])
modelParts := strings.Split(nic.Model, "(")
if len(modelParts) > 0 {
nic.Model = strings.TrimSpace(modelParts[0])
}
nics = append(nics, nic)
}
// Assign card and port information
Expand Down Expand Up @@ -176,7 +179,7 @@ func assignCardAndPort(nics []nicInfo) {
}
// Further split the last part to separate device from function
deviceFunc := strings.Split(parts[2], ".")
if len(deviceFunc) != 2 {
if len(deviceFunc) < 1 {
continue
}
// Card identifier is domain:bus:device
Expand Down
30 changes: 18 additions & 12 deletions internal/common/power.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ func EPPFromOutput(outputs map[string]script.ScriptOutput) string {
if line == "" {
continue
}
currentEpbValid := strings.TrimSpace(strings.Split(line, ":")[1])
lineParts := strings.Split(line, ":")
if len(lineParts) < 2 {
continue
}
currentEpbValid := strings.TrimSpace(lineParts[1])
if i == 0 {
eppValid = currentEpbValid
continue
Expand All @@ -53,7 +57,11 @@ func EPPFromOutput(outputs map[string]script.ScriptOutput) string {
if line == "" {
continue
}
currentEppPkgCtrl := strings.TrimSpace(strings.Split(line, ":")[1])
lineParts := strings.Split(line, ":")
if len(lineParts) < 2 {
continue
}
currentEppPkgCtrl := strings.TrimSpace(lineParts[1])
if i == 0 {
eppPkgCtrl = currentEppPkgCtrl
continue
Expand All @@ -77,7 +85,11 @@ func EPPFromOutput(outputs map[string]script.ScriptOutput) string {
if line == "" {
continue
}
currentEpp := strings.TrimSpace(strings.Split(line, ":")[1])
lineParts := strings.Split(line, ":")
if len(lineParts) < 2 {
continue
}
currentEpp := strings.TrimSpace(lineParts[1])
if i == 0 {
epp = currentEpp
continue
Expand Down Expand Up @@ -112,13 +124,7 @@ func EPBFromOutput(outputs map[string]script.ScriptOutput) string {

func ELCSummaryFromOutput(outputs map[string]script.ScriptOutput) string {
fieldValues := ELCFieldValuesFromOutput(outputs)
if len(fieldValues) == 0 {
return ""
}
if len(fieldValues) < 10 {
return ""
}
if len(fieldValues[9].Values) == 0 {
if len(fieldValues) < 10 || len(fieldValues[9].Values) == 0 {
return ""
}
summary := fieldValues[9].Values[0]
Expand Down Expand Up @@ -203,15 +209,15 @@ func ELCFieldValuesFromOutput(outputs map[string]script.ScriptOutput) (fieldValu
// value rows
for _, row := range rows[1:] {
var mode string
if row[2] == "IO" {
if len(row) > 7 && row[2] == "IO" {
if row[5] == "0" && row[6] == "0" && row[7] == "0" {
mode = "Latency Optimized"
} else if row[5] == "800" && row[6] == "10" && row[7] == "94" {
mode = "Default"
} else {
mode = "Custom"
}
} else { // COMPUTE
} else if len(row) > 5 { // COMPUTE
switch row[5] {
case "0":
mode = "Latency Optimized"
Expand Down
5 changes: 4 additions & 1 deletion internal/report/render_excel.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ func renderXlsxTable(tableValues table.TableValues, f *excelize.File, sheetName
}

func renderXlsxTableMultiTarget(targetTableValues []table.TableValues, targetNames []string, f *excelize.File, sheetName string, row *int) {
if len(targetTableValues) == 0 {
return
}
col := 1
// print the table name
tableNameStyle, _ := f.NewStyle(&excelize.Style{
Expand Down Expand Up @@ -202,7 +205,7 @@ func DefaultXlsxTableRendererFunc(tableValues table.TableValues, f *excelize.Fil
col := 1
for _, field := range tableValues.Fields {
var fieldValue string
if len(tableValues.Fields[0].Values) > 0 {
if len(field.Values) > 0 {
fieldValue = field.Values[0]
}
_ = f.SetCellValue(sheetName, cellName(col, *row), field.Name)
Expand Down
12 changes: 11 additions & 1 deletion internal/report/render_html.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@ func createHtmlReport(allTableValues []table.TableValues, targetName string) (ou
}

func createHtmlReportMultiTarget(allTargetsTableValues [][]table.TableValues, targetNames []string, allTableNames []string) (out []byte, err error) {
if len(allTargetsTableValues) == 0 {
return nil, fmt.Errorf("no target table values provided")
}
var sb strings.Builder
sb.WriteString(getHtmlReportBegin())

Expand Down Expand Up @@ -593,7 +596,11 @@ func DefaultHTMLTableRendererFunc(tableValues table.TableValues) string {
for _, field := range tableValues.Fields {
rowValues := []string{}
rowValues = append(rowValues, CreateFieldNameWithDescription(field.Name, field.Description))
rowValues = append(rowValues, htmltemplate.HTMLEscapeString(field.Values[0]))
if len(field.Values) > 0 {
rowValues = append(rowValues, htmltemplate.HTMLEscapeString(field.Values[0]))
} else {
rowValues = append(rowValues, "")
}
values = append(values, rowValues)
tableValueStyles = append(tableValueStyles, []string{"font-weight:bold"})
}
Expand All @@ -604,6 +611,9 @@ func DefaultHTMLTableRendererFunc(tableValues table.TableValues) string {
// RenderMultiTargetTableValuesAsHTML renders a table for multiple targets
// tableValues is a slice of table.TableValues, each of which represents the same table from a single target
func RenderMultiTargetTableValuesAsHTML(tableValues []table.TableValues, targetNames []string) string {
if len(tableValues) == 0 {
return ""
}
values := [][]string{}
var tableValueStyles [][]string
for fieldIndex, field := range tableValues[0].Fields {
Expand Down