feat: add p50, p95 and p99 sections per tenant to stats (#19044)

pull/19053/head
George Robinson 8 months ago committed by GitHub
parent aa66baec97
commit d256df481e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      cmd/dataobj-inspect/stats.go
  2. 52
      pkg/dataobj/tools/stats.go

@ -54,10 +54,13 @@ func (cmd *statsCommand) printObjStats(ctx context.Context, obj *dataobj.Object)
bold := color.New(color.Bold)
bold.Println("Object:")
fmt.Printf(
"\tsize: %v, sections: %d, tenants: %d\n",
"\tsize: %v, sections: %d, tenants: %d, sections per tenant: p50: %.2f, p95: %.2f, p99: %.2f\n",
humanize.Bytes(stats.Size),
stats.Sections,
len(stats.Tenants),
stats.SectionsPerTenantStats.Median,
stats.SectionsPerTenantStats.P95,
stats.SectionsPerTenantStats.P99,
)
for offset, sec := range obj.Sections() {
switch {

@ -14,9 +14,17 @@ import (
)
type Stats struct {
Size uint64
Sections int
Tenants []string
Size uint64
Sections int
Tenants []string
TenantSections map[string]int
SectionsPerTenantStats
}
type SectionsPerTenantStats struct {
Median float64
P95 float64
P99 float64
}
// ReadStats returns statistics about the data object. ReadStats returns an
@ -25,6 +33,7 @@ type Stats struct {
func ReadStats(ctx context.Context, obj *dataobj.Object) (*Stats, error) {
s := Stats{}
s.Size = uint64(obj.Size())
s.TenantSections = make(map[string]int)
for _, sec := range obj.Sections() {
s.Sections++
switch {
@ -33,13 +42,17 @@ func ReadStats(ctx context.Context, obj *dataobj.Object) (*Stats, error) {
if err != nil {
return nil, err
}
s.Tenants = append(s.Tenants, streamsSec.Tenant())
tenant := streamsSec.Tenant()
s.Tenants = append(s.Tenants, tenant)
s.TenantSections[tenant]++
case logs.CheckSection(sec):
logsSec, err := logs.Open(ctx, sec)
if err != nil {
return nil, err
}
s.Tenants = append(s.Tenants, logsSec.Tenant())
tenant := logsSec.Tenant()
s.Tenants = append(s.Tenants, tenant)
s.TenantSections[tenant]++
default:
return nil, errors.New("unknown section type")
}
@ -47,5 +60,34 @@ func ReadStats(ctx context.Context, obj *dataobj.Object) (*Stats, error) {
// A tenant can have multiple sections, so we must deduplicate them.
slices.Sort(s.Tenants)
s.Tenants = slices.Compact(s.Tenants)
calculateSectionsPerTenantStats(&s)
return &s, nil
}
func calculateSectionsPerTenantStats(s *Stats) {
if len(s.TenantSections) == 0 {
return
}
counts := make([]int, 0, len(s.TenantSections))
for _, n := range s.TenantSections {
counts = append(counts, n)
}
// Data must be sorted to calculate percentiles.
slices.Sort(counts)
n := len(counts)
if n%2 == 0 {
s.SectionsPerTenantStats.Median = float64(counts[n/2-1]+counts[n/2]) / 2.0
} else {
s.SectionsPerTenantStats.Median = float64(counts[n/2])
}
idx := int(float64(n) * 0.95)
if idx >= n {
idx = n - 1
}
s.SectionsPerTenantStats.P95 = float64(counts[idx])
idx = int(float64(n) * 0.99)
if idx >= n {
idx = n - 1
}
s.SectionsPerTenantStats.P99 = float64(counts[idx])
}

Loading…
Cancel
Save