mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
feat: Fix Deployment DAUs to work with local timezones (#7647)
* chore: Add timezone param to DAU SQL query * Merge DAUs response * Pass time offsets to metricscache
This commit is contained in:
@ -205,19 +205,19 @@ func (q *querier) GetTemplateAverageBuildTime(ctx context.Context, arg database.
|
||||
}
|
||||
|
||||
// Only used by metrics cache.
|
||||
func (q *querier) GetTemplateDAUs(ctx context.Context, templateID uuid.UUID) ([]database.GetTemplateDAUsRow, error) {
|
||||
func (q *querier) GetTemplateDAUs(ctx context.Context, arg database.GetTemplateDAUsParams) ([]database.GetTemplateDAUsRow, error) {
|
||||
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.GetTemplateDAUs(ctx, templateID)
|
||||
return q.db.GetTemplateDAUs(ctx, arg)
|
||||
}
|
||||
|
||||
// Only used by metrics cache.
|
||||
func (q *querier) GetDeploymentDAUs(ctx context.Context) ([]database.GetDeploymentDAUsRow, error) {
|
||||
func (q *querier) GetDeploymentDAUs(ctx context.Context, tzOffset int32) ([]database.GetDeploymentDAUsRow, error) {
|
||||
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return q.db.GetDeploymentDAUs(ctx)
|
||||
return q.db.GetDeploymentDAUs(ctx, tzOffset)
|
||||
}
|
||||
|
||||
// UpdateWorkspaceBuildCostByID is used by the provisioning system to update the cost of a workspace build.
|
||||
|
@ -435,21 +435,21 @@ func (q *fakeQuerier) InsertWorkspaceAgentStat(_ context.Context, p database.Ins
|
||||
return stat, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetTemplateDAUs(_ context.Context, templateID uuid.UUID) ([]database.GetTemplateDAUsRow, error) {
|
||||
func (q *fakeQuerier) GetTemplateDAUs(_ context.Context, arg database.GetTemplateDAUsParams) ([]database.GetTemplateDAUsRow, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
seens := make(map[time.Time]map[uuid.UUID]struct{})
|
||||
|
||||
for _, as := range q.workspaceAgentStats {
|
||||
if as.TemplateID != templateID {
|
||||
if as.TemplateID != arg.TemplateID {
|
||||
continue
|
||||
}
|
||||
if as.ConnectionCount == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
date := as.CreatedAt.Truncate(time.Hour * 24)
|
||||
date := as.CreatedAt.UTC().Add(time.Duration(arg.TzOffset) * time.Hour).Truncate(time.Hour * 24)
|
||||
|
||||
dateEntry := seens[date]
|
||||
if dateEntry == nil {
|
||||
@ -478,7 +478,7 @@ func (q *fakeQuerier) GetTemplateDAUs(_ context.Context, templateID uuid.UUID) (
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetDeploymentDAUs(_ context.Context) ([]database.GetDeploymentDAUsRow, error) {
|
||||
func (q *fakeQuerier) GetDeploymentDAUs(_ context.Context, tzOffset int32) ([]database.GetDeploymentDAUsRow, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
@ -488,7 +488,7 @@ func (q *fakeQuerier) GetDeploymentDAUs(_ context.Context) ([]database.GetDeploy
|
||||
if as.ConnectionCount == 0 {
|
||||
continue
|
||||
}
|
||||
date := as.CreatedAt.Truncate(time.Hour * 24)
|
||||
date := as.CreatedAt.UTC().Add(time.Duration(tzOffset) * time.Hour).Truncate(time.Hour * 24)
|
||||
|
||||
dateEntry := seens[date]
|
||||
if dateEntry == nil {
|
||||
|
@ -433,18 +433,18 @@ func (mr *MockStoreMockRecorder) GetDERPMeshKey(arg0 interface{}) *gomock.Call {
|
||||
}
|
||||
|
||||
// GetDeploymentDAUs mocks base method.
|
||||
func (m *MockStore) GetDeploymentDAUs(arg0 context.Context) ([]database.GetDeploymentDAUsRow, error) {
|
||||
func (m *MockStore) GetDeploymentDAUs(arg0 context.Context, arg1 int32) ([]database.GetDeploymentDAUsRow, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetDeploymentDAUs", arg0)
|
||||
ret := m.ctrl.Call(m, "GetDeploymentDAUs", arg0, arg1)
|
||||
ret0, _ := ret[0].([]database.GetDeploymentDAUsRow)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetDeploymentDAUs indicates an expected call of GetDeploymentDAUs.
|
||||
func (mr *MockStoreMockRecorder) GetDeploymentDAUs(arg0 interface{}) *gomock.Call {
|
||||
func (mr *MockStoreMockRecorder) GetDeploymentDAUs(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeploymentDAUs", reflect.TypeOf((*MockStore)(nil).GetDeploymentDAUs), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeploymentDAUs", reflect.TypeOf((*MockStore)(nil).GetDeploymentDAUs), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetDeploymentID mocks base method.
|
||||
@ -1093,7 +1093,7 @@ func (mr *MockStoreMockRecorder) GetTemplateByOrganizationAndName(arg0, arg1 int
|
||||
}
|
||||
|
||||
// GetTemplateDAUs mocks base method.
|
||||
func (m *MockStore) GetTemplateDAUs(arg0 context.Context, arg1 uuid.UUID) ([]database.GetTemplateDAUsRow, error) {
|
||||
func (m *MockStore) GetTemplateDAUs(arg0 context.Context, arg1 database.GetTemplateDAUsParams) ([]database.GetTemplateDAUsRow, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetTemplateDAUs", arg0, arg1)
|
||||
ret0, _ := ret[0].([]database.GetTemplateDAUsRow)
|
||||
|
@ -55,7 +55,7 @@ type sqlcQuerier interface {
|
||||
// are included.
|
||||
GetAuthorizationUserRoles(ctx context.Context, userID uuid.UUID) (GetAuthorizationUserRolesRow, error)
|
||||
GetDERPMeshKey(ctx context.Context) (string, error)
|
||||
GetDeploymentDAUs(ctx context.Context) ([]GetDeploymentDAUsRow, error)
|
||||
GetDeploymentDAUs(ctx context.Context, tzOffset int32) ([]GetDeploymentDAUsRow, error)
|
||||
GetDeploymentID(ctx context.Context) (string, error)
|
||||
GetDeploymentWorkspaceAgentStats(ctx context.Context, createdAt time.Time) (GetDeploymentWorkspaceAgentStatsRow, error)
|
||||
GetDeploymentWorkspaceStats(ctx context.Context) (GetDeploymentWorkspaceStatsRow, error)
|
||||
@ -101,7 +101,7 @@ type sqlcQuerier interface {
|
||||
GetTemplateAverageBuildTime(ctx context.Context, arg GetTemplateAverageBuildTimeParams) (GetTemplateAverageBuildTimeRow, error)
|
||||
GetTemplateByID(ctx context.Context, id uuid.UUID) (Template, error)
|
||||
GetTemplateByOrganizationAndName(ctx context.Context, arg GetTemplateByOrganizationAndNameParams) (Template, error)
|
||||
GetTemplateDAUs(ctx context.Context, templateID uuid.UUID) ([]GetTemplateDAUsRow, error)
|
||||
GetTemplateDAUs(ctx context.Context, arg GetTemplateDAUsParams) ([]GetTemplateDAUsRow, error)
|
||||
GetTemplateVersionByID(ctx context.Context, id uuid.UUID) (TemplateVersion, error)
|
||||
GetTemplateVersionByJobID(ctx context.Context, jobID uuid.UUID) (TemplateVersion, error)
|
||||
GetTemplateVersionByTemplateIDAndName(ctx context.Context, arg GetTemplateVersionByTemplateIDAndNameParams) (TemplateVersion, error)
|
||||
|
@ -6335,7 +6335,7 @@ func (q *sqlQuerier) DeleteOldWorkspaceAgentStats(ctx context.Context) error {
|
||||
|
||||
const getDeploymentDAUs = `-- name: GetDeploymentDAUs :many
|
||||
SELECT
|
||||
(created_at at TIME ZONE 'UTC')::date as date,
|
||||
(created_at at TIME ZONE cast($1::integer as text))::date as date,
|
||||
user_id
|
||||
FROM
|
||||
workspace_agent_stats
|
||||
@ -6352,8 +6352,8 @@ type GetDeploymentDAUsRow struct {
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetDeploymentDAUs(ctx context.Context) ([]GetDeploymentDAUsRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getDeploymentDAUs)
|
||||
func (q *sqlQuerier) GetDeploymentDAUs(ctx context.Context, tzOffset int32) ([]GetDeploymentDAUsRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getDeploymentDAUs, tzOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -6428,7 +6428,7 @@ func (q *sqlQuerier) GetDeploymentWorkspaceAgentStats(ctx context.Context, creat
|
||||
|
||||
const getTemplateDAUs = `-- name: GetTemplateDAUs :many
|
||||
SELECT
|
||||
(created_at at TIME ZONE 'UTC')::date as date,
|
||||
(created_at at TIME ZONE cast($2::integer as text))::date as date,
|
||||
user_id
|
||||
FROM
|
||||
workspace_agent_stats
|
||||
@ -6441,13 +6441,18 @@ ORDER BY
|
||||
date ASC
|
||||
`
|
||||
|
||||
type GetTemplateDAUsParams struct {
|
||||
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
|
||||
TzOffset int32 `db:"tz_offset" json:"tz_offset"`
|
||||
}
|
||||
|
||||
type GetTemplateDAUsRow struct {
|
||||
Date time.Time `db:"date" json:"date"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetTemplateDAUs(ctx context.Context, templateID uuid.UUID) ([]GetTemplateDAUsRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getTemplateDAUs, templateID)
|
||||
func (q *sqlQuerier) GetTemplateDAUs(ctx context.Context, arg GetTemplateDAUsParams) ([]GetTemplateDAUsRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getTemplateDAUs, arg.TemplateID, arg.TzOffset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ VALUES
|
||||
|
||||
-- name: GetTemplateDAUs :many
|
||||
SELECT
|
||||
(created_at at TIME ZONE 'UTC')::date as date,
|
||||
(created_at at TIME ZONE cast(@tz_offset::integer as text))::date as date,
|
||||
user_id
|
||||
FROM
|
||||
workspace_agent_stats
|
||||
@ -38,7 +38,7 @@ ORDER BY
|
||||
|
||||
-- name: GetDeploymentDAUs :many
|
||||
SELECT
|
||||
(created_at at TIME ZONE 'UTC')::date as date,
|
||||
(created_at at TIME ZONE cast(@tz_offset::integer as text))::date as date,
|
||||
user_id
|
||||
FROM
|
||||
workspace_agent_stats
|
||||
|
Reference in New Issue
Block a user