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 globalJSON {
|
||||||
if e != nil {
|
if e != nil {
|
||||||
printMsg(PerfTestResult{
|
printMsg(convertPerfResult(PerfTestResult{
|
||||||
Type: DrivePerfTest,
|
Type: DrivePerfTest,
|
||||||
Err: e.Error(),
|
Err: e.Error(),
|
||||||
Final: true,
|
Final: true,
|
||||||
})
|
}))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,11 +83,11 @@ func mainAdminSpeedTestDrive(ctx *cli.Context, aliasedURL string, outCh chan<- P
|
|||||||
results = append(results, result)
|
results = append(results, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printMsg(PerfTestResult{
|
printMsg(convertPerfResult(PerfTestResult{
|
||||||
Type: DrivePerfTest,
|
Type: DrivePerfTest,
|
||||||
DriveResult: results,
|
DriveResult: results,
|
||||||
Final: true,
|
Final: true,
|
||||||
})
|
}))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -64,17 +64,17 @@ func mainAdminSpeedTestNetperf(ctx *cli.Context, aliasedURL string, outCh chan<-
|
|||||||
if globalJSON {
|
if globalJSON {
|
||||||
select {
|
select {
|
||||||
case e := <-errorCh:
|
case e := <-errorCh:
|
||||||
printMsg(PerfTestResult{
|
printMsg(convertPerfResult(PerfTestResult{
|
||||||
Type: NetPerfTest,
|
Type: NetPerfTest,
|
||||||
Err: e.Error(),
|
Err: e.Error(),
|
||||||
Final: true,
|
Final: true,
|
||||||
})
|
}))
|
||||||
case result := <-resultCh:
|
case result := <-resultCh:
|
||||||
printMsg(PerfTestResult{
|
printMsg(convertPerfResult(PerfTestResult{
|
||||||
Type: NetPerfTest,
|
Type: NetPerfTest,
|
||||||
NetResult: &result,
|
NetResult: &result,
|
||||||
Final: true,
|
Final: true,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -95,11 +95,11 @@ func mainAdminSpeedTestObject(ctx *cli.Context, aliasedURL string, outCh chan<-
|
|||||||
|
|
||||||
if globalJSON {
|
if globalJSON {
|
||||||
if e != nil {
|
if e != nil {
|
||||||
printMsg(PerfTestResult{
|
printMsg(convertPerfResult(PerfTestResult{
|
||||||
Type: ObjectPerfTest,
|
Type: ObjectPerfTest,
|
||||||
Err: e.Error(),
|
Err: e.Error(),
|
||||||
Final: true,
|
Final: true,
|
||||||
})
|
}))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,17 +108,13 @@ func mainAdminSpeedTestObject(ctx *cli.Context, aliasedURL string, outCh chan<-
|
|||||||
if result.Version == "" {
|
if result.Version == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
printMsg(PerfTestResult{
|
|
||||||
Type: ObjectPerfTest,
|
|
||||||
ObjectResult: &result,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printMsg(PerfTestResult{
|
printMsg(convertPerfResult(PerfTestResult{
|
||||||
Type: ObjectPerfTest,
|
Type: ObjectPerfTest,
|
||||||
ObjectResult: &result,
|
ObjectResult: &result,
|
||||||
Final: true,
|
Final: true,
|
||||||
})
|
}))
|
||||||
|
|
||||||
return nil
|
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) {
|
func objectTestVerboseResult(result *madmin.SpeedTestResult) (msg string) {
|
||||||
msg += "PUT:\n"
|
msg += "PUT:\n"
|
||||||
for _, node := range result.PUTStats.Servers {
|
for _, node := range result.PUTStats.Servers {
|
||||||
@ -136,12 +183,13 @@ func objectTestShortResult(result *madmin.SpeedTestResult) (msg string) {
|
|||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PerfTestResult) String() string {
|
// String - dummy function to confirm to the 'message' interface. Not used.
|
||||||
|
func (p PerfTestOutput) String() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON - jsonified update message.
|
// JSON - jsonified output of the perf tests
|
||||||
func (p PerfTestResult) JSON() string {
|
func (p PerfTestOutput) JSON() string {
|
||||||
JSONBytes, e := json.MarshalIndent(p, "", " ")
|
JSONBytes, e := json.MarshalIndent(p, "", " ")
|
||||||
fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
|
fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
|
||||||
return string(JSONBytes)
|
return string(JSONBytes)
|
||||||
@ -176,6 +224,94 @@ func mainSupportPerf(ctx *cli.Context) error {
|
|||||||
return nil
|
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) {
|
func execSupportPerf(ctx *cli.Context, aliasedURL string, perfType string) {
|
||||||
alias, apiKey := initSubnetConnectivity(ctx, aliasedURL, true)
|
alias, apiKey := initSubnetConnectivity(ctx, aliasedURL, true)
|
||||||
if len(apiKey) == 0 {
|
if len(apiKey) == 0 {
|
||||||
@ -193,7 +329,7 @@ func execSupportPerf(ctx *cli.Context, aliasedURL string, perfType string) {
|
|||||||
resultFileName := resultFileNamePfx + ".json"
|
resultFileName := resultFileNamePfx + ".json"
|
||||||
|
|
||||||
regInfo := getClusterRegInfo(getAdminInfo(aliasedURL), alias)
|
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:")
|
fatalIf(probe.NewError(e), "Error creating zip from perf test results:")
|
||||||
|
|
||||||
if globalAirgapped {
|
if globalAirgapped {
|
||||||
@ -268,7 +404,7 @@ func writeJSONObjToZip(zipWriter *zip.Writer, obj interface{}, filename string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compress MinIO performance output
|
// 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
|
// Create profile zip file
|
||||||
tmpArchive, e := os.CreateTemp("", "mc-perf-")
|
tmpArchive, e := os.CreateTemp("", "mc-perf-")
|
||||||
|
|
||||||
@ -280,7 +416,7 @@ func zipPerfResult(perfResult []PerfTestResult, resultFilename string, regInfo C
|
|||||||
zipWriter := zip.NewWriter(tmpArchive)
|
zipWriter := zip.NewWriter(tmpArchive)
|
||||||
defer zipWriter.Close()
|
defer zipWriter.Close()
|
||||||
|
|
||||||
e = writeJSONObjToZip(zipWriter, perfResult, resultFilename)
|
e = writeJSONObjToZip(zipWriter, perfOutput, resultFilename)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return "", e
|
return "", e
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user