-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bde6756
commit d98619a
Showing
9 changed files
with
320 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
from alarms.alarm import Alarm | ||
from datetime import timedelta | ||
from helpers.query_helper import build_redshift_daily_location_visits_query | ||
from helpers.shoppertrak_sites import SHOPPERTRAK_SITES | ||
from nypl_py_utils.functions.log_helper import create_log | ||
|
||
|
||
class DailyLocationVisitsAlarms(Alarm): | ||
def __init__(self, redshift_client): | ||
super().__init__(redshift_client) | ||
self.logger = create_log("daily_location_visits_alarms") | ||
|
||
def run_checks(self): | ||
date_to_test = (self.yesterday_date - timedelta(days=29)).isoformat() | ||
self.logger.info(f"\nDAILY LOCATION VISITS: {date_to_test}\n") | ||
redshift_table = "daily_location_visits" + self.redshift_suffix | ||
redshift_query = build_redshift_daily_location_visits_query( | ||
redshift_table, date_to_test | ||
) | ||
|
||
self.redshift_client.connect() | ||
redshift_results = self.redshift_client.execute_query(redshift_query) | ||
self.redshift_client.close_connection() | ||
|
||
redshift_sites = [] | ||
redshift_healthy = [] | ||
for shoppertrak_site, is_all_healthy in redshift_results: | ||
redshift_sites.append(shoppertrak_site) | ||
redshift_healthy.append(int(is_all_healthy)) | ||
|
||
self.check_redshift_duplicate_sites_alarm(redshift_sites) | ||
self.check_redshift_missing_sites_alarm(redshift_sites) | ||
self.check_redshift_extra_sites_alarm(redshift_sites) | ||
self.check_redshift_healthy_sites_alarm(redshift_healthy) | ||
|
||
def check_redshift_duplicate_sites_alarm(self, redshift_sites): | ||
seen_sites = set() | ||
duplicate_sites = set() | ||
for site in redshift_sites: | ||
if site in seen_sites: | ||
duplicate_sites.add(site) | ||
seen_sites.add(site) | ||
|
||
if duplicate_sites: | ||
self.logger.error( | ||
"The following ShopperTrak sites are duplicated: {}".format( | ||
sorted(list(duplicate_sites)) | ||
) | ||
) | ||
|
||
def check_redshift_missing_sites_alarm(self, redshift_sites): | ||
missing_sites = SHOPPERTRAK_SITES.difference(set(redshift_sites)) | ||
if missing_sites: | ||
self.logger.error( | ||
"The following ShopperTrak sites are missing: {}".format( | ||
sorted(list(missing_sites)) | ||
) | ||
) | ||
|
||
def check_redshift_extra_sites_alarm(self, redshift_sites): | ||
extra_sites = set(redshift_sites).difference(SHOPPERTRAK_SITES) | ||
if extra_sites: | ||
self.logger.error( | ||
"The following unknown ShopperTrak site ids were found: {}".format( | ||
sorted(list(extra_sites)) | ||
) | ||
) | ||
|
||
def check_redshift_healthy_sites_alarm(self, redshift_healthy): | ||
percent_healthy = sum(redshift_healthy) / len(redshift_healthy) | ||
if percent_healthy < 0.5: | ||
self.logger.error( | ||
"Only {0:.2f}% of ShopperTrak sites were healthy".format( | ||
percent_healthy * 100 | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
SHOPPERTRAK_SITES = set( | ||
[ | ||
"ag", | ||
"al", | ||
"ba", | ||
"bc", | ||
"be", | ||
"bl", | ||
"bl - teen_center; interior", | ||
"br", | ||
"bt", | ||
"ca", | ||
"ch", | ||
"ci", | ||
"cl", | ||
"cn", | ||
"cp", | ||
"cs", | ||
"ct", | ||
"dh", | ||
"dy", | ||
"ea", | ||
"ep", | ||
"ew", | ||
"fe", | ||
"ft", | ||
"fw", | ||
"fx", | ||
"gd", | ||
"gd - teen_center; interior", | ||
"gk", | ||
"hb", | ||
"hb - teen_center; interior", | ||
"hd", | ||
"hf", | ||
"hg", | ||
"hk", | ||
"hl", | ||
"hp", | ||
"hs", | ||
"ht", | ||
"hu", | ||
"in", | ||
"jm", | ||
"jp", | ||
"kb", | ||
"kp", | ||
"lb", | ||
"lm", | ||
"ma - 40th_st_1", | ||
"ma - 40th_st_2", | ||
"ma - 42nd_st", | ||
"ma - 5th_ave", | ||
"ma - bartos; interior", | ||
"ma - gottesman; interior", | ||
"ma - retail; interior", | ||
"ma - social_sciences_library; interior", | ||
"ma - visitor_center; interior", | ||
"ma - wachenheim; interior", | ||
"mb", | ||
"mb - teen_center; interior", | ||
"me", | ||
"mh", | ||
"mh - teen_center; interior", | ||
"ml", | ||
"mn", | ||
"mo", | ||
"mp", | ||
"mr", | ||
"mu", | ||
"my", | ||
"nb", | ||
"nd", | ||
"ns", | ||
"ot", | ||
"pk", | ||
"pm", | ||
"pr", | ||
"rd", | ||
"ri", | ||
"rs", | ||
"rt", | ||
"sa", | ||
"sb", | ||
"sc", | ||
"sd", | ||
"se", | ||
"sg", | ||
"sg - teen_center; interior", | ||
"sn", | ||
"ss", | ||
"st", | ||
"sv", | ||
"tg", | ||
"th", | ||
"tm", | ||
"ts", | ||
"tv", | ||
"vc", | ||
"vn", | ||
"wb", | ||
"wf", | ||
"wh", | ||
"wk", | ||
"wl", | ||
"wo", | ||
"wt", | ||
"yv", | ||
] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
nypl-py-utils[mysql-client,postgresql-client,redshift-client,config-helper]==1.4.0 | ||
nypl-py-utils[mysql-client,postgresql-client,redshift-client,config-helper]==1.6.2 | ||
selenium>=4.10.0 |
112 changes: 112 additions & 0 deletions
112
tests/alarms/models/test_daily_location_visits_alarms.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import logging | ||
import pytest | ||
|
||
from alarms.models.daily_location_visits_alarms import DailyLocationVisitsAlarms | ||
from datetime import date | ||
|
||
|
||
class TestDailyLocationVisitsAlarms: | ||
@pytest.fixture | ||
def test_instance(self, mocker, monkeypatch): | ||
monkeypatch.setattr( | ||
"alarms.models.daily_location_visits_alarms.SHOPPERTRAK_SITES", | ||
set(["aa", "bb", "cc"]), | ||
) | ||
return DailyLocationVisitsAlarms(mocker.MagicMock()) | ||
|
||
def test_init(self, mocker): | ||
location_visits_alarms = DailyLocationVisitsAlarms(mocker.MagicMock()) | ||
assert location_visits_alarms.redshift_suffix == "_test_redshift_db" | ||
assert location_visits_alarms.run_added_tests | ||
assert location_visits_alarms.yesterday_date == date(2023, 5, 31) | ||
assert location_visits_alarms.yesterday == "2023-05-31" | ||
|
||
def test_run_checks_no_alarm(self, test_instance, mocker, caplog): | ||
mock_redshift_query = mocker.patch( | ||
"alarms.models.daily_location_visits_alarms.build_redshift_daily_location_visits_query", | ||
return_value="redshift query", | ||
) | ||
test_instance.redshift_client.execute_query.return_value = ( | ||
["aa", True], | ||
["bb", True], | ||
["cc", False], | ||
) | ||
|
||
with caplog.at_level(logging.ERROR): | ||
test_instance.run_checks() | ||
assert caplog.text == "" | ||
|
||
test_instance.redshift_client.connect.assert_called_once() | ||
mock_redshift_query.assert_called_once_with( | ||
"daily_location_visits_test_redshift_db", "2023-05-02" | ||
) | ||
test_instance.redshift_client.execute_query.assert_called_once_with( | ||
"redshift query" | ||
) | ||
test_instance.redshift_client.close_connection.assert_called_once() | ||
|
||
def test_run_checks_redshift_duplicate_sites_alarm( | ||
self, test_instance, mocker, caplog | ||
): | ||
mocker.patch( | ||
"alarms.models.daily_location_visits_alarms.build_redshift_daily_location_visits_query" | ||
) | ||
test_instance.redshift_client.execute_query.return_value = ( | ||
["aa", True], | ||
["bb", True], | ||
["bb", True], | ||
["cc", False], | ||
) | ||
|
||
with caplog.at_level(logging.ERROR): | ||
test_instance.run_checks() | ||
assert ("The following ShopperTrak sites are duplicated: ['bb']") in caplog.text | ||
|
||
def test_run_checks_redshift_missing_sites_alarm( | ||
self, test_instance, mocker, caplog | ||
): | ||
mocker.patch( | ||
"alarms.models.daily_location_visits_alarms.build_redshift_daily_location_visits_query" | ||
) | ||
test_instance.redshift_client.execute_query.return_value = ( | ||
["aa", True], | ||
["cc", True], | ||
) | ||
|
||
with caplog.at_level(logging.ERROR): | ||
test_instance.run_checks() | ||
assert "The following ShopperTrak sites are missing: ['bb']" in caplog.text | ||
|
||
def test_run_checks_redshift_extra_sites_alarm(self, test_instance, mocker, caplog): | ||
mocker.patch( | ||
"alarms.models.daily_location_visits_alarms.build_redshift_daily_location_visits_query" | ||
) | ||
test_instance.redshift_client.execute_query.return_value = ( | ||
["aa", True], | ||
["bb", True], | ||
["cc", False], | ||
["ee", True], | ||
["dd", False], | ||
) | ||
|
||
with caplog.at_level(logging.ERROR): | ||
test_instance.run_checks() | ||
assert ( | ||
"The following unknown ShopperTrak site ids were found: ['dd', 'ee']" | ||
) in caplog.text | ||
|
||
def test_run_checks_redshift_healthy_sites_alarm( | ||
self, test_instance, mocker, caplog | ||
): | ||
mocker.patch( | ||
"alarms.models.daily_location_visits_alarms.build_redshift_daily_location_visits_query" | ||
) | ||
test_instance.redshift_client.execute_query.return_value = ( | ||
["aa", True], | ||
["bb", False], | ||
["cc", False], | ||
) | ||
|
||
with caplog.at_level(logging.ERROR): | ||
test_instance.run_checks() | ||
assert "Only 33.33% of ShopperTrak sites were healthy" in caplog.text |