cli: Add JSON and Pretty Print formatting for `consul snapshot inspect` (#9006)
This commit is contained in:
parent
1b0efbfd27
commit
ee3eb03f50
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:feature
|
||||||
|
cli: snapshot inspect command supports JSON output
|
||||||
|
```
|
|
@ -0,0 +1,114 @@
|
||||||
|
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\t")
|
||||||
|
fmt.Fprintf(tw, " %s\t%s\t%s\t", "----", "----", "----")
|
||||||
|
// For each different type generate new output
|
||||||
|
for _, s := range info.Stats {
|
||||||
|
fmt.Fprintf(tw, "\n %s\t%d\t%s\t", s.Name, s.Count, ByteSize(uint64(s.Sum)))
|
||||||
|
}
|
||||||
|
fmt.Fprintf(tw, "\n %s\t%s\t%s\t", "----", "----", "----")
|
||||||
|
fmt.Fprintf(tw, "\n Total\t\t%s\t", ByteSize(uint64(info.TotalSize)))
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package inspect
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFormat(t *testing.T) {
|
||||||
|
m := []typeStats{{
|
||||||
|
Name: "msg",
|
||||||
|
Sum: 1,
|
||||||
|
Count: 2,
|
||||||
|
}}
|
||||||
|
info := OutputFormat{
|
||||||
|
Meta: &MetadataInfo{
|
||||||
|
ID: "one",
|
||||||
|
Size: 2,
|
||||||
|
Index: 3,
|
||||||
|
Term: 4,
|
||||||
|
Version: 1,
|
||||||
|
},
|
||||||
|
Stats: m,
|
||||||
|
TotalSize: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
formatters := map[string]Formatter{
|
||||||
|
"pretty": newPrettyFormatter(),
|
||||||
|
// the JSON formatter ignores the showMeta
|
||||||
|
"json": newJSONFormatter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for fmtName, formatter := range formatters {
|
||||||
|
t.Run(fmtName, func(t *testing.T) {
|
||||||
|
actual, err := formatter.Format(&info)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
gName := fmt.Sprintf("%s", fmtName)
|
||||||
|
|
||||||
|
expected := golden(t, gName, actual)
|
||||||
|
require.Equal(t, expected, actual)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,12 @@
|
||||||
package inspect
|
package inspect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent/consul/fsm"
|
"github.com/hashicorp/consul/agent/consul/fsm"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
@ -28,16 +25,41 @@ func New(ui cli.Ui) *cmd {
|
||||||
}
|
}
|
||||||
|
|
||||||
type cmd struct {
|
type cmd struct {
|
||||||
UI cli.Ui
|
UI cli.Ui
|
||||||
flags *flag.FlagSet
|
flags *flag.FlagSet
|
||||||
help string
|
help string
|
||||||
|
format string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cmd) init() {
|
func (c *cmd) init() {
|
||||||
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
|
c.flags = flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
c.flags.StringVar(
|
||||||
|
&c.format,
|
||||||
|
"format",
|
||||||
|
PrettyFormat,
|
||||||
|
fmt.Sprintf("Output format {%s}", strings.Join(GetSupportedFormats(), "|")))
|
||||||
|
|
||||||
c.help = flags.Usage(help, c.flags)
|
c.help = flags.Usage(help, c.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MetadataInfo is used for passing information
|
||||||
|
// through the formatter
|
||||||
|
type MetadataInfo struct {
|
||||||
|
ID string
|
||||||
|
Size int64
|
||||||
|
Index uint64
|
||||||
|
Term uint64
|
||||||
|
Version raft.SnapshotVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutputFormat is used for passing information
|
||||||
|
// through the formatter
|
||||||
|
type OutputFormat struct {
|
||||||
|
Meta *MetadataInfo
|
||||||
|
Stats []typeStats
|
||||||
|
TotalSize int
|
||||||
|
}
|
||||||
|
|
||||||
func (c *cmd) Run(args []string) int {
|
func (c *cmd) Run(args []string) int {
|
||||||
if err := c.flags.Parse(args); err != nil {
|
if err := c.flags.Parse(args); err != nil {
|
||||||
c.UI.Error(err.Error())
|
c.UI.Error(err.Error())
|
||||||
|
@ -84,38 +106,37 @@ func (c *cmd) Run(args []string) int {
|
||||||
c.UI.Error(fmt.Sprintf("Error extracting snapshot data: %s", err))
|
c.UI.Error(fmt.Sprintf("Error extracting snapshot data: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
// Outputs the original style of inspect information
|
|
||||||
legacy, err := c.legacyStats(meta)
|
|
||||||
if err != nil {
|
|
||||||
c.UI.Error(fmt.Sprintf("Error outputting snapshot data: %s", err))
|
|
||||||
}
|
|
||||||
c.UI.Info(legacy.String())
|
|
||||||
|
|
||||||
// Outputs the more detailed snapshot information
|
formatter, err := NewFormatter(c.format)
|
||||||
enhanced, err := c.readStats(stats, totalSize)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.UI.Error(fmt.Sprintf("Error outputting enhanced snapshot data: %s", err))
|
c.UI.Error(fmt.Sprintf("Error outputting enhanced snapshot data: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
c.UI.Info(enhanced.String())
|
//Generate structs for the formatter with information we read in
|
||||||
|
metaformat := &MetadataInfo{
|
||||||
return 0
|
ID: meta.ID,
|
||||||
}
|
Size: meta.Size,
|
||||||
|
Index: meta.Index,
|
||||||
// legacyStats outputs the expected stats from the original snapshot
|
Term: meta.Term,
|
||||||
// inspect command
|
Version: meta.Version,
|
||||||
func (c *cmd) legacyStats(meta *raft.SnapshotMeta) (bytes.Buffer, error) {
|
|
||||||
var b bytes.Buffer
|
|
||||||
tw := tabwriter.NewWriter(&b, 0, 2, 6, ' ', 0)
|
|
||||||
fmt.Fprintf(tw, "ID\t%s\n", meta.ID)
|
|
||||||
fmt.Fprintf(tw, "Size\t%d\n", meta.Size)
|
|
||||||
fmt.Fprintf(tw, "Index\t%d\n", meta.Index)
|
|
||||||
fmt.Fprintf(tw, "Term\t%d\n", meta.Term)
|
|
||||||
fmt.Fprintf(tw, "Version\t%d\n", meta.Version)
|
|
||||||
if err := tw.Flush(); err != nil {
|
|
||||||
return b, err
|
|
||||||
}
|
}
|
||||||
return b, nil
|
|
||||||
|
//Restructures stats given above to be human readable
|
||||||
|
formattedStats := generatetypeStats(stats)
|
||||||
|
|
||||||
|
in := &OutputFormat{
|
||||||
|
Meta: metaformat,
|
||||||
|
Stats: formattedStats,
|
||||||
|
TotalSize: totalSize,
|
||||||
|
}
|
||||||
|
out, err := formatter.Format(in)
|
||||||
|
if err != nil {
|
||||||
|
c.UI.Error(err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
c.UI.Output(out)
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type typeStats struct {
|
type typeStats struct {
|
||||||
|
@ -124,6 +145,19 @@ type typeStats struct {
|
||||||
Count int
|
Count int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generatetypeStats(info map[structs.MessageType]typeStats) []typeStats {
|
||||||
|
ss := make([]typeStats, 0, len(info))
|
||||||
|
|
||||||
|
for _, s := range info {
|
||||||
|
ss = append(ss, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the stat slice
|
||||||
|
sort.Slice(ss, func(i, j int) bool { return ss[i].Sum > ss[j].Sum })
|
||||||
|
|
||||||
|
return ss
|
||||||
|
}
|
||||||
|
|
||||||
// countingReader helps keep track of the bytes we have read
|
// countingReader helps keep track of the bytes we have read
|
||||||
// when reading snapshots
|
// when reading snapshots
|
||||||
type countingReader struct {
|
type countingReader struct {
|
||||||
|
@ -171,85 +205,6 @@ func enhance(file io.Reader) (map[structs.MessageType]typeStats, int, error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// readStats takes the information generated from enhance and creates human
|
|
||||||
// readable output from it
|
|
||||||
func (c *cmd) readStats(stats map[structs.MessageType]typeStats, totalSize int) (bytes.Buffer, error) {
|
|
||||||
// Output stats in size-order
|
|
||||||
ss := make([]typeStats, 0, len(stats))
|
|
||||||
|
|
||||||
for _, s := range stats {
|
|
||||||
ss = append(ss, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort the stat slice
|
|
||||||
sort.Slice(ss, func(i, j int) bool { return ss[i].Sum > ss[j].Sum })
|
|
||||||
|
|
||||||
var b bytes.Buffer
|
|
||||||
|
|
||||||
tw := tabwriter.NewWriter(&b, 8, 8, 6, ' ', 0)
|
|
||||||
fmt.Fprintln(tw, "\n Type\tCount\tSize\t")
|
|
||||||
fmt.Fprintf(tw, " %s\t%s\t%s\t", "----", "----", "----")
|
|
||||||
// For each different type generate new output
|
|
||||||
for _, s := range ss {
|
|
||||||
fmt.Fprintf(tw, "\n %s\t%d\t%s\t", s.Name, s.Count, ByteSize(uint64(s.Sum)))
|
|
||||||
}
|
|
||||||
fmt.Fprintf(tw, "\n %s\t%s\t%s\t", "----", "----", "----")
|
|
||||||
fmt.Fprintf(tw, "\n Total\t\t%s\t", ByteSize(uint64(totalSize)))
|
|
||||||
|
|
||||||
if err := tw.Flush(); err != nil {
|
|
||||||
c.UI.Error(fmt.Sprintf("Error rendering snapshot info: %s", err))
|
|
||||||
return b, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return b, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// ByteSize returns a human-readable byte string of the form 10MB, 12.5KB, and so forth. The following units are available:
|
|
||||||
// TB: Terabyte
|
|
||||||
// GB: Gigabyte
|
|
||||||
// MB: Megabyte
|
|
||||||
// KB: Kilobyte
|
|
||||||
// B: Byte
|
|
||||||
// The unit that results in the smallest number greater than or equal to 1 is always chosen.
|
|
||||||
// From https://github.com/cloudfoundry/bytefmt/blob/master/bytes.go
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cmd) Synopsis() string {
|
func (c *cmd) Synopsis() string {
|
||||||
return synopsis
|
return synopsis
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
ID 2-13-1602222343947
|
ID 2-13-1602222343947
|
||||||
Size 5141
|
Size 5141
|
||||||
Index 13
|
Index 13
|
||||||
Term 2
|
Term 2
|
||||||
Version 1
|
Version 1
|
||||||
|
|
||||||
|
|
||||||
Type Count Size
|
Type Count Size
|
||||||
---- ---- ----
|
---- ---- ----
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
ID 2-12-1603319127176
|
||||||
|
Size 5133
|
||||||
|
Index 12
|
||||||
|
Term 2
|
||||||
|
Version 1
|
||||||
|
|
||||||
|
Type Count Size
|
||||||
|
---- ---- ----
|
||||||
|
Register 3 1.8KB
|
||||||
|
ConnectCA 1 1.2KB
|
||||||
|
ConnectCAProviderState 1 1.1KB
|
||||||
|
Index 11 313B
|
||||||
|
ConnectCAConfig 1 247B
|
||||||
|
Autopilot 1 199B
|
||||||
|
SystemMetadata 1 68B
|
||||||
|
ChunkingState 1 12B
|
||||||
|
---- ---- ----
|
||||||
|
Total 5KB
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"Meta": {
|
||||||
|
"ID": "one",
|
||||||
|
"Size": 2,
|
||||||
|
"Index": 3,
|
||||||
|
"Term": 4,
|
||||||
|
"Version": 1
|
||||||
|
},
|
||||||
|
"Stats": [
|
||||||
|
{
|
||||||
|
"Name": "msg",
|
||||||
|
"Sum": 1,
|
||||||
|
"Count": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"TotalSize": 1
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
ID one
|
||||||
|
Size 2
|
||||||
|
Index 3
|
||||||
|
Term 4
|
||||||
|
Version 1
|
||||||
|
|
||||||
|
Type Count Size
|
||||||
|
---- ---- ----
|
||||||
|
msg 2 1B
|
||||||
|
---- ---- ----
|
||||||
|
Total 1B
|
|
@ -26,6 +26,8 @@ The following fields are displayed when inspecting a snapshot:
|
||||||
- `Version` - The snapshot format version. This only refers to the structure of
|
- `Version` - The snapshot format version. This only refers to the structure of
|
||||||
the snapshot, not the data contained within.
|
the snapshot, not the data contained within.
|
||||||
|
|
||||||
|
- Each data type, size, and count within the read snapshot.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Usage: `consul snapshot inspect [options] FILE`
|
Usage: `consul snapshot inspect [options] FILE`
|
||||||
|
@ -36,11 +38,11 @@ To inspect a snapshot from the file "backup.snap":
|
||||||
|
|
||||||
```shell-session
|
```shell-session
|
||||||
$ consul snapshot inspect backup.snap
|
$ consul snapshot inspect backup.snap
|
||||||
ID 2-5-1477944140022
|
ID 2-13-1603221729747
|
||||||
Size 667
|
Size 5141
|
||||||
Index 5
|
Index 13
|
||||||
Term 2
|
Term 2
|
||||||
Version 1
|
Version 1
|
||||||
|
|
||||||
Type Count Size
|
Type Count Size
|
||||||
---- ---- ----
|
---- ---- ----
|
||||||
|
@ -48,14 +50,80 @@ Version 1
|
||||||
ConnectCA 1 1.2KB
|
ConnectCA 1 1.2KB
|
||||||
ConnectCAProviderState 1 1.1KB
|
ConnectCAProviderState 1 1.1KB
|
||||||
Index 12 344B
|
Index 12 344B
|
||||||
AutopilotRequest 1 199B
|
Autopilot 1 199B
|
||||||
ConnectCAConfig 1 197B
|
ConnectCAConfig 1 197B
|
||||||
FederationState 1 139B
|
FederationState 1 139B
|
||||||
SystemMetadata 1 68B
|
SystemMetadata 1 68B
|
||||||
ChunkingState 1 12B
|
ChunkingState 1 12B
|
||||||
---- ---- ----
|
---- ---- ----
|
||||||
Total 5KB
|
Total 5KB
|
||||||
|
```
|
||||||
|
|
||||||
|
To enhance a snapshot inespection from "backup.snap":
|
||||||
|
```shell-session
|
||||||
|
$ consul snapshot inspect -format=json backup.snap
|
||||||
|
{
|
||||||
|
"Meta": {
|
||||||
|
"ID": "2-13-1603221729747",
|
||||||
|
"Size": 5141,
|
||||||
|
"Index": 13,
|
||||||
|
"Term": 2,
|
||||||
|
"Version": 1
|
||||||
|
},
|
||||||
|
"Stats": [
|
||||||
|
{
|
||||||
|
"Name": "Register",
|
||||||
|
"Sum": 1750,
|
||||||
|
"Count": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "ConnectCA",
|
||||||
|
"Sum": 1258,
|
||||||
|
"Count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "ConnectCAProviderState",
|
||||||
|
"Sum": 1174,
|
||||||
|
"Count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Index",
|
||||||
|
"Sum": 344,
|
||||||
|
"Count": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "Autopilot",
|
||||||
|
"Sum": 199,
|
||||||
|
"Count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "ConnectCAConfig",
|
||||||
|
"Sum": 197,
|
||||||
|
"Count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "FederationState",
|
||||||
|
"Sum": 139,
|
||||||
|
"Count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "SystemMetadata",
|
||||||
|
"Sum": 68,
|
||||||
|
"Count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "ChunkingState",
|
||||||
|
"Sum": 12,
|
||||||
|
"Count": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"TotalSize": 5141
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Please see the [HTTP API](/api/snapshot) documentation for
|
Please see the [HTTP API](/api/snapshot) documentation for
|
||||||
more details about snapshot internals.
|
more details about snapshot internals.
|
||||||
|
|
||||||
|
#### Command Options
|
||||||
|
|
||||||
|
- `-format` - Optional, allows from changing the output to JSON. Parameters accepted are "pretty" and "JSON".
|
||||||
|
|
Loading…
Reference in New Issue