Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/olympia/conf/prod/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@

# See: https://bugzilla.mozilla.org/show_bug.cgi?id=1633746
BIGQUERY_AMO_DATASET = 'amo_prod'
# See: https://github.com/mozilla/addons/issues/16150
BIGQUERY_AMO_STATS_PREFIX = 'moz-fx-data-shared-prod.addons.'

CINDER_QUEUE_PREFIX = 'amo-'
# See comment in settings_base for background.
Expand Down
2 changes: 2 additions & 0 deletions src/olympia/lib/settings_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1481,6 +1481,8 @@ def read_only_mode(env):
# See: https://bugzilla.mozilla.org/show_bug.cgi?id=1633746
BIGQUERY_PROJECT = 'moz-fx-data-shared-prod'
BIGQUERY_AMO_DATASET = 'amo_dev'
# See: https://github.com/mozilla/addons/issues/16150
BIGQUERY_AMO_STATS_PREFIX = 'moz-fx-data-shared-prod.addons.dev_'

# The path to the current google service account configuration for Google Cloud
# Storage (should be able to upload, download and sign objects with its private
Expand Down
134 changes: 116 additions & 18 deletions src/olympia/stats/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.test.utils import override_settings

from google.cloud import bigquery
from waffle.testutils import override_switch

from olympia.amo.tests import TestCase, addon_factory
from olympia.constants.applications import ANDROID, FIREFOX
Expand Down Expand Up @@ -187,8 +188,7 @@ def test_returns_series(self):
]


@override_settings(BIGQUERY_PROJECT='project', BIGQUERY_AMO_DATASET='dataset')
class TestGetUpdatesSeries(BigQueryTestMixin, TestCase):
class GetUpdatesSeriesMixin(BigQueryTestMixin):
def setUp(self):
super().setUp()

Expand Down Expand Up @@ -220,7 +220,7 @@ def test_create_query(self, bigquery_client_mock, timer_mock):
end_date = date(2020, 5, 28)
expected_query = f"""
SELECT submission_date, dau
FROM `project.dataset.{AMO_STATS_DAU_VIEW}`
FROM `{self._get_fully_qualified_view_name()}`
WHERE addon_id = @addon_id
AND submission_date BETWEEN @submission_date_start AND @submission_date_end
ORDER BY submission_date DESC
Expand Down Expand Up @@ -262,7 +262,7 @@ def test_create_query_with_source(self, bigquery_client_mock, timer_mock):
for source, column in AMO_TO_BQ_DAU_COLUMN_MAPPING.items():
expected_query = f"""
SELECT submission_date, dau, {column}
FROM `project.dataset.{AMO_STATS_DAU_VIEW}`
FROM `{self._get_fully_qualified_view_name()}`
WHERE addon_id = @addon_id
AND submission_date BETWEEN @submission_date_start AND @submission_date_end
ORDER BY submission_date DESC
Expand All @@ -279,8 +279,21 @@ def test_create_query_with_source(self, bigquery_client_mock, timer_mock):
timer_mock.assert_called_with(f'stats.get_updates_series.bigquery.{source}')


@override_switch('2026-amo-stats', active=False)
@override_settings(BIGQUERY_PROJECT='project', BIGQUERY_AMO_DATASET='dataset')
class TestGetAddonsAndAverageDailyUsersFromBigQuery(BigQueryTestMixin, TestCase):
class TestGetUpdatesSeriesWithSwitchDisabled(GetUpdatesSeriesMixin, TestCase):
def _get_fully_qualified_view_name(self):
return f'project.dataset.{AMO_STATS_DAU_VIEW}'


@override_switch('2026-amo-stats', active=True)
@override_settings(BIGQUERY_AMO_STATS_PREFIX='project.new_dataset.prefix_')
class TestGetUpdatesSeriesWithSwitchEnabled(GetUpdatesSeriesMixin, TestCase):
def _get_fully_qualified_view_name(self):
return f'project.new_dataset.prefix_{AMO_STATS_DAU_VIEW}'


class GetAddonsAndAverageDailyUsersFromBigQueryMixin(BigQueryTestMixin):
@mock.patch('google.cloud.bigquery.Client')
def test_create_client(self, bigquery_client_mock):
client = self.create_mock_client()
Expand All @@ -300,7 +313,7 @@ def test_create_query(self, bigquery_client_mock):
bigquery_client_mock.from_service_account_json.return_value = client
expected_query = f"""
SELECT addon_id, AVG(dau) AS count
FROM `project.dataset.{AMO_STATS_DAU_VIEW}`
FROM `{self._get_fully_qualified_view_name()}`
WHERE submission_date > DATE_SUB(CURRENT_DATE(), INTERVAL 13 DAY)
GROUP BY addon_id"""

Expand Down Expand Up @@ -334,16 +347,36 @@ def test_skips_null_values(self, bigquery_client_mock):
assert returned_results == [(1, 123)]


