Skip to content

Commit

Permalink
[Backport-5.0] [fix] fixes for mau calculations in product analytics (#…
Browse files Browse the repository at this point in the history
…52581) (#52682)

Backport #52581

## Test plan

Unit tests
  • Loading branch information
kopancek committed May 31, 2023
1 parent 636872c commit 00d83fe
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 7 deletions.
7 changes: 6 additions & 1 deletion internal/adminanalytics/BUILD.bazel

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions internal/adminanalytics/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package adminanalytics
import (
"context"
"fmt"
"time"

"github.com/keegancsmith/sqlf"

Expand Down Expand Up @@ -156,10 +155,7 @@ func (f *Users) MonthlyActiveUsers(ctx context.Context) ([]*MonthlyActiveUsersRo
}
}

now := time.Now()
to := now.Format(time.RFC3339)
prevMonth := now.AddDate(0, -2, 0) // going back 2 months
from := time.Date(prevMonth.Year(), prevMonth.Month(), 1, 0, 0, 0, 0, now.Location()).Format(time.RFC3339)
from, to := getTimestamps(2) // go back 2 months

query := sqlf.Sprintf(mauQuery, from, to, sqlf.Join(getDefaultConds(), ") AND ("))

Expand Down
15 changes: 14 additions & 1 deletion internal/adminanalytics/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var (
LastWeek = "LAST_WEEK"
Daily = "DAILY"
Weekly = "WEEKLY"
timeNow = time.Now
)

func makeDateParameters(dateRange string, grouping string, dateColumnName string) (*sqlf.Query, *sqlf.Query, error) {
Expand Down Expand Up @@ -74,12 +75,14 @@ LEFT OUTER JOIN users ON users.id = event_logs.user_id
`

func getDefaultConds() []*sqlf.Query {
return database.BuildCommonUsageConds(&database.CommonUsageOptions{
commonConds := database.BuildCommonUsageConds(&database.CommonUsageOptions{
ExcludeSystemUsers: true,
ExcludeNonActiveUsers: true,
ExcludeSourcegraphAdmins: true,
ExcludeSourcegraphOperators: true,
}, []*sqlf.Query{})

return append(commonConds, sqlf.Sprintf("anonymous_user_id != 'backend'"))
}

func makeEventLogsQueries(dateRange string, grouping string, events []string, conditions ...*sqlf.Query) (*sqlf.Query, *sqlf.Query, error) {
Expand Down Expand Up @@ -107,3 +110,13 @@ func makeEventLogsQueries(dateRange string, grouping string, events []string, co

return nodesQuery, summaryQuery, nil
}

// getTimestamps returns the start and end timestamps for the given number of months.
func getTimestamps(months int) (string, string) {
now := timeNow().UTC()
to := now.Format(time.RFC3339)
prevMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.UTC).AddDate(0, -months, 0)
from := prevMonth.Format(time.RFC3339)

return from, to
}
77 changes: 77 additions & 0 deletions internal/adminanalytics/utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package adminanalytics

import (
"testing"
"time"

"github.com/stretchr/testify/require"
)

func TestGetTimestamps(t *testing.T) {
now := time.Date(2023, 5, 30, 10, 12, 0, 0, time.UTC)

mockTimeNow := func(t time.Time) {
timeNow = func() time.Time {
return t
}
}

testCases := []struct {
name string
months int
now time.Time
expectedFrom string
expectedTo string
}{
{
name: "3 months",
months: 3,
now: now,
expectedFrom: "2023-02-01T00:00:00Z",
expectedTo: "2023-05-30T10:12:00Z",
},
{
name: "1 month",
months: 1,
now: now,
expectedFrom: "2023-04-01T00:00:00Z",
expectedTo: "2023-05-30T10:12:00Z",
},
{
name: "0 months",
months: 0,
now: now,
expectedFrom: "2023-05-01T00:00:00Z",
expectedTo: "2023-05-30T10:12:00Z",
},
{
name: "February non-leap year",
months: 2,
now: time.Date(2023, 4, 30, 10, 59, 0, 0, time.UTC),
expectedFrom: "2023-02-01T00:00:00Z",
expectedTo: "2023-04-30T10:59:00Z",
},
{
name: "February leap year",
months: 2,
now: time.Date(2024, 4, 29, 10, 59, 0, 0, time.UTC), // 2024 is a leap year
expectedFrom: "2024-02-01T00:00:00Z",
expectedTo: "2024-04-29T10:59:00Z",
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
mockTimeNow(tc.now)

t.Cleanup(func() {
timeNow = time.Now
})

from, to := getTimestamps(tc.months)

require.Equal(t, tc.expectedFrom, from)
require.Equal(t, tc.expectedTo, to)
})
}
}

0 comments on commit 00d83fe

Please sign in to comment.