From b8de2c2b4e574c5fabde01c9be8c93c4e390c897 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Fri, 16 Dec 2022 16:02:42 -0800 Subject: [PATCH] De-duplicate namespaces when historical and current month data are mixed (#18452) * De-duplicate namespaces when historical and current month data are mixed * add changelog --- changelog/18452.txt | 3 +++ vault/activity_log.go | 23 +++++++++++++++++++++-- vault/logical_system_activity.go | 1 + 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 changelog/18452.txt diff --git a/changelog/18452.txt b/changelog/18452.txt new file mode 100644 index 000000000000..6d4566667ee4 --- /dev/null +++ b/changelog/18452.txt @@ -0,0 +1,3 @@ +```release-note:bug +core/activity: de-duplicate namespaces when historical and current month data are mixed +``` diff --git a/vault/activity_log.go b/vault/activity_log.go index 970cef996a9c..24df0213e2fc 100644 --- a/vault/activity_log.go +++ b/vault/activity_log.go @@ -1590,8 +1590,27 @@ func (a *ActivityLog) handleQuery(ctx context.Context, startTime, endTime time.T return nil, err } - // Add the current month's namespace data the precomputed query namespaces - byNamespaceResponse = append(byNamespaceResponse, byNamespaceResponseCurrent...) + // Create a mapping of namespace id to slice index, so that we can efficiently update our results without + // having to traverse the entire namespace response slice every time. + nsrMap := make(map[string]int) + for i, nr := range byNamespaceResponse { + nsrMap[nr.NamespaceID] = i + } + + // Rather than blindly appending, which will create duplicates, check our existing counts against the current + // month counts, and append or update as necessary. + for _, nrc := range byNamespaceResponseCurrent { + if ndx, ok := nsrMap[nrc.NamespaceID]; ok { + existingRecord := byNamespaceResponse[ndx] + existingRecord.Counts.EntityClients += nrc.Counts.EntityClients + existingRecord.Counts.Clients += nrc.Counts.Clients + existingRecord.Counts.DistinctEntities += nrc.Counts.DistinctEntities + existingRecord.Counts.NonEntityClients += nrc.Counts.NonEntityClients + existingRecord.Counts.NonEntityTokens += nrc.Counts.NonEntityTokens + } else { + byNamespaceResponse = append(byNamespaceResponse, nrc) + } + } } // Sort clients within each namespace diff --git a/vault/logical_system_activity.go b/vault/logical_system_activity.go index 7b8d67513e25..4d743379df3f 100644 --- a/vault/logical_system_activity.go +++ b/vault/logical_system_activity.go @@ -161,6 +161,7 @@ func parseStartEndTimes(a *ActivityLog, d *framework.FieldData) (time.Time, time return startTime, endTime, nil } +// This endpoint is not used by the UI. The UI's "export" feature is entirely client-side. func (b *SystemBackend) handleClientExport(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) { a := b.Core.activityLog if a == nil {