1
0
mirror of https://github.com/minio/mc.git synced 2025-11-10 13:42:32 +03:00
Files
mc/cmd/admin-bucket-remote-bandwidth.go
2022-11-01 08:04:26 -07:00

197 lines
5.4 KiB
Go

// 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"
"sort"
"strings"
"time"
"github.com/dustin/go-humanize"
"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 adminBandwidthInfoCmdFlags = []cli.Flag{
cli.StringFlag{
Name: "unit",
Value: "b",
Usage: "[b|bi|B|Bi] Display bandwidth in bits (IEC [bi] or SI [b]) or bytes (IEC [Bi] or SI [B])",
},
}
var adminBwInfoCmd = cli.Command{
Name: "bandwidth",
Usage: "Show bandwidth info for buckets on the MinIO server in bits or bytes per second. Ki,Bi,Mi,Gi represent IEC units.",
Action: mainAdminBwInfo,
Before: setGlobalsFromContext,
OnUsageError: onUsageError,
Flags: append(globalFlags, adminBandwidthInfoCmdFlags...),
CustomHelpTemplate: `NAME:
{{.HelpName}} - {{.Usage}}
USAGE:
{{.HelpName}} FLAGS TARGET
FLAGS:
{{range .VisibleFlags}}{{.}}
{{end}}
EXAMPLES:
1. Show the bandwidth usage for all the buckets in a MinIO server setup
{{.Prompt}} {{.HelpName}} play/
2. Show the bandwidth usage for the bucket 'source-bucket' in a MinIO server setup
{{.Prompt}} {{.HelpName}} play/source-bucket
`,
}
func printTable(report madmin.Report, bits bool, iec bool) {
bucketMaxLength := 63
bucketColLength := 6
var bucketKeys []string
for bucket := range report.Report.BucketStats {
if len(bucket) <= bucketMaxLength && len(bucket) > bucketColLength {
bucketColLength = len(bucket)
}
bucketKeys = append(bucketKeys, bucket)
}
sort.Strings(bucketKeys)
dspOrder := []col{colGreen} // Header
for i := 0; i < len(report.Report.BucketStats); i++ {
dspOrder = append(dspOrder, colGrey)
}
var printColors []*color.Color
for _, c := range dspOrder {
printColors = append(printColors, getPrintCol(c))
}
cellText := make([][]string, len(report.Report.BucketStats)+1) // 1 for the header
tbl := console.NewTable(printColors, []bool{false, false, false}, 0)
bucketTitle := fmt.Sprintf("%-16v", "Bucket")
cellText[0] = []string{
bucketTitle,
"Configured Max Bandwidth",
"Current Bandwidth",
}
tbl.HeaderRowSeparator = true
index := 1
for _, bucket := range bucketKeys {
values := report.Report.BucketStats[bucket]
if len(bucket) > bucketMaxLength {
bucket = bucket[:bucketMaxLength] + ".."
}
var mul uint64
mul = 1
if bits {
mul = 8
}
limit := humanize.Bytes(uint64(values.LimitInBytesPerSecond) * mul)
current := humanize.Bytes(uint64(values.CurrentBandwidthInBytesPerSecond) * mul)
if iec {
limit = humanize.IBytes(uint64(values.LimitInBytesPerSecond)*mul) + "/sec"
current = humanize.IBytes(uint64(values.CurrentBandwidthInBytesPerSecond)*mul) + "/sec"
}
if bits {
limit = strings.ToLower(limit) + "/sec"
current = strings.ToLower(current) + "/sec"
}
if values.LimitInBytesPerSecond == 0 {
limit = "N/A" // N/A means cluster bandwidth is not configured
}
cellText[index] = []string{
bucket,
limit,
current,
}
index++
}
if len(report.Report.BucketStats) > 0 {
err := tbl.DisplayTable(cellText)
if err != nil {
console.Error(err)
}
}
}
func checkAdminBwInfoSyntax(ctx *cli.Context) {
u := ctx.String("unit")
if u != "bi" &&
u != "b" &&
u != "Bi" &&
u != "B" &&
u != "" {
showCommandHelpAndExit(ctx, globalErrorExitStatus)
}
if len(ctx.Args()) > 1 || len(ctx.Args()) == 0 {
showCommandHelpAndExit(ctx, globalErrorExitStatus)
}
}
func mainAdminBwInfo(ctx *cli.Context) {
checkAdminBwInfoSyntax(ctx)
aliasURL, bucket := getAliasAndBucket(ctx)
client := getClient(aliasURL)
reportCh := client.GetBucketBandwidth(globalContext, bucket)
firstPrint := true
bandwidthUnitsString := ctx.String("unit")
for {
select {
case report := <-reportCh:
if len(report.Report.BucketStats) == 0 {
continue
}
if report.Err != nil {
if strings.Contains(report.Err.Error(), "EOF") {
continue
}
console.Error(report.Err)
}
printBandwidth(report, firstPrint, bandwidthUnitsString == "bi" || bandwidthUnitsString == "b",
bandwidthUnitsString == "bi" || bandwidthUnitsString == "Bi")
firstPrint = false
case <-globalContext.Done():
return
}
}
}
func printBandwidth(report madmin.Report, firstPrint bool, bits bool, iec bool) {
rewindLines := len(report.Report.BucketStats) + 4
if firstPrint {
rewindLines = 0
}
if globalJSON {
reportJSON, e := json.MarshalIndent(report, "", " ")
fatalIf(probe.NewError(e), "Unable to marshal to JSON")
console.Println(string(reportJSON))
time.Sleep(1 * time.Second)
return
}
if len(report.Report.BucketStats) > 0 {
console.RewindLines(rewindLines)
// For the next iteration, rewind lines
printTable(report, bits, iec)
}
time.Sleep(1 * time.Second)
}