1
0
mirror of https://github.com/minio/mc.git synced 2025-07-30 07:23:03 +03:00

Improve format of perf tests output (#4330)

This commit is contained in:
Shireesh Anjal
2022-10-28 11:58:06 +05:30
committed by GitHub
parent 1f51635bc7
commit a2753bbaab
4 changed files with 155 additions and 22 deletions

View File

@ -68,11 +68,12 @@ func mainAdminSpeedTestDrive(ctx *cli.Context, aliasedURL string, outCh chan<- P
if globalJSON {
if e != nil {
printMsg(PerfTestResult{
printMsg(convertPerfResult(PerfTestResult{
Type: DrivePerfTest,
Err: e.Error(),
Final: true,
})
}))
return nil
}
@ -82,11 +83,11 @@ func mainAdminSpeedTestDrive(ctx *cli.Context, aliasedURL string, outCh chan<- P
results = append(results, result)
}
}
printMsg(PerfTestResult{
printMsg(convertPerfResult(PerfTestResult{
Type: DrivePerfTest,
DriveResult: results,
Final: true,
})
}))
return nil
}

View File

@ -64,17 +64,17 @@ func mainAdminSpeedTestNetperf(ctx *cli.Context, aliasedURL string, outCh chan<-
if globalJSON {
select {
case e := <-errorCh:
printMsg(PerfTestResult{
printMsg(convertPerfResult(PerfTestResult{
Type: NetPerfTest,
Err: e.Error(),
Final: true,
})
}))
case result := <-resultCh:
printMsg(PerfTestResult{
printMsg(convertPerfResult(PerfTestResult{
Type: NetPerfTest,
NetResult: &result,
Final: true,
})
}))
}
return nil
}

View File

@ -95,11 +95,11 @@ func mainAdminSpeedTestObject(ctx *cli.Context, aliasedURL string, outCh chan<-
if globalJSON {
if e != nil {
printMsg(PerfTestResult{
printMsg(convertPerfResult(PerfTestResult{
Type: ObjectPerfTest,
Err: e.Error(),
Final: true,
})
}))
return nil
}
@ -108,17 +108,13 @@ func mainAdminSpeedTestObject(ctx *cli.Context, aliasedURL string, outCh chan<-
if result.Version == "" {
continue
}
printMsg(PerfTestResult{
Type: ObjectPerfTest,
ObjectResult: &result,
})
}
printMsg(PerfTestResult{
printMsg(convertPerfResult(PerfTestResult{
Type: ObjectPerfTest,
ObjectResult: &result,
Final: true,
})
}))
return nil
}

View File

@ -106,6 +106,53 @@ EXAMPLES:
`,
}
// PerfTestOutput - stores the final output of performance test(s)
type PerfTestOutput struct {
ObjectResult *ObjTestResult `json:"object,omitempty"`
NetResult *madmin.NetperfResult `json:"network,omitempty"`
DriveResult []DriveTestResult `json:"drive,omitempty"`
Error string `json:"error,omitempty"`
}
// DriveTestResult - result of the drive performance test
type DriveTestResult struct {
Endpoint string `json:"endpoint"`
DrivePerf []madmin.DrivePerf `json:"drivePerf,omitempty"`
Error string `json:"error,omitempty"`
}
// ObjTestResult - result of the object performance test
type ObjTestResult struct {
Servers int `json:"servers"`
Drives int `json:"drives"`
Size int `json:"size"`
Concurrent int `json:"concurrent"`
PUTStats ObjPUTStats `json:"PUTStats"`
GETStats ObjGETStats `json:"GETStats"`
}
// ObjStatServer - Server level object performance stats
type ObjStatServer struct {
Endpoint string `json:"endpoint"`
Throughput uint64 `json:"throughput"`
ObjectsPerSec uint64 `json:"objectsPerSec"`
Error string `json:"error,omitempty"`
}
// ObjPUTStats - PUT stats of all the servers
type ObjPUTStats struct {
Throughput uint64 `json:"throughput"`
ObjectsPerSec uint64 `json:"objectsPerSec"`
Response madmin.Timings `json:"responseTime"`
Servers []ObjStatServer `json:"servers"`
}
// ObjGETStats - GET stats of all the servers
type ObjGETStats struct {
ObjPUTStats
TTFB madmin.Timings `json:"ttfb,omitempty"`
}
func objectTestVerboseResult(result *madmin.SpeedTestResult) (msg string) {
msg += "PUT:\n"
for _, node := range result.PUTStats.Servers {
@ -136,12 +183,13 @@ func objectTestShortResult(result *madmin.SpeedTestResult) (msg string) {
return msg
}
func (p PerfTestResult) String() string {
// String - dummy function to confirm to the 'message' interface. Not used.
func (p PerfTestOutput) String() string {
return ""
}
// JSON - jsonified update message.
func (p PerfTestResult) JSON() string {
// JSON - jsonified output of the perf tests
func (p PerfTestOutput) JSON() string {
JSONBytes, e := json.MarshalIndent(p, "", " ")
fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
return string(JSONBytes)
@ -176,6 +224,94 @@ func mainSupportPerf(ctx *cli.Context) error {
return nil
}
func convertDriveTestResult(dr madmin.DriveSpeedTestResult) DriveTestResult {
return DriveTestResult{
Endpoint: dr.Endpoint,
DrivePerf: dr.DrivePerf,
Error: dr.Error,
}
}
func convertDriveTestResults(driveResults []madmin.DriveSpeedTestResult) []DriveTestResult {
results := []DriveTestResult{}
for _, dr := range driveResults {
results = append(results, convertDriveTestResult(dr))
}
return results
}
func convertObjStatServers(ss []madmin.SpeedTestStatServer) []ObjStatServer {
out := []ObjStatServer{}
for _, s := range ss {
out = append(out, ObjStatServer{
Endpoint: s.Endpoint,
Throughput: s.ThroughputPerSec,
ObjectsPerSec: s.ObjectsPerSec,
Error: s.Err,
})
}
return out
}
func convertPUTStats(stats madmin.SpeedTestStats) ObjPUTStats {
return ObjPUTStats{
Throughput: stats.ThroughputPerSec,
ObjectsPerSec: stats.ObjectsPerSec,
Response: stats.Response,
Servers: convertObjStatServers(stats.Servers),
}
}
func convertGETStats(stats madmin.SpeedTestStats) ObjGETStats {
return ObjGETStats{
ObjPUTStats: convertPUTStats(stats),
TTFB: stats.TTFB,
}
}
func convertObjTestResult(objResult *madmin.SpeedTestResult) ObjTestResult {
if objResult == nil {
return ObjTestResult{}
}
result := ObjTestResult{
Servers: objResult.Servers,
Drives: objResult.Disks,
Size: objResult.Size,
Concurrent: objResult.Concurrent,
}
result.PUTStats = convertPUTStats(objResult.PUTStats)
result.GETStats = convertGETStats(objResult.GETStats)
return result
}
func updatePerfOutput(r PerfTestResult, out *PerfTestOutput) {
switch r.Type {
case DrivePerfTest:
out.DriveResult = convertDriveTestResults(r.DriveResult)
case ObjectPerfTest:
or := convertObjTestResult(r.ObjectResult)
out.ObjectResult = &or
case NetPerfTest:
out.NetResult = r.NetResult
default:
fatalIf(errDummy().Trace(), fmt.Sprintf("Invalid test type %d", r.Type))
}
}
func convertPerfResult(r PerfTestResult) PerfTestOutput {
out := PerfTestOutput{}
updatePerfOutput(r, &out)
return out
}
func convertPerfResults(results []PerfTestResult) PerfTestOutput {
out := PerfTestOutput{}
for _, r := range results {
updatePerfOutput(r, &out)
}
return out
}
func execSupportPerf(ctx *cli.Context, aliasedURL string, perfType string) {
alias, apiKey := initSubnetConnectivity(ctx, aliasedURL, true)
if len(apiKey) == 0 {
@ -193,7 +329,7 @@ func execSupportPerf(ctx *cli.Context, aliasedURL string, perfType string) {
resultFileName := resultFileNamePfx + ".json"
regInfo := getClusterRegInfo(getAdminInfo(aliasedURL), alias)
tmpFileName, e := zipPerfResult(results, resultFileName, regInfo)
tmpFileName, e := zipPerfResult(convertPerfResults(results), resultFileName, regInfo)
fatalIf(probe.NewError(e), "Error creating zip from perf test results:")
if globalAirgapped {
@ -268,7 +404,7 @@ func writeJSONObjToZip(zipWriter *zip.Writer, obj interface{}, filename string)
}
// compress MinIO performance output
func zipPerfResult(perfResult []PerfTestResult, resultFilename string, regInfo ClusterRegistrationInfo) (string, error) {
func zipPerfResult(perfOutput PerfTestOutput, resultFilename string, regInfo ClusterRegistrationInfo) (string, error) {
// Create profile zip file
tmpArchive, e := os.CreateTemp("", "mc-perf-")
@ -280,7 +416,7 @@ func zipPerfResult(perfResult []PerfTestResult, resultFilename string, regInfo C
zipWriter := zip.NewWriter(tmpArchive)
defer zipWriter.Close()
e = writeJSONObjToZip(zipWriter, perfResult, resultFilename)
e = writeJSONObjToZip(zipWriter, perfOutput, resultFilename)
if e != nil {
return "", e
}