@override_switch('2026-amo-stats', active=False)
@override_settings(BIGQUERY_PROJECT='project', BIGQUERY_AMO_DATASET='dataset')
class TestGetAveragesByAddonFromBigQuery(BigQueryTestMixin, TestCase):
expected_base_query = f"""
class TestGetAddonsAndAverageDailyUsersFromBigQueryWithSwitchDisabled(
GetAddonsAndAverageDailyUsersFromBigQueryMixin, TestCase
):
def _get_fully_qualified_view_name(self):
return f'project.dataset.{AMO_STATS_DAU_VIEW}'


@override_switch('2026-amo-stats', active=True)
@override_settings(BIGQUERY_AMO_STATS_PREFIX='project.new_dataset.prefix_')
class TestGetAddonsAndAverageDailyUsersFromBigQueryWithSwitchEnabled(
GetAddonsAndAverageDailyUsersFromBigQueryMixin, TestCase
):
def _get_fully_qualified_view_name(self):
return f'project.new_dataset.prefix_{AMO_STATS_DAU_VIEW}'


class GetAveragesByAddonFromBigQueryMixin(BigQueryTestMixin):
@property
def expected_base_query(self):
view = self._get_fully_qualified_view_name()
return f"""
WITH
this_week AS (
SELECT
addon_id,
AVG(dau) AS avg_this_week
FROM
`project.dataset.{AMO_STATS_DAU_VIEW}`
`{view}`
WHERE
submission_date >= @one_week_date
AND
Expand All @@ -357,7 +390,7 @@ class TestGetAveragesByAddonFromBigQuery(BigQueryTestMixin, TestCase):
addon_id,
AVG(dau) AS avg_previous_week
FROM
`project.dataset.{AMO_STATS_DAU_VIEW}`
`{view}`
WHERE
submission_date BETWEEN @two_weeks_date AND @one_week_date
AND
Expand Down Expand Up @@ -482,8 +515,25 @@ def test_returned_values(self, bigquery_client_mock):
}


@override_switch('2026-amo-stats', active=False)
@override_settings(BIGQUERY_PROJECT='project', BIGQUERY_AMO_DATASET='dataset')
class TestGetDownloadSeries(BigQueryTestMixin, TestCase):
class TestGetAveragesByAddonFromBigQueryWithSwitchDisabled(
GetAveragesByAddonFromBigQueryMixin, TestCase
):
def _get_fully_qualified_view_name(self):
return f'project.dataset.{AMO_STATS_DAU_VIEW}'


@override_switch('2026-amo-stats', active=True)
@override_settings(BIGQUERY_AMO_STATS_PREFIX='project.new_dataset.prefix_')
class TestGetAveragesByAddonFromBigQueryWithSwitchEnabled(
GetAveragesByAddonFromBigQueryMixin, TestCase
):
def _get_fully_qualified_view_name(self):
return f'project.new_dataset.prefix_{AMO_STATS_DAU_VIEW}'


class GetDownloadSeriesMixin(BigQueryTestMixin):
def setUp(self):
super().setUp()

Expand Down Expand Up @@ -515,7 +565,7 @@ def test_create_query(self, bigquery_client_mock, timer_mock):
end_date = date(2020, 5, 28)
expected_query = f"""
SELECT submission_date, total_downloads
FROM `project.dataset.{AMO_STATS_DOWNLOAD_VIEW}`
FROM `{self._get_fully_qualified_view_name()}`
WHERE hashed_addon_id = @hashed_addon_id
AND submission_date BETWEEN @submission_date_start AND @submission_date_end
ORDER BY submission_date DESC
Expand Down Expand Up @@ -557,7 +607,7 @@ def test_create_query_with_source(self, bigquery_client_mock, timer_mock):
for source, column in AMO_TO_BQ_DOWNLOAD_COLUMN_MAPPING.items():
expected_query = f"""
SELECT submission_date, total_downloads, {column}
FROM `project.dataset.{AMO_STATS_DOWNLOAD_VIEW}`
FROM `{self._get_fully_qualified_view_name()}`
WHERE hashed_addon_id = @hashed_addon_id
AND submission_date BETWEEN @submission_date_start AND @submission_date_end
ORDER BY submission_date DESC
Expand All @@ -576,8 +626,21 @@ def test_create_query_with_source(self, bigquery_client_mock, timer_mock):
)


@override_switch('2026-amo-stats', active=False)
@override_settings(BIGQUERY_PROJECT='project', BIGQUERY_AMO_DATASET='dataset')
class TestGetAddonsAndWeeklyDownloadsFromBigQuery(BigQueryTestMixin, TestCase):
class TestGetDownloadSeriesWithSwitchDisabled(GetDownloadSeriesMixin, TestCase):
def _get_fully_qualified_view_name(self):
return f'project.dataset.{AMO_STATS_DOWNLOAD_VIEW}'


@override_switch('2026-amo-stats', active=True)
@override_settings(BIGQUERY_AMO_STATS_PREFIX='project.new_dataset.prefix_')
class TestGetDownloadSeriesWithSwitchEnabled(GetDownloadSeriesMixin, TestCase):
def _get_fully_qualified_view_name(self):
return f'project.new_dataset.prefix_{AMO_STATS_DOWNLOAD_VIEW}'


