mirror of
https://github.com/minio/mc.git
synced 2025-12-11 22:37:25 +03:00
rename mc admin top to mc support top (#4191)
This commit is contained in:
committed by
GitHub
parent
c2f1770cec
commit
c12f6e46c3
@@ -18,13 +18,8 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
|
||||||
"github.com/minio/cli"
|
"github.com/minio/cli"
|
||||||
"github.com/minio/madmin-go"
|
"github.com/minio/pkg/console"
|
||||||
"github.com/minio/mc/pkg/probe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var adminTopAPIFlags = []cli.Flag{
|
var adminTopAPIFlags = []cli.Flag{
|
||||||
@@ -54,83 +49,11 @@ var adminTopAPICmd = cli.Command{
|
|||||||
Before: setGlobalsFromContext,
|
Before: setGlobalsFromContext,
|
||||||
Flags: append(adminTopAPIFlags, globalFlags...),
|
Flags: append(adminTopAPIFlags, globalFlags...),
|
||||||
HideHelpCommand: true,
|
HideHelpCommand: true,
|
||||||
CustomHelpTemplate: `NAME:
|
CustomHelpTemplate: `Please use 'mc support top api'
|
||||||
{{.HelpName}} - {{.Usage}}
|
|
||||||
|
|
||||||
USAGE:
|
|
||||||
{{.HelpName}} [FLAGS] TARGET
|
|
||||||
|
|
||||||
FLAGS:
|
|
||||||
{{range .VisibleFlags}}{{.}}
|
|
||||||
{{end}}
|
|
||||||
EXAMPLES:
|
|
||||||
1. Display current in-progress all S3 API calls.
|
|
||||||
{{.Prompt}} {{.HelpName}} myminio/
|
|
||||||
|
|
||||||
2. Display current in-progress all 's3.PutObject' API calls.
|
|
||||||
{{.Prompt}} {{.HelpName}} --name s3.PutObject myminio/
|
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkAdminTopAPISyntax - validate all the passed arguments
|
|
||||||
func checkAdminTopAPISyntax(ctx *cli.Context) {
|
|
||||||
if len(ctx.Args()) == 0 || len(ctx.Args()) > 1 {
|
|
||||||
cli.ShowCommandHelpAndExit(ctx, "api", 1) // last argument is exit code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mainAdminTopAPI(ctx *cli.Context) error {
|
func mainAdminTopAPI(ctx *cli.Context) error {
|
||||||
checkAdminTopAPISyntax(ctx)
|
console.Infoln("Please use 'mc support top api'")
|
||||||
|
|
||||||
aliasedURL := ctx.Args().Get(0)
|
|
||||||
|
|
||||||
// Create a new MinIO Admin Client
|
|
||||||
client, err := newAdminClient(aliasedURL)
|
|
||||||
if err != nil {
|
|
||||||
fatalIf(err.Trace(aliasedURL), "Unable to initialize admin client.")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxt, cancel := context.WithCancel(globalContext)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
opts, e := tracingOpts(ctx, ctx.StringSlice("call"))
|
|
||||||
fatalIf(probe.NewError(e), "Unable to start tracing")
|
|
||||||
|
|
||||||
mopts := matchOpts{
|
|
||||||
funcNames: ctx.StringSlice("name"),
|
|
||||||
apiPaths: ctx.StringSlice("path"),
|
|
||||||
nodes: ctx.StringSlice("node"),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start listening on all trace activity.
|
|
||||||
traceCh := client.ServiceTrace(ctxt, opts)
|
|
||||||
done := make(chan struct{})
|
|
||||||
|
|
||||||
p := tea.NewProgram(initTraceUI())
|
|
||||||
go func() {
|
|
||||||
if e := p.Start(); e != nil {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
close(done)
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for apiCallInfo := range traceCh {
|
|
||||||
if apiCallInfo.Err != nil {
|
|
||||||
fatalIf(probe.NewError(apiCallInfo.Err), "Unable to fetch top API events")
|
|
||||||
}
|
|
||||||
if matchTrace(mopts, apiCallInfo) {
|
|
||||||
p.Send(topAPIResult{
|
|
||||||
apiCallInfo: apiCallInfo,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
p.Send(topAPIResult{
|
|
||||||
apiCallInfo: madmin.ServiceTraceInfo{},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
<-done
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,14 +18,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/fatih/color"
|
|
||||||
"github.com/minio/cli"
|
"github.com/minio/cli"
|
||||||
json "github.com/minio/colorjson"
|
|
||||||
"github.com/minio/madmin-go"
|
|
||||||
"github.com/minio/mc/pkg/probe"
|
|
||||||
"github.com/minio/pkg/console"
|
"github.com/minio/pkg/console"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -49,117 +42,11 @@ var adminTopLocksCmd = cli.Command{
|
|||||||
Action: mainAdminTopLocks,
|
Action: mainAdminTopLocks,
|
||||||
OnUsageError: onUsageError,
|
OnUsageError: onUsageError,
|
||||||
Flags: append(globalFlags, topLocksFlag...),
|
Flags: append(globalFlags, topLocksFlag...),
|
||||||
CustomHelpTemplate: `NAME:
|
CustomHelpTemplate: `Please use 'mc support top locks'
|
||||||
{{.HelpName}} - {{.Usage}}
|
|
||||||
|
|
||||||
USAGE:
|
|
||||||
{{.HelpName}} TARGET
|
|
||||||
|
|
||||||
FLAGS:
|
|
||||||
{{range .VisibleFlags}}{{.}}
|
|
||||||
{{end}}
|
|
||||||
EXAMPLES:
|
|
||||||
1. Get a list of the 10 oldest locks on a MinIO cluster.
|
|
||||||
{{.Prompt}} {{.HelpName}} myminio/
|
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
// lockMessage struct to list lock information.
|
|
||||||
type lockMessage struct {
|
|
||||||
Status string `json:"status"`
|
|
||||||
Lock madmin.LockEntry `json:"locks"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTimeDiff(timeStamp time.Time) (string, string) {
|
|
||||||
now := time.Now().UTC()
|
|
||||||
diff := now.Sub(timeStamp)
|
|
||||||
hours := int(diff.Hours())
|
|
||||||
minutes := int(diff.Minutes()) % 60
|
|
||||||
seconds := int(diff.Seconds()) % 60
|
|
||||||
if hours == 0 {
|
|
||||||
if minutes == 0 {
|
|
||||||
return "Lock", fmt.Sprint(seconds, " seconds")
|
|
||||||
}
|
|
||||||
return "Lock", fmt.Sprint(minutes, " minutes")
|
|
||||||
}
|
|
||||||
return "StaleLock", fmt.Sprint(hours, " hours")
|
|
||||||
}
|
|
||||||
|
|
||||||
// String colorized oldest locks message.
|
|
||||||
func (u lockMessage) String() string {
|
|
||||||
const (
|
|
||||||
timeFieldMaxLen = 20
|
|
||||||
resourceFieldMaxLen = -1
|
|
||||||
typeFieldMaxLen = 6
|
|
||||||
)
|
|
||||||
|
|
||||||
lockState, timeDiff := getTimeDiff(u.Lock.Timestamp)
|
|
||||||
return console.Colorize(lockState, newPrettyTable(" ",
|
|
||||||
Field{"Time", timeFieldMaxLen},
|
|
||||||
Field{"Type", typeFieldMaxLen},
|
|
||||||
Field{"Resource", resourceFieldMaxLen},
|
|
||||||
).buildRow(timeDiff, u.Lock.Type, u.Lock.Resource))
|
|
||||||
}
|
|
||||||
|
|
||||||
// JSON jsonified top oldest locks message.
|
|
||||||
func (u lockMessage) JSON() string {
|
|
||||||
u.Status = "success"
|
|
||||||
statusJSONBytes, e := json.MarshalIndent(u, "", " ")
|
|
||||||
fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
|
|
||||||
return string(statusJSONBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkAdminTopLocksSyntax - validate all the passed arguments
|
|
||||||
func checkAdminTopLocksSyntax(ctx *cli.Context) {
|
|
||||||
if len(ctx.Args()) == 0 || len(ctx.Args()) > 1 {
|
|
||||||
cli.ShowCommandHelpAndExit(ctx, "locks", 1) // last argument is exit code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mainAdminTopLocks(ctx *cli.Context) error {
|
func mainAdminTopLocks(ctx *cli.Context) error {
|
||||||
checkAdminTopLocksSyntax(ctx)
|
console.Infoln("Please use 'mc support top locks'")
|
||||||
|
|
||||||
// Get the alias parameter from cli
|
|
||||||
args := ctx.Args()
|
|
||||||
aliasedURL := args.Get(0)
|
|
||||||
|
|
||||||
// Create a new MinIO Admin Client
|
|
||||||
client, err := newAdminClient(aliasedURL)
|
|
||||||
fatalIf(err, "Unable to initialize admin connection.")
|
|
||||||
|
|
||||||
// Call top locks API
|
|
||||||
entries, e := client.TopLocksWithOpts(globalContext, madmin.TopLockOpts{
|
|
||||||
Count: ctx.Int("count"),
|
|
||||||
Stale: ctx.Bool("stale"),
|
|
||||||
})
|
|
||||||
fatalIf(probe.NewError(e), "Unable to get server locks list.")
|
|
||||||
|
|
||||||
console.SetColor("StaleLock", color.New(color.FgRed, color.Bold))
|
|
||||||
console.SetColor("Lock", color.New(color.FgBlue, color.Bold))
|
|
||||||
console.SetColor("Headers", color.New(color.FgGreen, color.Bold))
|
|
||||||
|
|
||||||
// Print
|
|
||||||
printLocks(entries)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func printHeaders() {
|
|
||||||
timeFieldMaxLen := 20
|
|
||||||
resourceFieldMaxLen := -1
|
|
||||||
typeFieldMaxLen := 6
|
|
||||||
console.Println(console.Colorize("Headers", newPrettyTable(" ",
|
|
||||||
Field{"Time", timeFieldMaxLen},
|
|
||||||
Field{"Type", typeFieldMaxLen},
|
|
||||||
Field{"Resource", resourceFieldMaxLen},
|
|
||||||
).buildRow("Time", "Type", "Resource")))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prints oldest locks.
|
|
||||||
func printLocks(locks madmin.LockEntries) {
|
|
||||||
if !globalJSON {
|
|
||||||
printHeaders()
|
|
||||||
}
|
|
||||||
for _, entry := range locks {
|
|
||||||
printMsg(lockMessage{Lock: entry})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -434,6 +434,8 @@ var completeCmds = map[string]complete.Predictor{
|
|||||||
"/support/perf": aliasCompleter,
|
"/support/perf": aliasCompleter,
|
||||||
"/support/metrics": aliasCompleter,
|
"/support/metrics": aliasCompleter,
|
||||||
"/support/status": aliasCompleter,
|
"/support/status": aliasCompleter,
|
||||||
|
"/support/top/locks": aliasCompleter,
|
||||||
|
"/support/top/api": aliasCompleter,
|
||||||
|
|
||||||
"/license/register": aliasCompleter,
|
"/license/register": aliasCompleter,
|
||||||
"/license/info": aliasCompleter,
|
"/license/info": aliasCompleter,
|
||||||
|
|||||||
136
cmd/support-top-api.go
Normal file
136
cmd/support-top-api.go
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
// Copyright (c) 2015-2022 MinIO, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of MinIO Object Storage stack
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/minio/cli"
|
||||||
|
"github.com/minio/madmin-go"
|
||||||
|
"github.com/minio/mc/pkg/probe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var supportTopAPIFlags = []cli.Flag{
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "name",
|
||||||
|
Usage: "summarize current calls for matching API name",
|
||||||
|
},
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "path",
|
||||||
|
Usage: "summarize current API calls only on matching path",
|
||||||
|
},
|
||||||
|
cli.StringSliceFlag{
|
||||||
|
Name: "node",
|
||||||
|
Usage: "summarize current API calls only on matching servers",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "errors, e",
|
||||||
|
Usage: "summarize current API calls throwing only errors",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var supportTopAPICmd = cli.Command{
|
||||||
|
Name: "api",
|
||||||
|
Usage: "summarize API events on MinIO server in real-time",
|
||||||
|
Action: mainSupportTopAPI,
|
||||||
|
OnUsageError: onUsageError,
|
||||||
|
Before: setGlobalsFromContext,
|
||||||
|
Flags: append(supportTopAPIFlags, globalFlags...),
|
||||||
|
HideHelpCommand: true,
|
||||||
|
CustomHelpTemplate: `NAME:
|
||||||
|
{{.HelpName}} - {{.Usage}}
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
{{.HelpName}} [FLAGS] TARGET
|
||||||
|
|
||||||
|
FLAGS:
|
||||||
|
{{range .VisibleFlags}}{{.}}
|
||||||
|
{{end}}
|
||||||
|
EXAMPLES:
|
||||||
|
1. Display current in-progress all S3 API calls.
|
||||||
|
{{.Prompt}} {{.HelpName}} myminio/
|
||||||
|
|
||||||
|
2. Display current in-progress all 's3.PutObject' API calls.
|
||||||
|
{{.Prompt}} {{.HelpName}} --name s3.PutObject myminio/
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkSupportTopAPISyntax - validate all the passed arguments
|
||||||
|
func checkSupportTopAPISyntax(ctx *cli.Context) {
|
||||||
|
if len(ctx.Args()) == 0 || len(ctx.Args()) > 1 {
|
||||||
|
cli.ShowCommandHelpAndExit(ctx, "api", 1) // last argument is exit code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mainSupportTopAPI(ctx *cli.Context) error {
|
||||||
|
checkSupportTopAPISyntax(ctx)
|
||||||
|
|
||||||
|
aliasedURL := ctx.Args().Get(0)
|
||||||
|
|
||||||
|
// Create a new MinIO Admin Client
|
||||||
|
client, err := newAdminClient(aliasedURL)
|
||||||
|
if err != nil {
|
||||||
|
fatalIf(err.Trace(aliasedURL), "Unable to initialize admin client.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt, cancel := context.WithCancel(globalContext)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
opts, e := tracingOpts(ctx, ctx.StringSlice("call"))
|
||||||
|
fatalIf(probe.NewError(e), "Unable to start tracing")
|
||||||
|
|
||||||
|
mopts := matchOpts{
|
||||||
|
funcNames: ctx.StringSlice("name"),
|
||||||
|
apiPaths: ctx.StringSlice("path"),
|
||||||
|
nodes: ctx.StringSlice("node"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start listening on all trace activity.
|
||||||
|
traceCh := client.ServiceTrace(ctxt, opts)
|
||||||
|
done := make(chan struct{})
|
||||||
|
|
||||||
|
p := tea.NewProgram(initTraceUI())
|
||||||
|
go func() {
|
||||||
|
if e := p.Start(); e != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for apiCallInfo := range traceCh {
|
||||||
|
if apiCallInfo.Err != nil {
|
||||||
|
fatalIf(probe.NewError(apiCallInfo.Err), "Unable to fetch top API events")
|
||||||
|
}
|
||||||
|
if matchTrace(mopts, apiCallInfo) {
|
||||||
|
p.Send(topAPIResult{
|
||||||
|
apiCallInfo: apiCallInfo,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
p.Send(topAPIResult{
|
||||||
|
apiCallInfo: madmin.ServiceTraceInfo{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
<-done
|
||||||
|
return nil
|
||||||
|
}
|
||||||
164
cmd/support-top-locks.go
Normal file
164
cmd/support-top-locks.go
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of MinIO Object Storage stack
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/fatih/color"
|
||||||
|
"github.com/minio/cli"
|
||||||
|
json "github.com/minio/colorjson"
|
||||||
|
"github.com/minio/madmin-go"
|
||||||
|
"github.com/minio/mc/pkg/probe"
|
||||||
|
"github.com/minio/pkg/console"
|
||||||
|
)
|
||||||
|
|
||||||
|
var supportTopLocksFlag = []cli.Flag{
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "stale",
|
||||||
|
Usage: "list stale locks ask",
|
||||||
|
},
|
||||||
|
cli.IntFlag{
|
||||||
|
Name: "count",
|
||||||
|
Usage: "number of top locks",
|
||||||
|
Hidden: true,
|
||||||
|
Value: 10,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var supportTopLocksCmd = cli.Command{
|
||||||
|
Name: "locks",
|
||||||
|
Usage: "get a list of the 10 oldest locks on a MinIO cluster.",
|
||||||
|
Before: setGlobalsFromContext,
|
||||||
|
Action: mainSupportTopLocks,
|
||||||
|
OnUsageError: onUsageError,
|
||||||
|
Flags: append(supportTopLocksFlag, globalFlags...),
|
||||||
|
CustomHelpTemplate: `NAME:
|
||||||
|
{{.HelpName}} - {{.Usage}}
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
{{.HelpName}} TARGET
|
||||||
|
|
||||||
|
FLAGS:
|
||||||
|
{{range .VisibleFlags}}{{.}}
|
||||||
|
{{end}}
|
||||||
|
EXAMPLES:
|
||||||
|
1. Get a list of the 10 oldest locks on a MinIO cluster.
|
||||||
|
{{.Prompt}} {{.HelpName}} myminio/
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
// lockMessage struct to list lock information.
|
||||||
|
type lockMessage struct {
|
||||||
|
Status string `json:"status"`
|
||||||
|
Lock madmin.LockEntry `json:"locks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTimeDiff(timeStamp time.Time) (string, string) {
|
||||||
|
now := time.Now().UTC()
|
||||||
|
diff := now.Sub(timeStamp)
|
||||||
|
hours := int(diff.Hours())
|
||||||
|
minutes := int(diff.Minutes()) % 60
|
||||||
|
seconds := int(diff.Seconds()) % 60
|
||||||
|
if hours == 0 {
|
||||||
|
if minutes == 0 {
|
||||||
|
return "Lock", fmt.Sprint(seconds, " seconds")
|
||||||
|
}
|
||||||
|
return "Lock", fmt.Sprint(minutes, " minutes")
|
||||||
|
}
|
||||||
|
return "StaleLock", fmt.Sprint(hours, " hours")
|
||||||
|
}
|
||||||
|
|
||||||
|
// String colorized oldest locks message.
|
||||||
|
func (u lockMessage) String() string {
|
||||||
|
const (
|
||||||
|
timeFieldMaxLen = 20
|
||||||
|
resourceFieldMaxLen = -1
|
||||||
|
typeFieldMaxLen = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
lockState, timeDiff := getTimeDiff(u.Lock.Timestamp)
|
||||||
|
return console.Colorize(lockState, newPrettyTable(" ",
|
||||||
|
Field{"Time", timeFieldMaxLen},
|
||||||
|
Field{"Type", typeFieldMaxLen},
|
||||||
|
Field{"Resource", resourceFieldMaxLen},
|
||||||
|
).buildRow(timeDiff, u.Lock.Type, u.Lock.Resource))
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON jsonified top oldest locks message.
|
||||||
|
func (u lockMessage) JSON() string {
|
||||||
|
u.Status = "success"
|
||||||
|
statusJSONBytes, e := json.MarshalIndent(u, "", " ")
|
||||||
|
fatalIf(probe.NewError(e), "Unable to marshal into JSON.")
|
||||||
|
return string(statusJSONBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkAdminTopLocksSyntax - validate all the passed arguments
|
||||||
|
func checkSupportTopLocksSyntax(ctx *cli.Context) {
|
||||||
|
if len(ctx.Args()) == 0 || len(ctx.Args()) > 1 {
|
||||||
|
cli.ShowCommandHelpAndExit(ctx, "locks", 1) // last argument is exit code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mainSupportTopLocks(ctx *cli.Context) error {
|
||||||
|
checkSupportTopLocksSyntax(ctx)
|
||||||
|
// Get the alias parameter from cli
|
||||||
|
args := ctx.Args()
|
||||||
|
aliasedURL := args.Get(0)
|
||||||
|
|
||||||
|
// Create a new MinIO Admin Client
|
||||||
|
client, err := newAdminClient(aliasedURL)
|
||||||
|
fatalIf(err, "Unable to initialize admin connection.")
|
||||||
|
|
||||||
|
// Call top locks API
|
||||||
|
entries, e := client.TopLocksWithOpts(globalContext, madmin.TopLockOpts{
|
||||||
|
Count: ctx.Int("count"),
|
||||||
|
Stale: ctx.Bool("stale"),
|
||||||
|
})
|
||||||
|
fatalIf(probe.NewError(e), "Unable to get server locks list.")
|
||||||
|
|
||||||
|
console.SetColor("StaleLock", color.New(color.FgRed, color.Bold))
|
||||||
|
console.SetColor("Lock", color.New(color.FgBlue, color.Bold))
|
||||||
|
console.SetColor("Headers", color.New(color.FgGreen, color.Bold))
|
||||||
|
|
||||||
|
// Print
|
||||||
|
printLocks(entries)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printHeaders() {
|
||||||
|
timeFieldMaxLen := 20
|
||||||
|
resourceFieldMaxLen := -1
|
||||||
|
typeFieldMaxLen := 6
|
||||||
|
console.Println(console.Colorize("Headers", newPrettyTable(" ",
|
||||||
|
Field{"Time", timeFieldMaxLen},
|
||||||
|
Field{"Type", typeFieldMaxLen},
|
||||||
|
Field{"Resource", resourceFieldMaxLen},
|
||||||
|
).buildRow("Time", "Type", "Resource")))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints oldest locks.
|
||||||
|
func printLocks(locks madmin.LockEntries) {
|
||||||
|
if !globalJSON {
|
||||||
|
printHeaders()
|
||||||
|
}
|
||||||
|
for _, entry := range locks {
|
||||||
|
printMsg(lockMessage{Lock: entry})
|
||||||
|
}
|
||||||
|
}
|
||||||
42
cmd/support-top.go
Normal file
42
cmd/support-top.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (c) 2015-2021 MinIO, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of MinIO Object Storage stack
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import "github.com/minio/cli"
|
||||||
|
|
||||||
|
var supportTopSubcommands = []cli.Command{
|
||||||
|
supportTopAPICmd,
|
||||||
|
supportTopLocksCmd,
|
||||||
|
}
|
||||||
|
|
||||||
|
var supportTopCmd = cli.Command{
|
||||||
|
Name: "top",
|
||||||
|
Usage: "provide top like statistics for MinIO",
|
||||||
|
Action: mainSupportTop,
|
||||||
|
Before: setGlobalsFromContext,
|
||||||
|
Flags: globalFlags,
|
||||||
|
Subcommands: supportTopSubcommands,
|
||||||
|
HideHelpCommand: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// mainSupportTop is the handle for "mc support top" command.
|
||||||
|
func mainSupportTop(ctx *cli.Context) error {
|
||||||
|
commandNotFound(ctx, supportTopSubcommands)
|
||||||
|
return nil
|
||||||
|
// Sub-commands like "locks" have their own main.
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ var supportSubcommands = []cli.Command{
|
|||||||
supportPerfCmd,
|
supportPerfCmd,
|
||||||
supportInspectCmd,
|
supportInspectCmd,
|
||||||
supportProfileCmd,
|
supportProfileCmd,
|
||||||
|
supportTopCmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
var supportCmd = cli.Command{
|
var supportCmd = cli.Command{
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ prometheus manages prometheus config
|
|||||||
kms perform KMS management operations
|
kms perform KMS management operations
|
||||||
bucket manage buckets defined in the MinIO server
|
bucket manage buckets defined in the MinIO server
|
||||||
tier manage remote tier targets for ILM transition
|
tier manage remote tier targets for ILM transition
|
||||||
top provide top like statistics for MinIO
|
|
||||||
trace show http trace for MinIO server
|
trace show http trace for MinIO server
|
||||||
console show console logs for MinIO server
|
console show console logs for MinIO server
|
||||||
```
|
```
|
||||||
@@ -647,23 +646,6 @@ mc admin config import myminio < /tmp/my-serverconfig
|
|||||||
Healing is automatic on server side which runs on a continuous basis on a low priority thread, `mc admin heal` is deprecated and will be removed in future.
|
Healing is automatic on server side which runs on a continuous basis on a low priority thread, `mc admin heal` is deprecated and will be removed in future.
|
||||||
|
|
||||||
|
|
||||||
<a name="top"></a>
|
|
||||||
### Command `top` - provide top like statistics for MinIO
|
|
||||||
NOTE: This command is only applicable for a distributed MinIO setup. It is not supported on single node and gateway deployments.
|
|
||||||
|
|
||||||
```
|
|
||||||
NAME:
|
|
||||||
mc admin top - provide top like statistics for MinIO
|
|
||||||
|
|
||||||
COMMANDS:
|
|
||||||
locks Get a list of the 10 oldest locks on a MinIO cluster.
|
|
||||||
```
|
|
||||||
|
|
||||||
*Example: Get a list of the 10 oldest locks on a distributed MinIO cluster, where 'myminio' is the MinIO cluster alias.*
|
|
||||||
|
|
||||||
```
|
|
||||||
mc admin top locks myminio
|
|
||||||
```
|
|
||||||
|
|
||||||
<a name="trace"></a>
|
<a name="trace"></a>
|
||||||
### Command `trace` - Show http trace for MinIO server
|
### Command `trace` - Show http trace for MinIO server
|
||||||
|
|||||||
@@ -1925,6 +1925,7 @@ NAME:
|
|||||||
mc support inspect upload raw object contents for analysis
|
mc support inspect upload raw object contents for analysis
|
||||||
mc support profile generate profile data for debugging
|
mc support profile generate profile data for debugging
|
||||||
mc support logs configure/display MinIO console logs
|
mc support logs configure/display MinIO console logs
|
||||||
|
mc support top provide top like statistics for MinIO
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1968,6 +1969,16 @@ Enable logs for cluster with alias 'play'
|
|||||||
mc support logs enable play
|
mc support logs enable play
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Get a list of the 10 oldest locks on a distributed MinIO cluster, where 'myminio' is the MinIO cluster alias.*
|
||||||
|
```
|
||||||
|
mc admin top locks myminio
|
||||||
|
```
|
||||||
|
|
||||||
|
Display current in-progress all 's3.PutObject' API calls.
|
||||||
|
```
|
||||||
|
mc support top api --name s3.PutObject myminio/
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
<a name="ping"></a>
|
<a name="ping"></a>
|
||||||
### Command `ping`
|
### Command `ping`
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -60,6 +60,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||||
@@ -272,6 +273,7 @@ github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e
|
|||||||
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
|
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
||||||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
|
|||||||
Reference in New Issue
Block a user