github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/support-top-api.go (about) 1 // Copyright (c) 2015-2023 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "context" 22 23 tea "github.com/charmbracelet/bubbletea" 24 "github.com/minio/cli" 25 "github.com/minio/madmin-go/v3" 26 "github.com/minio/mc/pkg/probe" 27 ) 28 29 var supportTopAPIFlags = []cli.Flag{ 30 cli.StringSliceFlag{ 31 Name: "name", 32 Usage: "summarize current calls for matching API name", 33 }, 34 cli.StringSliceFlag{ 35 Name: "path", 36 Usage: "summarize current API calls only on matching path", 37 }, 38 cli.StringSliceFlag{ 39 Name: "node", 40 Usage: "summarize current API calls only on matching servers", 41 }, 42 cli.BoolFlag{ 43 Name: "errors, e", 44 Usage: "summarize current API calls throwing only errors", 45 }, 46 } 47 48 var supportTopAPICmd = cli.Command{ 49 Name: "api", 50 Usage: "summarize API events on MinIO server in real-time", 51 Action: mainSupportTopAPI, 52 OnUsageError: onUsageError, 53 Before: setGlobalsFromContext, 54 Flags: append(supportTopAPIFlags, supportGlobalFlags...), 55 HideHelpCommand: true, 56 CustomHelpTemplate: `NAME: 57 {{.HelpName}} - {{.Usage}} 58 59 USAGE: 60 {{.HelpName}} [FLAGS] TARGET 61 62 FLAGS: 63 {{range .VisibleFlags}}{{.}} 64 {{end}} 65 EXAMPLES: 66 1. Display current in-progress all S3 API calls. 67 {{.Prompt}} {{.HelpName}} myminio/ 68 69 2. Display current in-progress all 's3.PutObject' API calls. 70 {{.Prompt}} {{.HelpName}} --name s3.PutObject myminio/ 71 `, 72 } 73 74 // checkSupportTopAPISyntax - validate all the passed arguments 75 func checkSupportTopAPISyntax(ctx *cli.Context) { 76 if len(ctx.Args()) == 0 || len(ctx.Args()) > 1 { 77 showCommandHelpAndExit(ctx, 1) // last argument is exit code 78 } 79 } 80 81 func mainSupportTopAPI(ctx *cli.Context) error { 82 checkSupportTopAPISyntax(ctx) 83 84 aliasedURL := ctx.Args().Get(0) 85 alias, _ := url2Alias(aliasedURL) 86 validateClusterRegistered(alias, false) 87 88 // Create a new MinIO Admin Client 89 client, err := newAdminClient(aliasedURL) 90 if err != nil { 91 fatalIf(err.Trace(aliasedURL), "Unable to initialize admin client.") 92 return nil 93 } 94 95 ctxt, cancel := context.WithCancel(globalContext) 96 defer cancel() 97 98 opts, e := tracingOpts(ctx, ctx.StringSlice("call")) 99 fatalIf(probe.NewError(e), "Unable to start tracing") 100 101 mopts := matchingOpts(ctx) 102 103 // Start listening on all trace activity. 104 traceCh := client.ServiceTrace(ctxt, opts) 105 106 p := tea.NewProgram(initTraceUI()) 107 go func() { 108 for apiCallInfo := range traceCh { 109 if apiCallInfo.Err != nil { 110 fatalIf(probe.NewError(apiCallInfo.Err), "Unable to fetch top API events") 111 } 112 if mopts.matches(apiCallInfo) { 113 p.Send(topAPIResult{ 114 apiCallInfo: apiCallInfo, 115 }) 116 } 117 p.Send(topAPIResult{ 118 apiCallInfo: madmin.ServiceTraceInfo{}, 119 }) 120 } 121 }() 122 123 if _, e := p.Run(); e != nil { 124 cancel() 125 fatalIf(probe.NewError(e).Trace(aliasedURL), "Unable to fetch top API events") 126 } 127 128 return nil 129 }