chore: move Batcher and Tracker to workspacestats (#13418)

This commit is contained in:
Garrett Delfosse
2024-06-10 15:35:23 -04:00
committed by GitHub
parent c7e7312cb0
commit 5b9a65e5c1
13 changed files with 105 additions and 108 deletions
+6 -7
View File
@@ -62,7 +62,6 @@ import (
"github.com/coder/coder/v2/cli/config"
"github.com/coder/coder/v2/coderd"
"github.com/coder/coder/v2/coderd/autobuild"
"github.com/coder/coder/v2/coderd/batchstats"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/awsiamrds"
"github.com/coder/coder/v2/coderd/database/dbmem"
@@ -87,7 +86,7 @@ import (
stringutil "github.com/coder/coder/v2/coderd/util/strings"
"github.com/coder/coder/v2/coderd/workspaceapps"
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
"github.com/coder/coder/v2/coderd/workspaceusage"
"github.com/coder/coder/v2/coderd/workspacestats"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/drpc"
"github.com/coder/coder/v2/cryptorand"
@@ -870,9 +869,9 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
options.SwaggerEndpoint = vals.Swagger.Enable.Value()
}
batcher, closeBatcher, err := batchstats.New(ctx,
batchstats.WithLogger(options.Logger.Named("batchstats")),
batchstats.WithStore(options.Database),
batcher, closeBatcher, err := workspacestats.NewBatcher(ctx,
workspacestats.BatcherWithLogger(options.Logger.Named("batchstats")),
workspacestats.BatcherWithStore(options.Database),
)
if err != nil {
return xerrors.Errorf("failed to create agent stats batcher: %w", err)
@@ -977,8 +976,8 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
defer purger.Close()
// Updates workspace usage
tracker := workspaceusage.New(options.Database,
workspaceusage.WithLogger(logger.Named("workspace_usage_tracker")),
tracker := workspacestats.NewTracker(options.Database,
workspacestats.TrackerWithLogger(logger.Named("workspace_usage_tracker")),
)
options.WorkspaceUsageTracker = tracker
defer tracker.Close()
-6
View File
@@ -7,8 +7,6 @@ import (
"golang.org/x/xerrors"
"google.golang.org/protobuf/types/known/durationpb"
"github.com/google/uuid"
"cdr.dev/slog"
agentproto "github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/coderd/database"
@@ -16,10 +14,6 @@ import (
"github.com/coder/coder/v2/coderd/workspacestats"
)
type StatsBatcher interface {
Add(now time.Time, agentID uuid.UUID, templateID uuid.UUID, userID uuid.UUID, workspaceID uuid.UUID, st *agentproto.Stats) error
}
type StatsAPI struct {
AgentFn func(context.Context) (database.WorkspaceAgent, error)
Database database.Store
+1 -1
View File
@@ -39,7 +39,7 @@ type statsBatcher struct {
lastStats *agentproto.Stats
}
var _ agentapi.StatsBatcher = &statsBatcher{}
var _ workspacestats.Batcher = &statsBatcher{}
func (b *statsBatcher) Add(now time.Time, agentID uuid.UUID, templateID uuid.UUID, userID uuid.UUID, workspaceID uuid.UUID, st *agentproto.Stats) error {
b.mu.Lock()
+8 -11
View File
@@ -43,7 +43,6 @@ import (
"github.com/coder/coder/v2/coderd/appearance"
"github.com/coder/coder/v2/coderd/audit"
"github.com/coder/coder/v2/coderd/awsidentity"
"github.com/coder/coder/v2/coderd/batchstats"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/database/dbrollup"
@@ -69,7 +68,6 @@ import (
"github.com/coder/coder/v2/coderd/util/slice"
"github.com/coder/coder/v2/coderd/workspaceapps"
"github.com/coder/coder/v2/coderd/workspacestats"
"github.com/coder/coder/v2/coderd/workspaceusage"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/drpc"
"github.com/coder/coder/v2/codersdk/healthsdk"
@@ -189,7 +187,7 @@ type Options struct {
HTTPClient *http.Client
UpdateAgentMetrics func(ctx context.Context, labels prometheusmetrics.AgentMetricLabels, metrics []*agentproto.Stats_Metric)
StatsBatcher *batchstats.Batcher
StatsBatcher *workspacestats.DBBatcher
WorkspaceAppsStatsCollectorOptions workspaceapps.StatsCollectorOptions
@@ -206,7 +204,7 @@ type Options struct {
// stats. This is used to provide insights in the WebUI.
DatabaseRolluper *dbrollup.Rolluper
// WorkspaceUsageTracker tracks workspace usage by the CLI.
WorkspaceUsageTracker *workspaceusage.Tracker
WorkspaceUsageTracker *workspacestats.UsageTracker
}
// @title Coder API
@@ -384,8 +382,8 @@ func New(options *Options) *API {
}
if options.WorkspaceUsageTracker == nil {
options.WorkspaceUsageTracker = workspaceusage.New(options.Database,
workspaceusage.WithLogger(options.Logger.Named("workspace_usage_tracker")),
options.WorkspaceUsageTracker = workspacestats.NewTracker(options.Database,
workspacestats.TrackerWithLogger(options.Logger.Named("workspace_usage_tracker")),
)
}
@@ -434,8 +432,7 @@ func New(options *Options) *API {
options.Database,
options.Pubsub,
),
dbRolluper: options.DatabaseRolluper,
workspaceUsageTracker: options.WorkspaceUsageTracker,
dbRolluper: options.DatabaseRolluper,
}
var customRoleHandler CustomRoleHandler = &agplCustomRoleHandler{}
@@ -557,6 +554,7 @@ func New(options *Options) *API {
Pubsub: options.Pubsub,
TemplateScheduleStore: options.TemplateScheduleStore,
StatsBatcher: options.StatsBatcher,
UsageTracker: options.WorkspaceUsageTracker,
UpdateAgentMetricsFn: options.UpdateAgentMetrics,
AppStatBatchSize: workspaceapps.DefaultStatsDBReporterBatchSize,
})
@@ -1301,8 +1299,7 @@ type API struct {
Acquirer *provisionerdserver.Acquirer
// dbRolluper rolls up template usage stats from raw agent and app
// stats. This is used to provide insights in the WebUI.
dbRolluper *dbrollup.Rolluper
workspaceUsageTracker *workspaceusage.Tracker
dbRolluper *dbrollup.Rolluper
}
// Close waits for all WebSocket connections to drain before returning.
@@ -1341,7 +1338,7 @@ func (api *API) Close() error {
_ = (*coordinator).Close()
}
_ = api.agentProvider.Close()
api.workspaceUsageTracker.Close()
_ = api.statsReporter.Close()
return nil
}
+8 -9
View File
@@ -54,7 +54,6 @@ import (
"github.com/coder/coder/v2/coderd/audit"
"github.com/coder/coder/v2/coderd/autobuild"
"github.com/coder/coder/v2/coderd/awsidentity"
"github.com/coder/coder/v2/coderd/batchstats"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/database/dbrollup"
@@ -71,7 +70,7 @@ import (
"github.com/coder/coder/v2/coderd/util/ptr"
"github.com/coder/coder/v2/coderd/workspaceapps"
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
"github.com/coder/coder/v2/coderd/workspaceusage"
"github.com/coder/coder/v2/coderd/workspacestats"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/codersdk/drpc"
@@ -145,7 +144,7 @@ type Options struct {
// Logger should only be overridden if you expect errors
// as part of your test.
Logger *slog.Logger
StatsBatcher *batchstats.Batcher
StatsBatcher *workspacestats.DBBatcher
WorkspaceAppsStatsCollectorOptions workspaceapps.StatsCollectorOptions
AllowWorkspaceRenames bool
@@ -272,10 +271,10 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
if options.StatsBatcher == nil {
ctx, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)
batcher, closeBatcher, err := batchstats.New(ctx,
batchstats.WithStore(options.Database),
batcher, closeBatcher, err := workspacestats.NewBatcher(ctx,
workspacestats.BatcherWithStore(options.Database),
// Avoid cluttering up test output.
batchstats.WithLogger(slog.Make(sloghuman.Sink(io.Discard))),
workspacestats.BatcherWithLogger(slog.Make(sloghuman.Sink(io.Discard))),
)
require.NoError(t, err, "create stats batcher")
options.StatsBatcher = batcher
@@ -337,10 +336,10 @@ func NewOptions(t testing.TB, options *Options) (func(http.Handler), context.Can
options.WorkspaceUsageTrackerTick = make(chan time.Time, 1) // buffering just in case
}
// Close is called by API.Close()
wuTracker := workspaceusage.New(
wuTracker := workspacestats.NewTracker(
options.Database,
workspaceusage.WithLogger(options.Logger.Named("workspace_usage_tracker")),
workspaceusage.WithTickFlush(options.WorkspaceUsageTrackerTick, options.WorkspaceUsageTrackerFlush),
workspacestats.TrackerWithLogger(options.Logger.Named("workspace_usage_tracker")),
workspacestats.TrackerWithTickFlush(options.WorkspaceUsageTrackerTick, options.WorkspaceUsageTrackerFlush),
)
var mutex sync.RWMutex
+8 -9
View File
@@ -21,7 +21,6 @@ import (
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/agent/agenttest"
agentproto "github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/coderd/batchstats"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbauthz"
@@ -684,11 +683,11 @@ func TestTemplateInsights_Golden(t *testing.T) {
// NOTE(mafredri): Ideally we would pass batcher as a coderd option and
// insert using the agentClient, but we have a circular dependency on
// the database.
batcher, batcherCloser, err := batchstats.New(
batcher, batcherCloser, err := workspacestats.NewBatcher(
ctx,
batchstats.WithStore(db),
batchstats.WithLogger(logger.Named("batchstats")),
batchstats.WithInterval(time.Hour),
workspacestats.BatcherWithStore(db),
workspacestats.BatcherWithLogger(logger.Named("batchstats")),
workspacestats.BatcherWithInterval(time.Hour),
)
require.NoError(t, err)
defer batcherCloser() // Flushes the stats, this is to ensure they're written.
@@ -1583,11 +1582,11 @@ func TestUserActivityInsights_Golden(t *testing.T) {
// NOTE(mafredri): Ideally we would pass batcher as a coderd option and
// insert using the agentClient, but we have a circular dependency on
// the database.
batcher, batcherCloser, err := batchstats.New(
batcher, batcherCloser, err := workspacestats.NewBatcher(
ctx,
batchstats.WithStore(db),
batchstats.WithLogger(logger.Named("batchstats")),
batchstats.WithInterval(time.Hour),
workspacestats.BatcherWithStore(db),
workspacestats.BatcherWithLogger(logger.Named("batchstats")),
workspacestats.BatcherWithInterval(time.Hour),
)
require.NoError(t, err)
defer batcherCloser() // Flushes the stats, this is to ensure they're written.
@@ -21,7 +21,6 @@ import (
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/coderd/agentmetrics"
"github.com/coder/coder/v2/coderd/batchstats"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbgen"
@@ -29,6 +28,7 @@ import (
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/prometheusmetrics"
"github.com/coder/coder/v2/coderd/workspacestats"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/cryptorand"
@@ -391,14 +391,14 @@ func TestAgentStats(t *testing.T) {
db, pubsub := dbtestutil.NewDB(t)
log := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
batcher, closeBatcher, err := batchstats.New(ctx,
batcher, closeBatcher, err := workspacestats.NewBatcher(ctx,
// We had previously set the batch size to 1 here, but that caused
// intermittent test flakes due to a race between the batcher completing
// its flush and the test asserting that the metrics were collected.
// Instead, we close the batcher after all stats have been posted, which
// forces a flush.
batchstats.WithStore(db),
batchstats.WithLogger(log),
workspacestats.BatcherWithStore(db),
workspacestats.BatcherWithLogger(log),
)
require.NoError(t, err, "create stats batcher failed")
t.Cleanup(closeBatcher)
+1 -1
View File
@@ -1115,7 +1115,7 @@ func (api *API) postWorkspaceUsage(rw http.ResponseWriter, r *http.Request) {
return
}
api.workspaceUsageTracker.Add(workspace.ID)
api.statsReporter.TrackUsage(workspace.ID)
rw.WriteHeader(http.StatusNoContent)
}
@@ -1,4 +1,4 @@
package batchstats
package workspacestats
import (
"context"
@@ -24,9 +24,13 @@ const (
defaultFlushInterval = time.Second
)
// Batcher holds a buffer of agent stats and periodically flushes them to
// its configured store. It also updates the workspace's last used time.
type Batcher struct {
type Batcher interface {
Add(now time.Time, agentID uuid.UUID, templateID uuid.UUID, userID uuid.UUID, workspaceID uuid.UUID, st *agentproto.Stats) error
}
// DBBatcher holds a buffer of agent stats and periodically flushes them to
// its configured store.
type DBBatcher struct {
store database.Store
log slog.Logger
@@ -50,39 +54,39 @@ type Batcher struct {
}
// Option is a functional option for configuring a Batcher.
type Option func(b *Batcher)
type BatcherOption func(b *DBBatcher)
// WithStore sets the store to use for storing stats.
func WithStore(store database.Store) Option {
return func(b *Batcher) {
// BatcherWithStore sets the store to use for storing stats.
func BatcherWithStore(store database.Store) BatcherOption {
return func(b *DBBatcher) {
b.store = store
}
}
// WithBatchSize sets the number of stats to store in a batch.
func WithBatchSize(size int) Option {
return func(b *Batcher) {
// BatcherWithBatchSize sets the number of stats to store in a batch.
func BatcherWithBatchSize(size int) BatcherOption {
return func(b *DBBatcher) {
b.batchSize = size
}
}
// WithInterval sets the interval for flushes.
func WithInterval(d time.Duration) Option {
return func(b *Batcher) {
// BatcherWithInterval sets the interval for flushes.
func BatcherWithInterval(d time.Duration) BatcherOption {
return func(b *DBBatcher) {
b.interval = d
}
}
// WithLogger sets the logger to use for logging.
func WithLogger(log slog.Logger) Option {
return func(b *Batcher) {
// BatcherWithLogger sets the logger to use for logging.
func BatcherWithLogger(log slog.Logger) BatcherOption {
return func(b *DBBatcher) {
b.log = log
}
}
// New creates a new Batcher and starts it.
func New(ctx context.Context, opts ...Option) (*Batcher, func(), error) {
b := &Batcher{}
// NewBatcher creates a new Batcher and starts it.
func NewBatcher(ctx context.Context, opts ...BatcherOption) (*DBBatcher, func(), error) {
b := &DBBatcher{}
b.log = slog.Make(sloghuman.Sink(os.Stderr))
b.flushLever = make(chan struct{}, 1) // Buffered so that it doesn't block.
for _, opt := range opts {
@@ -127,7 +131,7 @@ func New(ctx context.Context, opts ...Option) (*Batcher, func(), error) {
}
// Add adds a stat to the batcher for the given workspace and agent.
func (b *Batcher) Add(
func (b *DBBatcher) Add(
now time.Time,
agentID uuid.UUID,
templateID uuid.UUID,
@@ -174,7 +178,7 @@ func (b *Batcher) Add(
}
// Run runs the batcher.
func (b *Batcher) run(ctx context.Context) {
func (b *DBBatcher) run(ctx context.Context) {
// nolint:gocritic // This is only ever used for one thing - inserting agent stats.
authCtx := dbauthz.AsSystemRestricted(ctx)
for {
@@ -199,7 +203,7 @@ func (b *Batcher) run(ctx context.Context) {
}
// flush flushes the batcher's buffer.
func (b *Batcher) flush(ctx context.Context, forced bool, reason string) {
func (b *DBBatcher) flush(ctx context.Context, forced bool, reason string) {
b.mu.Lock()
b.flushForced.Store(true)
start := time.Now()
@@ -256,7 +260,7 @@ func (b *Batcher) flush(ctx context.Context, forced bool, reason string) {
}
// initBuf resets the buffer. b MUST be locked.
func (b *Batcher) initBuf(size int) {
func (b *DBBatcher) initBuf(size int) {
b.buf = &database.InsertWorkspaceAgentStatsParams{
ID: make([]uuid.UUID, 0, b.batchSize),
CreatedAt: make([]time.Time, 0, b.batchSize),
@@ -280,7 +284,7 @@ func (b *Batcher) initBuf(size int) {
b.connectionsByProto = make([]map[string]int64, 0, size)
}
func (b *Batcher) resetBuf() {
func (b *DBBatcher) resetBuf() {
b.buf.ID = b.buf.ID[:0]
b.buf.CreatedAt = b.buf.CreatedAt[:0]
b.buf.UserID = b.buf.UserID[:0]
@@ -1,4 +1,4 @@
package batchstats
package workspacestats
import (
"context"
@@ -35,10 +35,10 @@ func TestBatchStats(t *testing.T) {
tick := make(chan time.Time)
flushed := make(chan int, 1)
b, closer, err := New(ctx,
WithStore(store),
WithLogger(log),
func(b *Batcher) {
b, closer, err := NewBatcher(ctx,
BatcherWithStore(store),
BatcherWithLogger(log),
func(b *DBBatcher) {
b.tickCh = tick
b.flushed = flushed
},
+10 -5
View File
@@ -22,16 +22,13 @@ import (
"github.com/coder/coder/v2/codersdk"
)
type StatsBatcher interface {
Add(now time.Time, agentID uuid.UUID, templateID uuid.UUID, userID uuid.UUID, workspaceID uuid.UUID, st *agentproto.Stats) error
}
type ReporterOptions struct {
Database database.Store
Logger slog.Logger
Pubsub pubsub.Pubsub
TemplateScheduleStore *atomic.Pointer[schedule.TemplateScheduleStore]
StatsBatcher StatsBatcher
StatsBatcher Batcher
UsageTracker *UsageTracker
UpdateAgentMetricsFn func(ctx context.Context, labels prometheusmetrics.AgentMetricLabels, metrics []*agentproto.Stats_Metric)
AppStatBatchSize int
@@ -205,3 +202,11 @@ func UpdateTemplateWorkspacesLastUsedAt(ctx context.Context, db database.Store,
}
return nil
}
func (r *Reporter) TrackUsage(workspaceID uuid.UUID) {
r.opts.UsageTracker.Add(workspaceID)
}
func (r *Reporter) Close() error {
return r.opts.UsageTracker.Close()
}
@@ -1,4 +1,4 @@
package workspaceusage
package workspacestats
import (
"bytes"
@@ -25,10 +25,10 @@ type Store interface {
BatchUpdateWorkspaceLastUsedAt(context.Context, database.BatchUpdateWorkspaceLastUsedAtParams) error
}
// Tracker tracks and de-bounces updates to workspace usage activity.
// UsageTracker tracks and de-bounces updates to workspace usage activity.
// It keeps an internal map of workspace IDs that have been used and
// periodically flushes this to its configured Store.
type Tracker struct {
type UsageTracker struct {
log slog.Logger // you know, for logs
flushLock sync.Mutex // protects m
flushErrors int // tracks the number of consecutive errors flushing
@@ -42,10 +42,10 @@ type Tracker struct {
flushCh chan int // used for testing.
}
// New returns a new Tracker. It is the caller's responsibility
// NewTracker returns a new Tracker. It is the caller's responsibility
// to call Close().
func New(s Store, opts ...Option) *Tracker {
tr := &Tracker{
func NewTracker(s Store, opts ...TrackerOption) *UsageTracker {
tr := &UsageTracker{
log: slog.Make(sloghuman.Sink(os.Stderr)),
m: &uuidSet{},
s: s,
@@ -67,33 +67,33 @@ func New(s Store, opts ...Option) *Tracker {
return tr
}
type Option func(*Tracker)
type TrackerOption func(*UsageTracker)
// WithLogger sets the logger to be used by Tracker.
func WithLogger(log slog.Logger) Option {
return func(h *Tracker) {
// TrackerWithLogger sets the logger to be used by Tracker.
func TrackerWithLogger(log slog.Logger) TrackerOption {
return func(h *UsageTracker) {
h.log = log
}
}
// WithFlushInterval allows configuring the flush interval of Tracker.
func WithFlushInterval(d time.Duration) Option {
return func(h *Tracker) {
// TrackerWithFlushInterval allows configuring the flush interval of Tracker.
func TrackerWithFlushInterval(d time.Duration) TrackerOption {
return func(h *UsageTracker) {
ticker := time.NewTicker(d)
h.tickCh = ticker.C
h.stopTick = ticker.Stop
}
}
// WithTickFlush allows passing two channels: one that reads
// TrackerWithTickFlush allows passing two channels: one that reads
// a time.Time, and one that returns the number of marked workspaces
// every time Tracker flushes.
// For testing only and will panic if used outside of tests.
func WithTickFlush(tickCh <-chan time.Time, flushCh chan int) Option {
func TrackerWithTickFlush(tickCh <-chan time.Time, flushCh chan int) TrackerOption {
if flag.Lookup("test.v") == nil {
panic("developer error: WithTickFlush is not to be used outside of tests.")
}
return func(h *Tracker) {
return func(h *UsageTracker) {
h.tickCh = tickCh
h.stopTick = func() {}
h.flushCh = flushCh
@@ -102,14 +102,14 @@ func WithTickFlush(tickCh <-chan time.Time, flushCh chan int) Option {
// Add marks the workspace with the given ID as having been used recently.
// Tracker will periodically flush this to its configured Store.
func (tr *Tracker) Add(workspaceID uuid.UUID) {
func (tr *UsageTracker) Add(workspaceID uuid.UUID) {
tr.m.Add(workspaceID)
}
// flush updates last_used_at of all current workspace IDs.
// If this is held while a previous flush is in progress, it will
// deadlock until the previous flush has completed.
func (tr *Tracker) flush(now time.Time) {
func (tr *UsageTracker) flush(now time.Time) {
// Copy our current set of IDs
ids := tr.m.UniqueAndClear()
count := len(ids)
@@ -154,7 +154,7 @@ func (tr *Tracker) flush(now time.Time) {
// loop periodically flushes every tick.
// If loop is called after Close, it will exit immediately and log an error.
func (tr *Tracker) loop() {
func (tr *UsageTracker) loop() {
select {
case <-tr.doneCh:
tr.log.Error(context.Background(), "developer error: Loop called after Close")
@@ -186,7 +186,7 @@ func (tr *Tracker) loop() {
// Close stops Tracker and returns once Loop has exited.
// After calling Close(), Loop must not be called.
func (tr *Tracker) Close() error {
func (tr *UsageTracker) Close() error {
tr.stopOnce.Do(func() {
tr.stopCh <- struct{}{}
tr.stopTick()
@@ -1,4 +1,4 @@
package workspaceusage_test
package workspacestats_test
import (
"bytes"
@@ -21,7 +21,7 @@ import (
"github.com/coder/coder/v2/coderd/database/dbtestutil"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/database/pubsub"
"github.com/coder/coder/v2/coderd/workspaceusage"
"github.com/coder/coder/v2/coderd/workspacestats"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/testutil"
)
@@ -35,9 +35,9 @@ func TestTracker(t *testing.T) {
tickCh := make(chan time.Time)
flushCh := make(chan int, 1)
wut := workspaceusage.New(mDB,
workspaceusage.WithLogger(log),
workspaceusage.WithTickFlush(tickCh, flushCh),
wut := workspacestats.NewTracker(mDB,
workspacestats.TrackerWithLogger(log),
workspacestats.TrackerWithTickFlush(tickCh, flushCh),
)
defer wut.Close()