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:
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user