consul/command/snapshot/inspect/formatter.go

131 lines
3.0 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package inspect
import (
"bytes"
"encoding/json"
"fmt"
"strconv"
"strings"
"text/tabwriter"
)
const (
PrettyFormat string = "pretty"
JSONFormat string = "json"
)
type Formatter interface {
Format(*OutputFormat) (string, error)
}
func GetSupportedFormats() []string {
return []string{PrettyFormat, JSONFormat}
}
type prettyFormatter struct{}
func newPrettyFormatter() Formatter {
return &prettyFormatter{}
}
func NewFormatter(format string) (Formatter, error) {
switch format {
case PrettyFormat:
return newPrettyFormatter(), nil
case JSONFormat:
return newJSONFormatter(), nil
default:
return nil, fmt.Errorf("Unknown format: %s", format)
}
}
func (_ *prettyFormatter) Format(info *OutputFormat) (string, error) {
var b bytes.Buffer
tw := tabwriter.NewWriter(&b, 8, 8, 6, ' ', 0)
fmt.Fprintf(tw, " ID\t%s", info.Meta.ID)
fmt.Fprintf(tw, "\n Size\t%d", info.Meta.Size)
fmt.Fprintf(tw, "\n Index\t%d", info.Meta.Index)
fmt.Fprintf(tw, "\n Term\t%d", info.Meta.Term)
fmt.Fprintf(tw, "\n Version\t%d", info.Meta.Version)
fmt.Fprintf(tw, "\n")
fmt.Fprintln(tw, "\n Type\tCount\tSize")
fmt.Fprintf(tw, " %s\t%s\t%s", "----", "----", "----")
// For each different type generate new output
for _, s := range info.Stats {
fmt.Fprintf(tw, "\n %s\t%d\t%s", s.Name, s.Count, ByteSize(uint64(s.Sum)))
}
fmt.Fprintf(tw, "\n %s\t%s\t%s", "----", "----", "----")
fmt.Fprintf(tw, "\n Total\t\t%s", ByteSize(uint64(info.TotalSize)))
if info.StatsKV != nil {
fmt.Fprintf(tw, "\n")
fmt.Fprintln(tw, "\n Key Name\tCount\tSize")
fmt.Fprintf(tw, " %s\t%s\t%s", "----", "----", "----")
// For each different type generate new output
for _, s := range info.StatsKV {
fmt.Fprintf(tw, "\n %s\t%d\t%s", s.Name, s.Count, ByteSize(uint64(s.Sum)))
}
fmt.Fprintf(tw, "\n %s\t%s\t%s", "----", "----", "----")
fmt.Fprintf(tw, "\n Total\t\t%s", ByteSize(uint64(info.TotalSizeKV)))
}
if err := tw.Flush(); err != nil {
return b.String(), err
}
return b.String(), nil
}
type jsonFormatter struct{}
func newJSONFormatter() Formatter {
return &jsonFormatter{}
}
func (_ *jsonFormatter) Format(info *OutputFormat) (string, error) {
b, err := json.MarshalIndent(info, "", " ")
if err != nil {
return "", fmt.Errorf("Failed to marshal original snapshot stats: %v", err)
}
return string(b), nil
}
const (
BYTE = 1 << (10 * iota)
KILOBYTE
MEGABYTE
GIGABYTE
TERABYTE
)
func ByteSize(bytes uint64) string {
unit := ""
value := float64(bytes)
switch {
case bytes >= TERABYTE:
unit = "TB"
value = value / TERABYTE
case bytes >= GIGABYTE:
unit = "GB"
value = value / GIGABYTE
case bytes >= MEGABYTE:
unit = "MB"
value = value / MEGABYTE
case bytes >= KILOBYTE:
unit = "KB"
value = value / KILOBYTE
case bytes >= BYTE:
unit = "B"
case bytes == 0:
return "0"
}
result := strconv.FormatFloat(value, 'f', 1, 64)
result = strings.TrimSuffix(result, ".0")
return result + unit
}