diff --git a/changelog/19625.txt b/changelog/19625.txt new file mode 100644 index 000000000000..b0cb558e3cd1 --- /dev/null +++ b/changelog/19625.txt @@ -0,0 +1,4 @@ +```release-note:feature +core (enterprise): Add background worker for automatic reporting of billing +information. +``` diff --git a/vault/activity_log.go b/vault/activity_log.go index 965d34a662f3..d45525f2f21a 100644 --- a/vault/activity_log.go +++ b/vault/activity_log.go @@ -171,6 +171,14 @@ type ActivityLog struct { partialMonthClientTracker map[string]*activity.EntityRecord inprocessExport *atomic.Bool + + // CensusReportDone is a channel used to signal tests upon successful calls + // to (CensusReporter).Write() in CensusReport. + CensusReportDone chan bool + + // CensusReportInterval is the testing configuration for time between + // Write() calls initiated in CensusReport. + CensusReportInterval time.Duration } // These non-persistent configuration options allow us to disable @@ -182,6 +190,9 @@ type ActivityLogCoreConfig struct { // Do not start timers to send or persist fragments. DisableTimers bool + + // CensusReportInterval is the testing configuration for time + CensusReportInterval time.Duration } // NewActivityLog creates an activity log. @@ -203,6 +214,7 @@ func NewActivityLog(core *Core, logger log.Logger, view *BarrierView, metrics me writeCh: make(chan struct{}, 1), // same for full segment doneCh: make(chan struct{}, 1), partialMonthClientTracker: make(map[string]*activity.EntityRecord), + CensusReportInterval: time.Hour * 1, currentSegment: segmentInfo{ startTimestamp: 0, @@ -940,6 +952,10 @@ func (a *ActivityLog) SetConfigInit(config activityConfig) { a.defaultReportMonths = config.DefaultReportMonths a.retentionMonths = config.RetentionMonths + + if a.configOverrides.CensusReportInterval > 0 { + a.CensusReportInterval = a.configOverrides.CensusReportInterval + } } // This version reacts to user changes @@ -1076,6 +1092,9 @@ func (c *Core) setupActivityLog(ctx context.Context, wg *sync.WaitGroup) error { manager.retentionWorker(ctx, time.Now(), months) close(manager.retentionDone) }(manager.retentionMonths) + + manager.CensusReportDone = make(chan bool) + go c.activityLog.CensusReport(ctx, c.censusAgent) } return nil @@ -1576,7 +1595,9 @@ func (a *ActivityLog) handleQuery(ctx context.Context, startTime, endTime time.T if computePartial { // Traverse through current month's activitylog data and group clients // into months and namespaces + a.fragmentLock.RLock() partialByMonth, partialByNamespace = a.populateNamespaceAndMonthlyBreakdowns() + a.fragmentLock.RUnlock() // Convert the byNamespace breakdowns into structs that are // consumable by the /activity endpoint, so as to reuse code between these two @@ -1760,6 +1781,8 @@ type activityConfig struct { // Enabled is one of enable, disable, default. Enabled string `json:"enabled"` + + CensusReportInterval time.Duration `json:"census_report_interval"` } func defaultActivityConfig() activityConfig { diff --git a/vault/activity_log_util.go b/vault/activity_log_util.go index 8cfa76a0f093..57ba7215a513 100644 --- a/vault/activity_log_util.go +++ b/vault/activity_log_util.go @@ -8,3 +8,6 @@ import "context" func (a *ActivityLog) sendCurrentFragment(ctx context.Context) error { return nil } + +// CensusReport is a no-op on OSS +func (a *ActivityLog) CensusReport(_ctx context.Context, _ca *CensusAgent) {} diff --git a/vault/census.go b/vault/census.go new file mode 100644 index 000000000000..2312b3b54ef1 --- /dev/null +++ b/vault/census.go @@ -0,0 +1,6 @@ +//go:build !enterprise + +package vault + +// CensusAgent is a stub for OSS +type CensusAgent struct{} diff --git a/vault/core.go b/vault/core.go index 50077d673dc0..b692da84bfc9 100644 --- a/vault/core.go +++ b/vault/core.go @@ -638,6 +638,9 @@ type Core struct { activityLogConfig ActivityLogCoreConfig + // censusAgent is the mechanism used for reporting Vault's billing data. + censusAgent *CensusAgent + // activeTime is set on active nodes indicating the time at which this node // became active. activeTime time.Time @@ -801,6 +804,9 @@ type CoreConfig struct { LicensePath string LicensingConfig *LicensingConfig + // Configured Census Agent + censusAgent *CensusAgent + DisablePerformanceStandby bool DisableIndexing bool DisableKeyEncodingChecks bool diff --git a/vault/testing.go b/vault/testing.go index d8b243e6d9b2..35ba74f44284 100644 --- a/vault/testing.go +++ b/vault/testing.go @@ -214,6 +214,7 @@ func TestCoreWithSealAndUINoCleanup(t testing.T, opts *CoreConfig) *Core { conf.PluginDirectory = opts.PluginDirectory conf.DetectDeadlocks = opts.DetectDeadlocks conf.Experiments = []string{experiments.VaultExperimentEventsAlpha1} + conf.censusAgent = opts.censusAgent if opts.Logger != nil { conf.Logger = opts.Logger