mirror of
https://github.com/minio/mc.git
synced 2025-11-12 01:02:26 +03:00
Add admin profiling command (#2557)
Implement profiling command to start & download profiling data of a standalone or all nodes of a cluster. ``` 1. Start CPU profiling $ mc admin profiling start --type "cpu" myminio/ 2. Download latest profiling data under save under profiling.zip $ mc admin profiling stop myminio/ ```
This commit is contained in:
@@ -37,6 +37,7 @@ var adminCmd = cli.Command{
|
|||||||
adminCredsCmd,
|
adminCredsCmd,
|
||||||
adminConfigCmd,
|
adminConfigCmd,
|
||||||
adminHealCmd,
|
adminHealCmd,
|
||||||
|
adminProfilingCmd,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
111
cmd/admin-profiling-start.go
Normal file
111
cmd/admin-profiling-start.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Minio Client (C) 2018 Minio, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/minio/cli"
|
||||||
|
"github.com/minio/mc/pkg/console"
|
||||||
|
"github.com/minio/mc/pkg/probe"
|
||||||
|
"github.com/minio/minio/pkg/madmin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var adminProfilingStartFlags = []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "type",
|
||||||
|
Usage: "Profiler type, possible values are: `cpu`, `mem`, `block`, `mutex` and `trace`",
|
||||||
|
Value: "mem",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var adminProfilingStartCmd = cli.Command{
|
||||||
|
Name: "start",
|
||||||
|
Usage: "Start recording profiling data",
|
||||||
|
Action: mainAdminProfilingStart,
|
||||||
|
Before: setGlobalsFromContext,
|
||||||
|
Flags: append(adminProfilingStartFlags, globalFlags...),
|
||||||
|
HideHelpCommand: true,
|
||||||
|
CustomHelpTemplate: `NAME:
|
||||||
|
{{.HelpName}} - {{.Usage}}
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
{{.HelpName}} [FLAGS] TARGET
|
||||||
|
|
||||||
|
FLAGS:
|
||||||
|
{{range .VisibleFlags}}{{.}}
|
||||||
|
{{end}}
|
||||||
|
EXAMPLES:
|
||||||
|
1. Start CPU profiling
|
||||||
|
$ {{.HelpName}} --type cpu myminio/
|
||||||
|
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkAdminProfilingStartSyntax(ctx *cli.Context) {
|
||||||
|
// Check flags combinations
|
||||||
|
if len(ctx.Args()) != 1 {
|
||||||
|
cli.ShowCommandHelpAndExit(ctx, "start", 1) // last argument is exit code
|
||||||
|
}
|
||||||
|
|
||||||
|
profilerTypes := []madmin.ProfilerType{
|
||||||
|
madmin.ProfilerCPU,
|
||||||
|
madmin.ProfilerMEM,
|
||||||
|
madmin.ProfilerBlock,
|
||||||
|
madmin.ProfilerMutex,
|
||||||
|
madmin.ProfilerTrace,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the provided profiler type is known and supported
|
||||||
|
supportedProfiler := false
|
||||||
|
profilerType := strings.ToLower(ctx.String("type"))
|
||||||
|
for _, profiler := range profilerTypes {
|
||||||
|
if profilerType == string(profiler) {
|
||||||
|
supportedProfiler = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !supportedProfiler {
|
||||||
|
fatalIf(errDummy(), "Profiler type unrecognized. Possible values are: %v.", profilerTypes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mainAdminProfilingStart - the entry function of profiling command
|
||||||
|
func mainAdminProfilingStart(ctx *cli.Context) error {
|
||||||
|
// Check for command syntax
|
||||||
|
checkAdminProfilingStartSyntax(ctx)
|
||||||
|
|
||||||
|
// Get the alias parameter from cli
|
||||||
|
args := ctx.Args()
|
||||||
|
aliasedURL := args.Get(0)
|
||||||
|
|
||||||
|
profilerType := ctx.String("type")
|
||||||
|
|
||||||
|
// Create a new Minio Admin Client
|
||||||
|
client, err := newAdminClient(aliasedURL)
|
||||||
|
if err != nil {
|
||||||
|
fatalIf(err.Trace(aliasedURL), "Cannot initialize admin client.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start profiling
|
||||||
|
_, cmdErr := client.StartProfiling(madmin.ProfilerType(profilerType))
|
||||||
|
fatalIf(probe.NewError(cmdErr), "Unable to start profiling.")
|
||||||
|
|
||||||
|
console.Infoln("Profiling data successfully started.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
106
cmd/admin-profiling-stop.go
Normal file
106
cmd/admin-profiling-stop.go
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Minio Client (C) 2018 Minio, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/minio/cli"
|
||||||
|
"github.com/minio/mc/pkg/console"
|
||||||
|
"github.com/minio/mc/pkg/probe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var adminProfilingStopCmd = cli.Command{
|
||||||
|
Name: "stop",
|
||||||
|
Usage: "Stop and download profiling data",
|
||||||
|
Action: mainAdminProfilingStop,
|
||||||
|
Before: setGlobalsFromContext,
|
||||||
|
Flags: globalFlags,
|
||||||
|
HideHelpCommand: true,
|
||||||
|
CustomHelpTemplate: `NAME:
|
||||||
|
{{.HelpName}} - {{.Usage}}
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
{{.HelpName}} [FLAGS] TARGET
|
||||||
|
|
||||||
|
FLAGS:
|
||||||
|
{{range .VisibleFlags}}{{.}}
|
||||||
|
{{end}}
|
||||||
|
EXAMPLES:
|
||||||
|
2. Download latest profiling data in the current directory
|
||||||
|
$ {{.HelpName}} myminio/
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkAdminProfilingStopSyntax(ctx *cli.Context) {
|
||||||
|
if len(ctx.Args()) != 1 {
|
||||||
|
cli.ShowCommandHelpAndExit(ctx, "stop", 1) // last argument is exit code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mainAdminProfilingStop - the entry function of profiling stop command
|
||||||
|
func mainAdminProfilingStop(ctx *cli.Context) error {
|
||||||
|
// Check for command syntax
|
||||||
|
checkAdminProfilingStopSyntax(ctx)
|
||||||
|
|
||||||
|
// Get the alias parameter from cli
|
||||||
|
args := ctx.Args()
|
||||||
|
aliasedURL := args.Get(0)
|
||||||
|
|
||||||
|
// Create a new Minio Admin Client
|
||||||
|
client, err := newAdminClient(aliasedURL)
|
||||||
|
if err != nil {
|
||||||
|
fatalIf(err.Trace(aliasedURL), "Cannot initialize admin client.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create profiling zip file
|
||||||
|
tmpFile, e := ioutil.TempFile("", "mc-profiling-")
|
||||||
|
fatalIf(probe.NewError(e), "Unable to download profiling data.")
|
||||||
|
|
||||||
|
// Ask for profiling data, which will come compressed with zip format
|
||||||
|
zippedData, adminErr := client.DownloadProfilingData()
|
||||||
|
fatalIf(probe.NewError(adminErr), "Unable to download profiling data.")
|
||||||
|
|
||||||
|
// Copy zip content to target download file
|
||||||
|
_, e = io.Copy(tmpFile, zippedData)
|
||||||
|
fatalIf(probe.NewError(e), "Unable to download profiling data.")
|
||||||
|
|
||||||
|
// Close everything
|
||||||
|
zippedData.Close()
|
||||||
|
tmpFile.Close()
|
||||||
|
|
||||||
|
downloadPath := "profiling.zip"
|
||||||
|
|
||||||
|
fi, e := os.Stat(downloadPath)
|
||||||
|
if e == nil && !fi.IsDir() {
|
||||||
|
e = os.Rename(downloadPath, downloadPath+"."+time.Now().Format("2006-01-02T15:04:05.999999-07:00"))
|
||||||
|
fatalIf(probe.NewError(e), "Unable to create a backup of profiling.zip")
|
||||||
|
} else {
|
||||||
|
if !os.IsNotExist(e) {
|
||||||
|
fatal(probe.NewError(e), "Unable to download profiling data.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fatalIf(probe.NewError(os.Rename(tmpFile.Name(), downloadPath)), "Unable to download profiling data.")
|
||||||
|
|
||||||
|
console.Infof("Profiling data successfully downloaded as %s\n", downloadPath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
40
cmd/admin-profiling.go
Normal file
40
cmd/admin-profiling.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Minio Client (C) 2018 Minio, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/minio/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var adminProfilingCmd = cli.Command{
|
||||||
|
Name: "profiling",
|
||||||
|
Usage: "Generate profiling data for debugging purposes",
|
||||||
|
Action: mainAdminProfiling,
|
||||||
|
Before: setGlobalsFromContext,
|
||||||
|
Flags: globalFlags,
|
||||||
|
Subcommands: []cli.Command{
|
||||||
|
adminProfilingStartCmd,
|
||||||
|
adminProfilingStopCmd,
|
||||||
|
},
|
||||||
|
HideHelpCommand: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// mainAdminProfiling is the handle for "mc admin profiling" command.
|
||||||
|
func mainAdminProfiling(ctx *cli.Context) error {
|
||||||
|
cli.ShowCommandHelp(ctx, ctx.Args().First())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -45,6 +45,10 @@ func fatalIf(err *probe.Error, msg string, data ...interface{}) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
fatal(err, msg, data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fatal(err *probe.Error, msg string, data ...interface{}) {
|
||||||
if globalJSON {
|
if globalJSON {
|
||||||
errorMsg := errorMessage{
|
errorMsg := errorMessage{
|
||||||
Message: msg,
|
Message: msg,
|
||||||
|
|||||||
104
vendor/github.com/minio/minio/pkg/madmin/API.md
generated
vendored
104
vendor/github.com/minio/minio/pkg/madmin/API.md
generated
vendored
@@ -36,12 +36,12 @@ func main() {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
| Service operations | Info operations | Healing operations | Config operations | IAM operations | Misc |
|
| Service operations | Info operations | Healing operations | Config operations | Misc |
|
||||||
|:----------------------------|:----------------------------|:--------------------------------------|:--------------------------|:------------------------------------|:------------------------------------|
|
|:----------------------------|:----------------------------|:--------------------------------------|:--------------------------|:------------------------------------|
|
||||||
| [`ServiceStatus`](#ServiceStatus) | [`ServerInfo`](#ServerInfo) | [`Heal`](#Heal) | [`GetConfig`](#GetConfig) | [`AddUser`](#AddUser) | [`SetAdminCredentials`](#SetAdminCredentials) |
|
| [`ServiceStatus`](#ServiceStatus) | [`ServerInfo`](#ServerInfo) | [`Heal`](#Heal) | [`GetConfig`](#GetConfig) | [`SetCredentials`](#SetCredentials) |
|
||||||
| [`ServiceSendAction`](#ServiceSendAction) | | | [`SetConfig`](#SetConfig) | [`SetUserPolicy`](#SetUserPolicy) | [`StartProfiling`](#StartProfiling) |
|
| [`ServiceSendAction`](#ServiceSendAction) | | | [`SetConfig`](#SetConfig) | [`StartProfiling`](#StartProfiling) |
|
||||||
| | | | [`GetConfigKeys`](#GetConfigKeys) | [`ListUsers`](#ListUsers) | [`DownloadProfilingData`](#DownloadProfilingData) |
|
| | | | [`GetConfigKeys`](#GetConfigKeys) | [`DownloadProfilingData`](#DownloadProfilingData) |
|
||||||
| | | | [`SetConfigKeys`](#SetConfigKeys) | [`AddCannedPolicy`](#AddCannedPolicy) | |
|
| | | | [`SetConfigKeys`](#SetConfigKeys) | |
|
||||||
|
|
||||||
|
|
||||||
## 1. Constructor
|
## 1. Constructor
|
||||||
@@ -273,7 +273,7 @@ __Example__
|
|||||||
|
|
||||||
<a name="GetConfig"></a>
|
<a name="GetConfig"></a>
|
||||||
### GetConfig() ([]byte, error)
|
### GetConfig() ([]byte, error)
|
||||||
Get current `config.json` of a Minio server.
|
Get config.json of a minio setup.
|
||||||
|
|
||||||
__Example__
|
__Example__
|
||||||
|
|
||||||
@@ -295,17 +295,37 @@ __Example__
|
|||||||
|
|
||||||
|
|
||||||
<a name="SetConfig"></a>
|
<a name="SetConfig"></a>
|
||||||
### SetConfig(config io.Reader) error
|
### SetConfig(config io.Reader) (SetConfigResult, error)
|
||||||
Set a new `config.json` for a Minio server.
|
Set config.json of a minio setup and restart setup for configuration
|
||||||
|
change to take effect.
|
||||||
|
|
||||||
|
|
||||||
|
| Param | Type | Description |
|
||||||
|
|---|---|---|
|
||||||
|
|`st.Status` | _bool_ | true if set-config succeeded, false otherwise. |
|
||||||
|
|`st.NodeSummary.Name` | _string_ | Network address of the node. |
|
||||||
|
|`st.NodeSummary.ErrSet` | _bool_ | Bool representation indicating if an error is encountered with the node.|
|
||||||
|
|`st.NodeSummary.ErrMsg` | _string_ | String representation of the error (if any) on the node.|
|
||||||
|
|
||||||
|
|
||||||
__Example__
|
__Example__
|
||||||
|
|
||||||
``` go
|
``` go
|
||||||
config := bytes.NewReader([]byte(`config.json contents go here`))
|
config := bytes.NewReader([]byte(`config.json contents go here`))
|
||||||
if err := madmClnt.SetConfig(config); err != nil {
|
result, err := madmClnt.SetConfig(config)
|
||||||
|
if err != nil {
|
||||||
log.Fatalf("failed due to: %v", err)
|
log.Fatalf("failed due to: %v", err)
|
||||||
}
|
}
|
||||||
log.Println("SetConfig was successful")
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
enc := json.NewEncoder(&buf)
|
||||||
|
enc.SetEscapeHTML(false)
|
||||||
|
enc.SetIndent("", "\t")
|
||||||
|
err = enc.Encode(result)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(err)
|
||||||
|
}
|
||||||
|
log.Println("SetConfig: ", string(buf.Bytes()))
|
||||||
```
|
```
|
||||||
|
|
||||||
<a name="GetConfigKeys"></a>
|
<a name="GetConfigKeys"></a>
|
||||||
@@ -347,72 +367,18 @@ __Example__
|
|||||||
log.Println("New configuration successfully set")
|
log.Println("New configuration successfully set")
|
||||||
```
|
```
|
||||||
|
|
||||||
## 8. IAM operations
|
|
||||||
|
|
||||||
<a name="AddCannedPolicy"></a>
|
|
||||||
### AddCannedPolicy(policyName string, policy string) error
|
|
||||||
Create a new canned policy on Minio server.
|
|
||||||
|
|
||||||
__Example__
|
## 8. Misc operations
|
||||||
|
|
||||||
```
|
<a name="SetCredentials"></a>
|
||||||
policy := `{"Version": "2012-10-17","Statement": [{"Action": ["s3:GetObject"],"Effect": "Allow","Resource": ["arn:aws:s3:::my-bucketname/*"],"Sid": ""}]}`
|
### SetCredentials() error
|
||||||
|
|
||||||
if err = madmClnt.AddCannedPolicy("get-only", policy); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
<a name="AddUser"></a>
|
|
||||||
### AddUser(user string, secret string) error
|
|
||||||
Add a new user on a Minio server.
|
|
||||||
|
|
||||||
__Example__
|
|
||||||
|
|
||||||
``` go
|
|
||||||
if err = madmClnt.AddUser("newuser", "newstrongpassword"); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
<a name="SetUserPolicy"></a>
|
|
||||||
### SetUserPolicy(user string, policyName string) error
|
|
||||||
Enable a canned policy `get-only` for a given user on Minio server.
|
|
||||||
|
|
||||||
__Example__
|
|
||||||
|
|
||||||
``` go
|
|
||||||
if err = madmClnt.SetUserPolicy("newuser", "get-only"); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
<a name="ListUsers"></a>
|
|
||||||
### ListUsers() (map[string]UserInfo, error)
|
|
||||||
Lists all users on Minio server.
|
|
||||||
|
|
||||||
__Example__
|
|
||||||
|
|
||||||
``` go
|
|
||||||
users, err := madmClnt.ListUsers();
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
for k, v := range users {
|
|
||||||
fmt.Printf("User %s Status %s\n", k, v.Status)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 9. Misc operations
|
|
||||||
|
|
||||||
<a name="SetAdminCredentials"></a>
|
|
||||||
### SetAdminCredentials() error
|
|
||||||
Set new credentials of a Minio setup.
|
Set new credentials of a Minio setup.
|
||||||
|
|
||||||
__Example__
|
__Example__
|
||||||
|
|
||||||
``` go
|
``` go
|
||||||
err = madmClnt.SetAdminCredentials("YOUR-NEW-ACCESSKEY", "YOUR-NEW-SECRETKEY")
|
err = madmClnt.SetCredentials("YOUR-NEW-ACCESSKEY", "YOUR-NEW-SECRETKEY")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|||||||
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@@ -134,10 +134,10 @@
|
|||||||
"revisionTime": "2018-09-25T09:12:15Z"
|
"revisionTime": "2018-09-25T09:12:15Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "/5zp4gweRyx0NTrMTEwhCqdMaDA=",
|
"checksumSHA1": "/OdvNthJAc6DQQ7waRjvzAc7Q3c=",
|
||||||
"path": "github.com/minio/minio/pkg/madmin",
|
"path": "github.com/minio/minio/pkg/madmin",
|
||||||
"revision": "79e0add0e50323873b5d30fb41ef70584a9b6f22",
|
"revision": "aebfceeafb410452d1c03edfa69b7bc5509cc1bc",
|
||||||
"revisionTime": "2018-10-16T19:47:06Z"
|
"revisionTime": "2018-09-29T08:17:01Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "flg07CqTxM9togozKRQiJugao4s=",
|
"checksumSHA1": "flg07CqTxM9togozKRQiJugao4s=",
|
||||||
|
|||||||
Reference in New Issue
Block a user