Print number of bytes added to the repo

This includes optional compression and crypto overhead.
This commit is contained in:
Alexander Neumann 2022-05-01 14:41:36 +02:00 committed by Michael Eischer
parent 99634c0936
commit 6c4ceaf1e7
6 changed files with 65 additions and 44 deletions

View file

@ -31,18 +31,22 @@ type ErrorFunc func(file string, fi os.FileInfo, err error) error
// ItemStats collects some statistics about a particular file or directory. // ItemStats collects some statistics about a particular file or directory.
type ItemStats struct { type ItemStats struct {
DataBlobs int // number of new data blobs added for this item DataBlobs int // number of new data blobs added for this item
DataSize uint64 // sum of the sizes of all new data blobs DataSize uint64 // sum of the sizes of all new data blobs
TreeBlobs int // number of new tree blobs added for this item DataSizeInRepo uint64 // sum of the bytes added to the repo (including compression and crypto overhead)
TreeSize uint64 // sum of the sizes of all new tree blobs TreeBlobs int // number of new tree blobs added for this item
TreeSize uint64 // sum of the sizes of all new tree blobs
TreeSizeInRepo uint64 // sum of the bytes added to the repo (including compression and crypto overhead)
} }
// Add adds other to the current ItemStats. // Add adds other to the current ItemStats.
func (s *ItemStats) Add(other ItemStats) { func (s *ItemStats) Add(other ItemStats) {
s.DataBlobs += other.DataBlobs s.DataBlobs += other.DataBlobs
s.DataSize += other.DataSize s.DataSize += other.DataSize
s.DataSizeInRepo += other.DataSizeInRepo
s.TreeBlobs += other.TreeBlobs s.TreeBlobs += other.TreeBlobs
s.TreeSize += other.TreeSize s.TreeSize += other.TreeSize
s.TreeSizeInRepo += other.TreeSizeInRepo
} }
// Archiver saves a directory structure to the repo. // Archiver saves a directory structure to the repo.
@ -183,7 +187,8 @@ func (arch *Archiver) saveTree(ctx context.Context, t *restic.Tree) (restic.ID,
res.Wait(ctx) res.Wait(ctx)
if !res.Known() { if !res.Known() {
s.TreeBlobs++ s.TreeBlobs++
s.TreeSize += uint64(len(buf)) s.TreeSize += uint64(res.Length())
s.TreeSizeInRepo += uint64(res.SizeInRepo())
} }
// The context was canceled in the meantime, res.ID() might be invalid // The context was canceled in the meantime, res.ID() might be invalid
if ctx.Err() != nil { if ctx.Err() != nil {

View file

@ -1019,7 +1019,7 @@ func TestArchiverSaveTree(t *testing.T) {
want: TestDir{ want: TestDir{
"targetfile": TestFile{Content: string("foobar")}, "targetfile": TestFile{Content: string("foobar")},
}, },
stat: ItemStats{1, 6, 0, 0}, stat: ItemStats{1, 6, 32 + 6, 0, 0, 0},
}, },
{ {
src: TestDir{ src: TestDir{
@ -1031,7 +1031,7 @@ func TestArchiverSaveTree(t *testing.T) {
"targetfile": TestFile{Content: string("foobar")}, "targetfile": TestFile{Content: string("foobar")},
"filesymlink": TestSymlink{Target: "targetfile"}, "filesymlink": TestSymlink{Target: "targetfile"},
}, },
stat: ItemStats{1, 6, 0, 0}, stat: ItemStats{1, 6, 32 + 6, 0, 0, 0},
}, },
{ {
src: TestDir{ src: TestDir{
@ -1051,7 +1051,7 @@ func TestArchiverSaveTree(t *testing.T) {
"symlink": TestSymlink{Target: "subdir"}, "symlink": TestSymlink{Target: "subdir"},
}, },
}, },
stat: ItemStats{0, 0, 1, 0x154}, stat: ItemStats{0, 0, 0, 1, 0x154, 0x16a},
}, },
{ {
src: TestDir{ src: TestDir{
@ -1075,7 +1075,7 @@ func TestArchiverSaveTree(t *testing.T) {
}, },
}, },
}, },
stat: ItemStats{1, 6, 3, 0x47f}, stat: ItemStats{1, 6, 32 + 6, 3, 0x47f, 0x4c1},
}, },
} }
@ -1140,7 +1140,8 @@ func TestArchiverSaveTree(t *testing.T) {
bothZeroOrNeither(t, uint64(test.stat.DataBlobs), uint64(stat.DataBlobs)) bothZeroOrNeither(t, uint64(test.stat.DataBlobs), uint64(stat.DataBlobs))
bothZeroOrNeither(t, uint64(test.stat.TreeBlobs), uint64(stat.TreeBlobs)) bothZeroOrNeither(t, uint64(test.stat.TreeBlobs), uint64(stat.TreeBlobs))
bothZeroOrNeither(t, test.stat.DataSize, stat.DataSize) bothZeroOrNeither(t, test.stat.DataSize, stat.DataSize)
bothZeroOrNeither(t, test.stat.TreeSize, stat.TreeSize) bothZeroOrNeither(t, test.stat.DataSizeInRepo, stat.DataSizeInRepo)
bothZeroOrNeither(t, test.stat.TreeSizeInRepo, stat.TreeSizeInRepo)
}) })
} }
} }

