diff --git a/pkg/analyze/host_filesystem_performance.go b/pkg/analyze/host_filesystem_performance.go index 3f9ae3706..8d84fd65d 100644 --- a/pkg/analyze/host_filesystem_performance.go +++ b/pkg/analyze/host_filesystem_performance.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "log" - "path/filepath" "strings" "text/template" "time" @@ -30,138 +29,40 @@ func (a *AnalyzeHostFilesystemPerformance) IsExcluded() (bool, error) { func (a *AnalyzeHostFilesystemPerformance) Analyze( getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents, ) ([]*AnalyzeResult, error) { - hostAnalyzer := a.hostAnalyzer - - result := &AnalyzeResult{ - Title: a.Title(), - } - - collectorName := hostAnalyzer.CollectorName + collectorName := a.hostAnalyzer.CollectorName if collectorName == "" { collectorName = "filesystemPerformance" } - name := filepath.Join("host-collectors/filesystemPerformance", collectorName+".json") - contents, err := getCollectedFileContents(name) + const nodeBaseDir = "host-collectors/filesystemPerformance" + localPath := fmt.Sprintf("%s/%s.json", nodeBaseDir, collectorName) + fileName := fmt.Sprintf("%s.json", collectorName) + + collectedContents, err := retrieveCollectedContents( + getCollectedFileContents, + localPath, + nodeBaseDir, + fileName, + ) if err != nil { - if len(hostAnalyzer.Outcomes) >= 1 { - // if the very first outcome is FILE_NOT_COLLECTED', then use that outcome - // otherwise, return the error - if hostAnalyzer.Outcomes[0].Fail != nil && hostAnalyzer.Outcomes[0].Fail.When == FILE_NOT_COLLECTED { - result.IsFail = true - result.Message = renderFSPerfOutcome(hostAnalyzer.Outcomes[0].Fail.Message, collect.FSPerfResults{}) - result.URI = hostAnalyzer.Outcomes[0].Fail.URI - return []*AnalyzeResult{result}, nil - } - if hostAnalyzer.Outcomes[0].Warn != nil && hostAnalyzer.Outcomes[0].Warn.When == FILE_NOT_COLLECTED { - result.IsWarn = true - result.Message = renderFSPerfOutcome(hostAnalyzer.Outcomes[0].Warn.Message, collect.FSPerfResults{}) - result.URI = hostAnalyzer.Outcomes[0].Warn.URI - return []*AnalyzeResult{result}, nil - } - if hostAnalyzer.Outcomes[0].Pass != nil && hostAnalyzer.Outcomes[0].Pass.When == FILE_NOT_COLLECTED { - result.IsPass = true - result.Message = renderFSPerfOutcome(hostAnalyzer.Outcomes[0].Pass.Message, collect.FSPerfResults{}) - result.URI = hostAnalyzer.Outcomes[0].Pass.URI - return []*AnalyzeResult{result}, nil - } - } - - return nil, errors.Wrapf(err, "failed to get collected file %s", name) - } - - fioResult := collect.FioResult{} - if err := json.Unmarshal(contents, &fioResult); err != nil { - return nil, errors.Wrapf(err, "failed to unmarshal fio results from %s", name) + return []*AnalyzeResult{{Title: a.Title()}}, err } - var job *collect.FioJobs - for _, j := range fioResult.Jobs { - if j.JobName == collect.FioJobName { - job = &j - break + var results []*AnalyzeResult + for _, content := range collectedContents { + currentTitle := a.Title() + if content.NodeName != "" { + currentTitle = fmt.Sprintf("%s - Node %s", a.Title(), content.NodeName) } - } - if job == nil { - return nil, errors.Errorf("no job named 'fsperf' found in fio results from %s", name) - } - - fioWriteLatency := job.Sync - - fsPerf := fioWriteLatency.FSPerfResults() - if err := json.Unmarshal(contents, &fsPerf); err != nil { - return nil, errors.Wrapf(err, "failed to unmarshal filesystem performance results from %s", name) - } - - for _, outcome := range hostAnalyzer.Outcomes { - - if outcome.Fail != nil { - if outcome.Fail.When == "" { - result.IsFail = true - result.Message = renderFSPerfOutcome(outcome.Fail.Message, fsPerf) - result.URI = outcome.Fail.URI - - return []*AnalyzeResult{result}, nil - } - - isMatch, err := compareHostFilesystemPerformanceConditionalToActual(outcome.Fail.When, fsPerf) - if err != nil { - return nil, errors.Wrapf(err, "failed to compare %q", outcome.Fail.When) - } - - if isMatch { - result.IsFail = true - result.Message = renderFSPerfOutcome(outcome.Fail.Message, fsPerf) - result.URI = outcome.Fail.URI - - return []*AnalyzeResult{result}, nil - } - } else if outcome.Warn != nil { - if outcome.Warn.When == "" { - result.IsWarn = true - result.Message = renderFSPerfOutcome(outcome.Warn.Message, fsPerf) - result.URI = outcome.Warn.URI - - return []*AnalyzeResult{result}, nil - } - - isMatch, err := compareHostFilesystemPerformanceConditionalToActual(outcome.Warn.When, fsPerf) - if err != nil { - return nil, errors.Wrapf(err, "failed to compare %q", outcome.Warn.When) - } - - if isMatch { - result.IsWarn = true - result.Message = renderFSPerfOutcome(outcome.Warn.Message, fsPerf) - result.URI = outcome.Warn.URI - - return []*AnalyzeResult{result}, nil - } - } else if outcome.Pass != nil { - if outcome.Pass.When == "" { - result.IsPass = true - result.Message = renderFSPerfOutcome(outcome.Pass.Message, fsPerf) - result.URI = outcome.Pass.URI - - return []*AnalyzeResult{result}, nil - } - - isMatch, err := compareHostFilesystemPerformanceConditionalToActual(outcome.Pass.When, fsPerf) - if err != nil { - return nil, errors.Wrapf(err, "failed to compare %q", outcome.Pass.When) - } - - if isMatch { - result.IsPass = true - result.Message = renderFSPerfOutcome(outcome.Pass.Message, fsPerf) - result.URI = outcome.Pass.URI - - return []*AnalyzeResult{result}, nil - } - + result, err := a.analyzeSingleNode(content, currentTitle) + if err != nil { + return nil, errors.Wrapf(err, "failed to analyze filesystem performance for %s", currentTitle) + } + if result != nil { + results = append(results, result...) } } - return []*AnalyzeResult{result}, nil + return results, nil } func compareHostFilesystemPerformanceConditionalToActual(conditional string, fsPerf collect.FSPerfResults) (res bool, err error) { @@ -258,3 +159,103 @@ func renderFSPerfOutcome(outcome string, fsPerf collect.FSPerfResults) string { } return buf.String() } + +func (a *AnalyzeHostFilesystemPerformance) analyzeSingleNode(content collectedContent, currentTitle string) ([]*AnalyzeResult, error) { + hostAnalyzer := a.hostAnalyzer + result := &AnalyzeResult{ + Title: currentTitle, + } + fioResult := collect.FioResult{} + if err := json.Unmarshal(content.Data, &fioResult); err != nil { + return nil, errors.Wrapf(err, "failed to unmarshal fio results from %s", currentTitle) + } + + var job *collect.FioJobs + for _, j := range fioResult.Jobs { + if j.JobName == collect.FioJobName { + job = &j + break + } + } + if job == nil { + return nil, errors.Errorf("no job named 'fsperf' found in fio results from %s", currentTitle) + } + + fioWriteLatency := job.Sync + + fsPerf := fioWriteLatency.FSPerfResults() + if err := json.Unmarshal(content.Data, &fsPerf); err != nil { + return nil, errors.Wrapf(err, "failed to unmarshal filesystem performance results from %s", currentTitle) + } + + for _, outcome := range hostAnalyzer.Outcomes { + + if outcome.Fail != nil { + if outcome.Fail.When == "" { + result.IsFail = true + result.Message = renderFSPerfOutcome(outcome.Fail.Message, fsPerf) + result.URI = outcome.Fail.URI + + return []*AnalyzeResult{result}, nil + } + + isMatch, err := compareHostFilesystemPerformanceConditionalToActual(outcome.Fail.When, fsPerf) + if err != nil { + return nil, errors.Wrapf(err, "failed to compare %q", outcome.Fail.When) + } + + if isMatch { + result.IsFail = true + result.Message = renderFSPerfOutcome(outcome.Fail.Message, fsPerf) + result.URI = outcome.Fail.URI + + return []*AnalyzeResult{result}, nil + } + } else if outcome.Warn != nil { + if outcome.Warn.When == "" { + result.IsWarn = true + result.Message = renderFSPerfOutcome(outcome.Warn.Message, fsPerf) + result.URI = outcome.Warn.URI + + return []*AnalyzeResult{result}, nil + } + + isMatch, err := compareHostFilesystemPerformanceConditionalToActual(outcome.Warn.When, fsPerf) + if err != nil { + return nil, errors.Wrapf(err, "failed to compare %q", outcome.Warn.When) + } + + if isMatch { + result.IsWarn = true + result.Message = renderFSPerfOutcome(outcome.Warn.Message, fsPerf) + result.URI = outcome.Warn.URI + + return []*AnalyzeResult{result}, nil + } + } else if outcome.Pass != nil { + if outcome.Pass.When == "" { + result.IsPass = true + result.Message = renderFSPerfOutcome(outcome.Pass.Message, fsPerf) + result.URI = outcome.Pass.URI + + return []*AnalyzeResult{result}, nil + } + + isMatch, err := compareHostFilesystemPerformanceConditionalToActual(outcome.Pass.When, fsPerf) + if err != nil { + return nil, errors.Wrapf(err, "failed to compare %q", outcome.Pass.When) + } + + if isMatch { + result.IsPass = true + result.Message = renderFSPerfOutcome(outcome.Pass.Message, fsPerf) + result.URI = outcome.Pass.URI + + return []*AnalyzeResult{result}, nil + } + + } + } + + return []*AnalyzeResult{result}, nil +}