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:
Steven Masley
2023-05-30 19:18:27 +02:00
committed by GitHub
parent 68658b5197
commit c795a0e500
29 changed files with 606 additions and 310 deletions

View File

@ -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.

View File

@ -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 {

View File

@ -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)

View File

@ -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)

View File

@ -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
}

View File

@ -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