mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add flag to disable template insights (#20940)
Closes #20399 To summarize the original commit messages: - Do not log stats to the database. - Return errors on the insight endpoints. - Update the frontend to show those errors. - Also fixes an issue with getting the user status count via codersdk, since I added a test to ensure it was not disabled by this flag and it was sending the wrong payload.
This commit is contained in:
@@ -28,7 +28,7 @@ import (
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
)
|
||||
|
||||
func TestUpdateStates(t *testing.T) {
|
||||
func TestUpdateStats(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var (
|
||||
@@ -542,6 +542,135 @@ func TestUpdateStates(t *testing.T) {
|
||||
}
|
||||
require.True(t, updateAgentMetricsFnCalled)
|
||||
})
|
||||
|
||||
t.Run("DropStats", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var (
|
||||
now = dbtime.Now()
|
||||
dbM = dbmock.NewMockStore(gomock.NewController(t))
|
||||
ps = pubsub.NewInMemory()
|
||||
|
||||
templateScheduleStore = schedule.MockTemplateScheduleStore{
|
||||
GetFn: func(context.Context, database.Store, uuid.UUID) (schedule.TemplateScheduleOptions, error) {
|
||||
panic("should not be called")
|
||||
},
|
||||
SetFn: func(context.Context, database.Store, database.Template, schedule.TemplateScheduleOptions) (database.Template, error) {
|
||||
panic("not implemented")
|
||||
},
|
||||
}
|
||||
updateAgentMetricsFnCalled = false
|
||||
tickCh = make(chan time.Time)
|
||||
flushCh = make(chan int, 1)
|
||||
wut = workspacestats.NewTracker(dbM,
|
||||
workspacestats.TrackerWithTickFlush(tickCh, flushCh),
|
||||
)
|
||||
|
||||
req = &agentproto.UpdateStatsRequest{
|
||||
Stats: &agentproto.Stats{
|
||||
ConnectionsByProto: map[string]int64{
|
||||
"tcp": 1,
|
||||
"dean": 2,
|
||||
},
|
||||
ConnectionCount: 3,
|
||||
ConnectionMedianLatencyMs: 23,
|
||||
RxPackets: 120,
|
||||
RxBytes: 1000,
|
||||
TxPackets: 130,
|
||||
TxBytes: 2000,
|
||||
SessionCountVscode: 1,
|
||||
SessionCountJetbrains: 2,
|
||||
SessionCountReconnectingPty: 3,
|
||||
SessionCountSsh: 4,
|
||||
Metrics: []*agentproto.Stats_Metric{
|
||||
{
|
||||
Name: "awesome metric",
|
||||
Value: 42,
|
||||
},
|
||||
{
|
||||
Name: "uncool metric",
|
||||
Value: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
api := agentapi.StatsAPI{
|
||||
AgentFn: func(context.Context) (database.WorkspaceAgent, error) {
|
||||
return agent, nil
|
||||
},
|
||||
Workspace: &workspaceAsCacheFields,
|
||||
Database: dbM,
|
||||
StatsReporter: workspacestats.NewReporter(workspacestats.ReporterOptions{
|
||||
Database: dbM,
|
||||
Pubsub: ps,
|
||||
StatsBatcher: nil, // Should not be called.
|
||||
UsageTracker: wut,
|
||||
TemplateScheduleStore: templateScheduleStorePtr(templateScheduleStore),
|
||||
UpdateAgentMetricsFn: func(ctx context.Context, labels prometheusmetrics.AgentMetricLabels, metrics []*agentproto.Stats_Metric) {
|
||||
updateAgentMetricsFnCalled = true
|
||||
assert.Equal(t, prometheusmetrics.AgentMetricLabels{
|
||||
Username: user.Username,
|
||||
WorkspaceName: workspace.Name,
|
||||
AgentName: agent.Name,
|
||||
TemplateName: template.Name,
|
||||
}, labels)
|
||||
assert.Equal(t, req.Stats.Metrics, metrics)
|
||||
},
|
||||
DisableDatabaseInserts: true,
|
||||
}),
|
||||
AgentStatsRefreshInterval: 10 * time.Second,
|
||||
TimeNowFn: func() time.Time {
|
||||
return now
|
||||
},
|
||||
}
|
||||
defer wut.Close()
|
||||
|
||||
// We expect an activity bump because ConnectionCount > 0.
|
||||
dbM.EXPECT().ActivityBumpWorkspace(gomock.Any(), database.ActivityBumpWorkspaceParams{
|
||||
WorkspaceID: workspace.ID,
|
||||
NextAutostart: time.Time{}.UTC(),
|
||||
}).Return(nil)
|
||||
|
||||
// Workspace last used at gets bumped.
|
||||
dbM.EXPECT().BatchUpdateWorkspaceLastUsedAt(gomock.Any(), database.BatchUpdateWorkspaceLastUsedAtParams{
|
||||
IDs: []uuid.UUID{workspace.ID},
|
||||
LastUsedAt: now,
|
||||
}).Return(nil)
|
||||
|
||||
// Ensure that pubsub notifications are sent.
|
||||
notifyDescription := make(chan struct{})
|
||||
ps.SubscribeWithErr(wspubsub.WorkspaceEventChannel(workspace.OwnerID),
|
||||
wspubsub.HandleWorkspaceEvent(
|
||||
func(_ context.Context, e wspubsub.WorkspaceEvent, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if e.Kind == wspubsub.WorkspaceEventKindStatsUpdate && e.WorkspaceID == workspace.ID {
|
||||
go func() {
|
||||
notifyDescription <- struct{}{}
|
||||
}()
|
||||
}
|
||||
}))
|
||||
|
||||
resp, err := api.UpdateStats(context.Background(), req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, &agentproto.UpdateStatsResponse{
|
||||
ReportInterval: durationpb.New(10 * time.Second),
|
||||
}, resp)
|
||||
|
||||
tickCh <- now
|
||||
count := <-flushCh
|
||||
require.Equal(t, 1, count, "expected one flush with one id")
|
||||
|
||||
ctx := testutil.Context(t, testutil.WaitShort)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Error("timed out while waiting for pubsub notification")
|
||||
case <-notifyDescription:
|
||||
}
|
||||
require.True(t, updateAgentMetricsFnCalled)
|
||||
})
|
||||
}
|
||||
|
||||
func templateScheduleStorePtr(store schedule.TemplateScheduleStore) *atomic.Pointer[schedule.TemplateScheduleStore] {
|
||||
|
||||
Reference in New Issue
Block a user