View file

@ -86,11 +86,17 @@ func (s *FutureBlob) Known() bool {
return s.res.known return s.res.known
} }
// Length returns the length of the blob. // Length returns the raw length of the blob.
func (s *FutureBlob) Length() int { func (s *FutureBlob) Length() int {
return s.length return s.length
} }
// SizeInRepo returns the number of bytes added to the repo (including
// compression and crypto overhead).
func (s *FutureBlob) SizeInRepo() int {
return s.res.size
}
type saveBlobJob struct { type saveBlobJob struct {
restic.BlobType restic.BlobType
buf *Buffer buf *Buffer

View file

@ -210,6 +210,7 @@ func (s *FileSaver) saveFile(ctx context.Context, chnker *chunker.Chunker, snPat
if !res.Known() { if !res.Known() {
stats.DataBlobs++ stats.DataBlobs++
stats.DataSize += uint64(res.Length()) stats.DataSize += uint64(res.Length())
stats.DataSizeInRepo += uint64(res.SizeInRepo())
} }
node.Content = append(node.Content, res.ID()) node.Content = append(node.Content, res.ID())

View file

@ -110,12 +110,14 @@ func (b *JSONProgress) CompleteItem(messageType, item string, previous, current
switch messageType { switch messageType {
case "dir new": case "dir new":
b.print(verboseUpdate{ b.print(verboseUpdate{
MessageType: "verbose_status", MessageType: "verbose_status",
Action: "new", Action: "new",
Item: item, Item: item,
Duration: d.Seconds(), Duration: d.Seconds(),
DataSize: s.DataSize, DataSize: s.DataSize,
MetadataSize: s.TreeSize, DataSizeInRepo: s.DataSizeInRepo,
MetadataSize: s.TreeSize,
MetadataSizeInRepo: s.TreeSizeInRepo,
}) })
case "dir unchanged": case "dir unchanged":
b.print(verboseUpdate{ b.print(verboseUpdate{
@ -125,20 +127,23 @@ func (b *JSONProgress) CompleteItem(messageType, item string, previous, current
}) })
case "dir modified": case "dir modified":
b.print(verboseUpdate{ b.print(verboseUpdate{
MessageType: "verbose_status", MessageType: "verbose_status",
Action: "modified", Action: "modified",
Item: item, Item: item,
Duration: d.Seconds(), Duration: d.Seconds(),
DataSize: s.DataSize, DataSize: s.DataSize,
MetadataSize: s.TreeSize, DataSizeInRepo: s.DataSizeInRepo,
MetadataSize: s.TreeSize,
MetadataSizeInRepo: s.TreeSizeInRepo,
}) })
case "file new": case "file new":
b.print(verboseUpdate{ b.print(verboseUpdate{
MessageType: "verbose_status", MessageType: "verbose_status",
Action: "new", Action: "new",
Item: item, Item: item,
Duration: d.Seconds(), Duration: d.Seconds(),
DataSize: s.DataSize, DataSize: s.DataSize,
DataSizeInRepo: s.DataSizeInRepo,
}) })
case "file unchanged": case "file unchanged":
b.print(verboseUpdate{ b.print(verboseUpdate{
@ -148,11 +153,12 @@ func (b *JSONProgress) CompleteItem(messageType, item string, previous, current
}) })
case "file modified": case "file modified":
b.print(verboseUpdate{ b.print(verboseUpdate{
MessageType: "verbose_status", MessageType: "verbose_status",
Action: "modified", Action: "modified",
Item: item, Item: item,
Duration: d.Seconds(), Duration: d.Seconds(),
DataSize: s.DataSize, DataSize: s.DataSize,
DataSizeInRepo: s.DataSizeInRepo,
}) })
} }
} }
@ -216,13 +222,15 @@ type errorUpdate struct {
} }
type verboseUpdate struct { type verboseUpdate struct {
MessageType string `json:"message_type"` // "verbose_status" MessageType string `json:"message_type"` // "verbose_status"
Action string `json:"action"` Action string `json:"action"`
Item string `json:"item"` Item string `json:"item"`
Duration float64 `json:"duration"` // in seconds Duration float64 `json:"duration"` // in seconds
DataSize uint64 `json:"data_size"` DataSize uint64 `json:"data_size"`
MetadataSize uint64 `json:"metadata_size"` DataSizeInRepo uint64 `json:"data_size_in_repo"`
TotalFiles uint `json:"total_files"` MetadataSize uint64 `json:"metadata_size"`
MetadataSizeInRepo uint64 `json:"metadata_size_in_repo"`
TotalFiles uint `json:"total_files"`
} }
type summaryOutput struct { type summaryOutput struct {

View file

@ -138,17 +138,17 @@ func formatBytes(c uint64) string {
func (b *TextProgress) CompleteItem(messageType, item string, previous, current *restic.Node, s archiver.ItemStats, d time.Duration) { func (b *TextProgress) CompleteItem(messageType, item string, previous, current *restic.Node, s archiver.ItemStats, d time.Duration) {
switch messageType { switch messageType {
case "dir new": case "dir new":
b.VV("new %v, saved in %.3fs (%v added, %v metadata)", item, d.Seconds(), formatBytes(s.DataSize), formatBytes(s.TreeSize)) b.VV("new %v, saved in %.3fs (%v added, %v stored, %v metadata)", item, d.Seconds(), formatBytes(s.DataSize), formatBytes(s.DataSizeInRepo), formatBytes(s.TreeSizeInRepo))
case "dir unchanged": case "dir unchanged":
b.VV("unchanged %v", item) b.VV("unchanged %v", item)
case "dir modified": case "dir modified":
b.VV("modified %v, saved in %.3fs (%v added, %v metadata)", item, d.Seconds(), formatBytes(s.DataSize), formatBytes(s.TreeSize)) b.VV("modified %v, saved in %.3fs (%v added, %v stored, %v metadata)", item, d.Seconds(), formatBytes(s.DataSize), formatBytes(s.DataSizeInRepo), formatBytes(s.TreeSizeInRepo))
case "file new": case "file new":
b.VV("new %v, saved in %.3fs (%v added)", item, d.Seconds(), formatBytes(s.DataSize)) b.VV("new %v, saved in %.3fs (%v added)", item, d.Seconds(), formatBytes(s.DataSize))
case "file unchanged": case "file unchanged":
b.VV("unchanged %v", item) b.VV("unchanged %v", item)
case "file modified": case "file modified":
b.VV("modified %v, saved in %.3fs (%v added)", item, d.Seconds(), formatBytes(s.DataSize)) b.VV("modified %v, saved in %.3fs (%v added, %v stored)", item, d.Seconds(), formatBytes(s.DataSize), formatBytes(s.DataSizeInRepo))
} }
} }
@ -178,7 +178,7 @@ func (b *TextProgress) Finish(snapshotID restic.ID, start time.Time, summary *Su
if dryRun { if dryRun {
verb = "Would add" verb = "Would add"
} }
b.P("%s to the repo: %-5s\n", verb, formatBytes(summary.ItemStats.DataSize+summary.ItemStats.TreeSize)) b.P("%s to the repo: %-5s (%-5s stored)\n", verb, formatBytes(summary.ItemStats.DataSize+summary.ItemStats.TreeSize), formatBytes(summary.ItemStats.DataSizeInRepo+summary.ItemStats.TreeSizeInRepo))
b.P("\n") b.P("\n")
b.P("processed %v files, %v in %s", b.P("processed %v files, %v in %s",
summary.Files.New+summary.Files.Changed+summary.Files.Unchanged, summary.Files.New+summary.Files.Changed+summary.Files.Unchanged,