You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
toolkit/cmd/gcsinfo/main.go

125 lines
2.6 KiB

package main
import (
"container/heap"
"context"
"flag"
"fmt"
"log"
"math"
"os/signal"
"syscall"
"time"
"cloud.google.com/go/storage"
"google.golang.org/api/iterator"
)
var (
b = flag.String("bucket", "", "name of the bucket to use")
)
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM, syscall.SIGINT)
defer cancel()
flag.Parse()
client, err := storage.NewClient(ctx)
if err != nil {
log.Fatal(err)
}
bucket := client.Bucket(*b)
it := bucket.Objects(ctx, nil)
var totalSize int64
var minSize int64 = math.MaxInt64
var maxSize int64
sizes := &Int64Heap{}
var oldest time.Time
var youngest time.Time
heap.Init(sizes)
for {
objAttrs, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
log.Fatalf("Failed to iterate objects: %v", err)
}
// Add the size of each object to the total size
sizes.Push(objAttrs.Size)
totalSize += objAttrs.Size
minSize = min(minSize, objAttrs.Size)
maxSize = max(maxSize, objAttrs.Size)
if oldest.IsZero() || objAttrs.Created.Before(oldest) {
oldest = objAttrs.Created
}
if youngest.IsZero() || objAttrs.Created.After(youngest) {
youngest = objAttrs.Created
}
}
fmt.Printf("bucket: %s\n", *b)
fmt.Printf("total size: %s\n", toHumanBytes(totalSize))
fmt.Printf("min: %s\n", toHumanBytes(minSize))
fmt.Printf("max: %s\n", toHumanBytes(maxSize))
fmt.Printf("median: %s\n", toHumanBytes(sizes.At(sizes.Len()/2)))
fmt.Printf("mean: %s\n", toHumanBytes(totalSize/int64(sizes.Len())))
}
func min(a, b int64) int64 {
if a < b {
return a
}
return b
}
func max(a, b int64) int64 {
if a > b {
return a
}
return b
}
// An Int64Heap is a min-heap of ints.
type Int64Heap []int64
func (h Int64Heap) Len() int { return len(h) }
func (h Int64Heap) Less(i, j int) bool { return h[i] < h[j] }
func (h Int64Heap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h Int64Heap) At(i int) int64 { return h[i] }
func (h *Int64Heap) Push(x any) {
// Push and Pop use pointer receivers because they modify the slice's length,
// not just its contents.
*h = append(*h, x.(int64))
}
func (h *Int64Heap) Pop() any {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
var prefixes = []string{"b", "Kib", "Mib", "Gib", "Tib", "Pib"}
func toHumanBytes(i int64) string {
f := float64(i)
if f < 1024.0 {
return fmt.Sprintf("%4.2fb", f)
}
for i := 1; i < len(prefixes); i++ {
f /= 1024
if f < 1024.0 {
return fmt.Sprintf("%4.2f%s", f, prefixes[i])
}
}
return fmt.Sprintf("%4.2f%s", f, prefixes[len(prefixes)-1])
}