Skip to content

Commit

Permalink
Sort namespaces, mounts, and clients before adding them to HLL (#28062)
Browse files Browse the repository at this point in the history
* sort namespaces and mounts before adding them

* also sort clients

* add comments

* pr comment fixes

* changelog

* changelog update
  • Loading branch information
miagilepner authored Aug 13, 2024
1 parent cbc06c0 commit 8cd4263
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 3 deletions.
3 changes: 3 additions & 0 deletions changelog/28062.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
core/activity: Ensure client count queries that include the current month return consistent results by sorting the clients before performing estimation
```
58 changes: 55 additions & 3 deletions vault/activity_log_util_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"errors"
"fmt"
"io"
"slices"
"sort"
"strings"
"time"
Expand Down Expand Up @@ -156,20 +157,30 @@ func (a *ActivityLog) computeCurrentMonthForBillingPeriodInternal(ctx context.Co
return nil, errors.New("malformed current month used to calculate current month's activity")
}

for nsID, namespace := range month.Namespaces {
namespaces := month.Namespaces.sort()
for _, n := range namespaces {
nsID := n.id
namespace := n.processByNamespace
namespaceActivity := &activity.MonthlyNamespaceRecord{NamespaceID: nsID, Counts: &activity.CountsRecord{}}
newNamespaceActivity := &activity.MonthlyNamespaceRecord{NamespaceID: nsID, Counts: &activity.CountsRecord{}}
mountsActivity := make([]*activity.MountRecord, 0)
newMountsActivity := make([]*activity.MountRecord, 0)

for mountAccessor, mount := range namespace.Mounts {
mounts := namespace.Mounts.sort()
for _, m := range mounts {
mountAccessor := m.accessor
mount := m.processMount
mountPath := a.mountAccessorToMountPath(mountAccessor)

mountCounts := &activity.CountsRecord{}
newMountCounts := &activity.CountsRecord{}

for _, typ := range ActivityClientTypes {
for clientID := range mount.Counts.clientsByType(typ) {
clients := mount.Counts.clientsByType(typ)
clientIDs := clients.sort()

// sort the client IDs before inserting
for _, clientID := range clientIDs {
hllByType[typ].Insert([]byte(clientID))

// increment the per mount, per namespace, and total counts
Expand Down Expand Up @@ -241,6 +252,47 @@ func (a *ActivityLog) incrementCount(c *activity.CountsRecord, num int, typ stri
}
}

type processByNamespaceID struct {
id string
*processByNamespace
}

func (s summaryByNamespace) sort() []*processByNamespaceID {
namespaces := make([]*processByNamespaceID, 0, len(s))
for nsID, namespace := range s {
namespaces = append(namespaces, &processByNamespaceID{id: nsID, processByNamespace: namespace})
}
slices.SortStableFunc(namespaces, func(a, b *processByNamespaceID) int {
return strings.Compare(a.id, b.id)
})
return namespaces
}

type processMountAccessor struct {
accessor string
*processMount
}

func (s summaryByMount) sort() []*processMountAccessor {
mounts := make([]*processMountAccessor, 0, len(s))
for mountAccessor, mount := range s {
mounts = append(mounts, &processMountAccessor{accessor: mountAccessor, processMount: mount})
}
slices.SortStableFunc(mounts, func(a, b *processMountAccessor) int {
return strings.Compare(a.accessor, b.accessor)
})
return mounts
}

func (c clientIDSet) sort() []string {
clientIDs := make([]string, 0, len(c))
for clientID := range c {
clientIDs = append(clientIDs, clientID)
}
sort.Strings(clientIDs)
return clientIDs
}

// sortALResponseNamespaces sorts the namespaces for activity log responses.
func (a *ActivityLog) sortALResponseNamespaces(byNamespaceResponse []*ResponseNamespace) {
sort.Slice(byNamespaceResponse, func(i, j int) bool {
Expand Down

0 comments on commit 8cd4263

Please sign in to comment.