class GetAddonsAndWeeklyDownloadsFromBigQueryMixin(BigQueryTestMixin):
@mock.patch('google.cloud.bigquery.Client')
def test_create_client(self, bigquery_client_mock):
client = self.create_mock_client()
Expand All @@ -597,7 +660,7 @@ def test_create_query(self, bigquery_client_mock):
bigquery_client_mock.from_service_account_json.return_value = client
expected_query = f"""
SELECT hashed_addon_id, SUM(total_downloads) AS count
FROM `project.dataset.{AMO_STATS_DOWNLOAD_VIEW}`
FROM `{self._get_fully_qualified_view_name()}`
WHERE submission_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)
GROUP BY hashed_addon_id"""

Expand Down Expand Up @@ -631,8 +694,25 @@ def test_skips_null_values(self, bigquery_client_mock):
assert returned_results == [(1, 123)]


@override_switch('2026-amo-stats', active=False)
@override_settings(BIGQUERY_PROJECT='project', BIGQUERY_AMO_DATASET='dataset')
class TestGetAverageDailyUsersPerVersionFromBigquery(BigQueryTestMixin, TestCase):
class TestGetAddonsAndWeeklyDownloadsFromBigQueryWithSwitchDisabled(
GetAddonsAndWeeklyDownloadsFromBigQueryMixin, TestCase
):
def _get_fully_qualified_view_name(self):
return f'project.dataset.{AMO_STATS_DOWNLOAD_VIEW}'


@override_switch('2026-amo-stats', active=True)
@override_settings(BIGQUERY_AMO_STATS_PREFIX='project.new_dataset.prefix_')
class TestGetAddonsAndWeeklyDownloadsFromBigQueryWithSwitchEnabled(
GetAddonsAndWeeklyDownloadsFromBigQueryMixin, TestCase
):
def _get_fully_qualified_view_name(self):
return f'project.new_dataset.prefix_{AMO_STATS_DOWNLOAD_VIEW}'


class GetAverageDailyUsersPerVersionFromBigqueryMixin(BigQueryTestMixin):
def setUp(self):
super().setUp()
self.addon = addon_factory()
Expand All @@ -644,7 +724,7 @@ def test_create_query(self, bigquery_client_mock):
expected_query = f"""
SELECT `dau_by_version_struct`.`key` AS `version`,
cast(round(avg(`dau_by_version_struct`.`value`)) as BIGINT) AS `adu`
FROM `project.dataset.{AMO_STATS_DAU_VIEW}`,
FROM `{self._get_fully_qualified_view_name()}`,
unnest(`dau_by_addon_version`) as `dau_by_version_struct`
WHERE addon_id = @addon_id
AND submission_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 13 DAY)
Expand Down Expand Up @@ -673,7 +753,7 @@ def test_create_query_with_limit(self, bigquery_client_mock):
expected_query = f"""
SELECT `dau_by_version_struct`.`key` AS `version`,
cast(round(avg(`dau_by_version_struct`.`value`)) as BIGINT) AS `adu`
FROM `project.dataset.{AMO_STATS_DAU_VIEW}`,
FROM `{self._get_fully_qualified_view_name()}`,
unnest(`dau_by_addon_version`) as `dau_by_version_struct`
WHERE addon_id = @addon_id
AND submission_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 13 DAY)
Expand All @@ -687,3 +767,21 @@ def test_create_query_with_limit(self, bigquery_client_mock):
)

client.query.assert_called_with(expected_query, job_config=mock.ANY)


@override_switch('2026-amo-stats', active=False)
@override_settings(BIGQUERY_PROJECT='project', BIGQUERY_AMO_DATASET='dataset')
class TestGetAverageDailyUsersPerVersionFromBigqueryWithSwitchDisabled(
GetAverageDailyUsersPerVersionFromBigqueryMixin, TestCase
):
def _get_fully_qualified_view_name(self):
return f'project.dataset.{AMO_STATS_DAU_VIEW}'


@override_switch('2026-amo-stats', active=True)
@override_settings(BIGQUERY_AMO_STATS_PREFIX='project.new_dataset.prefix_')
class TestGetAverageDailyUsersPerVersionFromBigqueryWithSwitchEnabled(
GetAverageDailyUsersPerVersionFromBigqueryMixin, TestCase
):
def _get_fully_qualified_view_name(self):
return f'project.new_dataset.prefix_{AMO_STATS_DAU_VIEW}'
3 changes: 3 additions & 0 deletions src/olympia/stats/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from django.conf import settings

import waffle
from django_statsd.clients import statsd
from google.cloud import bigquery

Expand Down Expand Up @@ -32,6 +33,8 @@


def make_fully_qualified_view_name(view):
if waffle.switch_is_active('2026-amo-stats'):
return settings.BIGQUERY_AMO_STATS_PREFIX + view
return '.'.join([settings.BIGQUERY_PROJECT, settings.BIGQUERY_AMO_DATASET, view])


Expand Down
Loading