def test_post_timeout_single(self): keen.project_id = "5004ded1163d66114f000000" api_key = "2e79c6ec1d0145be8891bf668599c79a" keen.write_key = scoped_keys.encrypt(api_key, {"allowed_operations": ["write"]}) client = KeenClient(keen.project_id, write_key=keen.write_key, read_key=None, post_timeout=0.0001) client.add_event("python_test", {"hello": "goodbye"})
def main(): print "[INFO] Getting raw spire data..." date = (datetime.today() - timedelta(days=DAYS_AGO)).strftime("%Y-%m-%d") # Breath breath_client = KeenClient( project_id=keen["breath"]["project_id"], read_key=keen["breath"]["read_key"], write_key=keen["breath"]["write_key"], ) if len(breath_client.extraction("sessions", timeframe="this_" + str(DAYS_AGO) + "_days")) > 0: print "[INFO] Already uploaded breath data for " + date + "." else: breaths = get_spire(spire["breath"], date) if len(breaths["data"]) > 0: print "[INFO] Uploading breath data..." keen_breaths = {} keen_breaths["breaths"] = [{"timestamp": b["timestamp"], "value": b["value"]} for b in breaths["data"]] keen_breaths["metadata"] = breaths["metadata"] keen_breaths["metadata"]["min"] = min([b["value"] for b in breaths["data"]]) keen_breaths["metadata"]["max"] = max([b["value"] for b in breaths["data"]]) keen_breaths["id"] = USER + date breath_client.add_event("sessions", keen_breaths) print "[INFO] Uploaded breath data for " + date + "." else: print "[INFO] No breath data found for " + date + "." # Steps steps_client = KeenClient( project_id=keen["steps"]["project_id"], read_key=keen["steps"]["read_key"], write_key=keen["steps"]["write_key"] ) if len(steps_client.extraction("sessions", timeframe="this_" + str(DAYS_AGO) + "_days")) > 0: print "[INFO] Already uploaded steps data for " + date + "." else: steps = get_spire(spire["step"], date) if len(steps["data"]) > 0: print "[INFO] Uploading steps data..." keen_steps = {} keen_steps["steps"] = [{"timestamp": s["timestamp"], "value": s["value"]} for s in steps["data"]] keen_steps["metadata"] = steps["metadata"] keen_steps["id"] = USER + date steps_client.add_event("sessions", keen_steps) print "[INFO] Uploaded steps data for " + date + "." else: print "[INFO] No steps data found for " + date + "."
class KeenEventService: def __init__(self): self.client = KeenClient( project_id=ENV["keen"]["project_id"], write_key=ENV["keen"]["write_key"], read_key=ENV["keen"]["read_key"], master_key=ENV["keen"]["master_key"], ) # # insert an event log # def insert_event(self, event_collection, event_log): try: self.client.add_event(event_collection, event_log) except Exception, e: log.exception(e)
class CustomJSONEncoderTests(BaseTestCase): def setUp(self): super(CustomJSONEncoderTests, self).setUp() api_key = "2e79c6ec1d0145be8891bf668599c79a" self.client = KeenClient(project_id='5004ded1163d66114f000000', write_key=scoped_keys.encrypt(api_key, {"allowed_operations": ["write"]}), read_key=scoped_keys.encrypt(api_key, {"allowed_operations": ["read"]}), json_encoder=CustomEncoder) def tearDown(self): self.client = None super(CustomJSONEncoderTests, self).tearDown() def test_custom_encoder_with_datetime_type(self): self.client.add_event("sign_ups", { "username": "******", "referred_by": "harry", "confirmed_at": datetime.datetime.utcnow() })
class AsyncKeenClient(object): def __init__(self): self._client = KeenClient( project_id=os.environ['KEEN_PROJECT_ID'], write_key=os.environ['KEEN_WRITE_KEY'], post_timeout=100 ) def add_event(self, collection, body): push = lambda: self._client.add_event(collection, body) IOLoop.current().spawn_callback(push)
def test_direct_persistence_strategy(self): project_id = "5004ded1163d66114f000000" api_key = "2e79c6ec1d0145be8891bf668599c79a" write_key = scoped_keys.encrypt(api_key, {"allowed_operations": ["write"]}) read_key = scoped_keys.encrypt(api_key, {"allowed_operations": ["read"]}) client = KeenClient(project_id, write_key=write_key, read_key=read_key) client.add_event("python_test", {"hello": "goodbye"}) client.add_event("python_test", {"hello": "goodbye"}) client.add_events( { "sign_ups": [{ "username": "******", "referred_by": "steve", "son_of": "my_mom" }], "purchases": [ {"price": 5}, {"price": 6}, {"price": 7} ]} )
def test_direct_persistence_strategy(self): project_id = "5004ded1163d66114f000000" api_key = "2e79c6ec1d0145be8891bf668599c79a" write_key = scoped_keys.encrypt(api_key, {"allowed_operations": ["write"]}) read_key = scoped_keys.encrypt(api_key, {"allowed_operations": ["read"]}) client = KeenClient(project_id, write_key=write_key, read_key=read_key) client.add_event("python_test", {"hello": "goodbye"}) client.add_event("python_test", {"hello": "goodbye"}) client.add_events({ "sign_ups": [{ "username": "******", "referred_by": "steve", "son_of": "my_mom" }], "purchases": [{ "price": 5 }, { "price": 6 }, { "price": 7 }] })
from keen.client import KeenClient import json client = KeenClient( project_id="50ba759d897a2c45c2000000", write_key= "72a1ad85456fd2361cfe8b65d240eab16b083caa944c11d9507761e536d34822eca4cefad12e482373ee41278953f98c6ff724b33b56fd5971e8d34cdd284cb6c3f202d9f13329e39c01eb9a35d1124cae81d9a4505992fce03be4030e32b19c72df266c55a18937f001e7158f6eac44", read_key= "f7a829ecc9e237949b0b97245c828661ff0c9f46eaec35a7dc4cfd3b4ef42804f5fc1859ecad05bd7d72b6c3a2e4047ae39cba86b5d51c770be26b0a406cbb44650d20fd05fb7896293f015cec3af3ca2df8a507927bf4cfed9275eb89e8dee855cf45db75b221074bda2f737d2810f2" ) headers = {"Accept": "text/event-stream"} messages = SSEClient('https://flickering-fire-322.firebaseio.com/.json', headers=headers) first = True for msg in messages: print msg.event print msg.data if not first and 'put' in msg.event: data = json.loads(msg.data) path = data['path'].split("/") device = path[1] timestamp = path[2] data = int(data['data']) event = {"device": device, "volume": data, "timestamp": timestamp} client.add_event("flow", event) first = False
import json client = KeenClient( project_id="50ba759d897a2c45c2000000", write_key="72a1ad85456fd2361cfe8b65d240eab16b083caa944c11d9507761e536d34822eca4cefad12e482373ee41278953f98c6ff724b33b56fd5971e8d34cdd284cb6c3f202d9f13329e39c01eb9a35d1124cae81d9a4505992fce03be4030e32b19c72df266c55a18937f001e7158f6eac44", read_key="f7a829ecc9e237949b0b97245c828661ff0c9f46eaec35a7dc4cfd3b4ef42804f5fc1859ecad05bd7d72b6c3a2e4047ae39cba86b5d51c770be26b0a406cbb44650d20fd05fb7896293f015cec3af3ca2df8a507927bf4cfed9275eb89e8dee855cf45db75b221074bda2f737d2810f2" ) headers = {"Accept": "text/event-stream"} messages = SSEClient('https://flickering-fire-322.firebaseio.com/.json', headers=headers) first = True for msg in messages: print msg.event print msg.data if not first and 'put' in msg.event: data = json.loads(msg.data) path = data['path'].split("/") device = path[1] timestamp = path[2] data = int(data['data']) event = { "device": device, "volume": data, "timestamp": timestamp } client.add_event("flow", event) first = False
def test_direct_persistence_strategy(self): project_id = "5004ded1163d66114f000000" auth_token = "2e79c6ec1d0145be8891bf668599c79a" client = KeenClient(project_id, auth_token) client.add_event("python_test", {"hello": "goodbye"})
# Clean up the bloomsky data bloomskyData[0]['Data'].pop('ImageURL', 0) bloomskyData[0]['Data'].pop('TS', 0) bloomskyData[0]['Data'].pop('ImageTS', 0) # Convert to Celsius and millibar # Also below I'm doing bunch of field name normalizations to conform # my naming standards with other IoTs that I have at home bloomskyData[0]['Data']['temperature'] = toCelsius( bloomskyData[0]['Data']['Temperature']) bloomskyData[0]['Data'].pop('Temperature') bloomskyData[0]['Data']['pressure'] = toMilliBar( bloomskyData[0]['Data']['Pressure']) bloomskyData[0]['Data'].pop('Pressure') bloomskyData[0]['Data']['humidity'] = bloomskyData[0]['Data'].pop('Humidity') bloomskyData[0]['Data']['agentName'] = agent_name bloomskyData[0]['Data']['timestamp'] = datetime.datetime.utcnow().strftime( "%FT%H:%M:%S.%fZ") bloomskyData[0]['Data']['day'] = not bloomskyData[0]['Data'].pop('Night') bloomskyData[0]['Data']['rain'] = bloomskyData[0]['Data'].pop('Rain') # Hoping that Electric Imp lux and BloomSky Luminance are similar :) bloomskyData[0]['Data']['lux'] = bloomskyData[0]['Data'].pop('Luminance') # Create the Keen.io client client = KeenClient(project_id=project_id, write_key=write_key, get_timeout=100) #print bloomskyData[0]['Data'] client.add_event(event_collector, bloomskyData[0]['Data'])
}, "weekend" : { "night": 8, "work": 10, "home": 10 } } def random_use(d): a = model[day(d)][hour(d)] b = random.randrange(int(a - 0.2 * a), int(a + 0.2 * a)) + random.random() return b - (0.1 * b) # <codecell> cur = start while cur < stop: use = random_use(cur) data = {"keen": {"timestamp": cur.isoformat()}, "device": "230c51eb6e4936ee", "volume": use} client.add_event("flow", data) cur = cur + one_hour # <codecell> stop.isoformat() # <codecell>
class Alerter: def __init__(self): logging.basicConfig() self.logger = logging.getLogger() self.logger.setLevel(logging.INFO) self.garage_data = anyconfig.load("garage_data.json")['garage_data'] self.sg = sendgrid.SendGridClient(SENDGRID_USERNAME, SENDGRID_PASSWORD) self.keen_client = None def __keen_client(self): if KEEN_CLIENT_ENABLED and self.keen_client == None: self.keen_client = KeenClient( project_id=KEEN_PROJECT_ID, write_key=KEEN_WRITE_KEY, read_key=KEEN_READ_KEY, base_url=KEEN_API_URL ) return self.keen_client def is_email(self, address): assert isinstance(address, str) return "@" in address def is_phone(self, address): assert isinstance(address, str) address = address.replace("-", "") pattern = re.compile("^[\dA-Z]{3}[\dA-Z]{3}[\dA-Z]{4}$", re.IGNORECASE) return pattern.match(address) is not None @newrelic.agent.background_task() def send_alert(self, address, garage): if self.is_email(address): self.send_email(address, garage) elif self.is_phone(address): self.send_txt(address, garage) self.clear_subs_for_user(address) @newrelic.agent.background_task() def send_email(self, address, garage): self.logger.info("send_email(): Sending email about {} to {}".format(garage, address)) message = sendgrid.Mail() message.add_to(address) message_text = "{} has a new spot open".format(garage) message.set_subject(message_text) message.set_text(message_text) #todo add how many spots are there message.set_from(SENDGRID_EMAIL_FROM) self.sg.send(message) @newrelic.agent.background_task() def send_txt(self, address, garage): self.logger.info("send_txt(): Sending txt about {} to {}".format(garage, address)) body = "{} has a new spot open".format(garage), EasySms.send_sms(to=address, body=body) @newrelic.agent.background_task() def find_changes(self): current = json.loads(self.redis_connection.hget("current", "data")) previous = json.loads(self.redis_connection.hget("previous", "data")) cur_stations = {} prev_stations = {} for garage in current.itervalues(): cur_stations.update(garage['stations']) for garage in previous.itervalues(): prev_stations.update(garage['stations']) stations_with_new_spots = [] for station_name in cur_stations.keys(): if cur_stations[station_name] > prev_stations[station_name]: stations_with_new_spots.append(station_name) all_changes = {} for station_name in cur_stations.keys(): if cur_stations[station_name] != prev_stations[station_name]: all_changes[station_name] = cur_stations[station_name] self.logger.info("find_changes(): all chargers changes: {}".format(all_changes)) if KEEN_CLIENT_ENABLED and all_changes > 0: self.logger.info("find_changes(): sending keen events: {}".format(all_changes)) self.keen_client.add_event("chargers", all_changes) self.logger.info("find_changes(): stations with new spots {}".format(stations_with_new_spots)) return stations_with_new_spots @newrelic.agent.background_task() def clear_subs_for_user(self, target): self.logger.info("clear_subs_for_user(): Clearing sub for user {}".format(target)) for key in self.redis_connection.keys("SUB-*"): if self.redis_connection.type(key) == "set": self.redis_connection.srem(key, target) self.logger.info("clear_subs_for_user(): Removing user {} from subscription to {}".format(target, key)) def find_garage(self, station): # station = PG3-STATION 26 for example # PG1 is Hilltop, PG2 is Central, PG3 is Creekside garages = ['Hilltop', 'Central', 'Creekside'] garage_array_index = int(station[2]) - 1 return garages[garage_array_index] @newrelic.agent.background_task() def main_loop(self): self.redis_connection = redis.StrictRedis.from_url(REDIS_URL) pubsub = self.redis_connection.pubsub() pubsub.subscribe(REDIS_CHANNEL) # todo add tests for item in pubsub.listen(): self.logger.info("alerter.main_loop(): Got a new alert. Processing ...") if item['type'] == "message": self.logger.info("alerter.main_loop(): received alert of new info with timstamp {}".format(item['data'])) for station in self.find_changes(): self.logger.info("alerter.main_loop(): Found new station {}...checking for subscriptions".format(station)) garage_name = self.find_garage(station) queue_name = "SUB-{}".format(garage_name) self.logger.info("alerter.main_loop(): Checking queue {} for members".format(queue_name)) queue_members = self.redis_connection.smembers(queue_name) if len(queue_members) == 0: self.logger.info("alerter.main_loop(): No notifications to send for garage {}".format(garage_name)) for target in queue_members: self.logger.info("alerter.main_loop(): Notifying {} for {} changes.".format(target, garage_name)) self.send_alert(target, garage_name) self.logger.info("alerter.main_loop(): done processing alert.")
class HireKeen: def __init__(self): self.keenWriter = KeenClient( project_id=config.KEEN_PROJECTID, write_key=config.KEEN_WRITEKEY, read_key=config.KEEN_READKEY ) def record_keen(self, index, event): self.keenWriter.add_event(index, event) def extract_keen(self, index, timeframe, filters): return self.keenWriter.extraction(index, timeframe, filters=filters) def pred_identify(self, user_id): self.identified = True self.predclient.identify(user_id) def pred_ranked(self, engine, data): return self.predclient.get_itemrank_ranked(engine, data) def pred_top_rec(self, engine, number): return self.predclient.get_itemrec_topn(engine, number) def pred_create(self, user, userType): self.predclient.create_user(user, {'userType': userType}) def event_record_register(self, loggedin_id): user_details = self.db_user.find_one({'linkedin_id': loggedin_id}) if user_details: event_data = { "action": "registration", "userId": user_details['linkedin_id'], "userCompanyId": user_details['linkedin_company_id'] } recordEvent.delay('siteActions', event_data) def event_record_activate(self, loggedin_id): user_details = self.db_user.find_one({'linkedin_id': loggedin_id}) if user_details: event_data = { "action": "activation", "userId": user_details['linkedin_id'], "userCompanyId": user_details['linkedin_company_id'] } recordEvent.delay('siteActions', event_data) def event_record_create_project(self, project_slug, user_id): project_details = self.db_project.find_one({'slug': project_slug, 'loggedin_id': user_id}) if project_details: try: user_details = self.db_user.find_one({'linkedin_id': project_details['loggedin_id']}) company_details = self.db_linkedincompany.find_one({'id': user_details['linkedin_company_id']}) event_data = { "action": "project creation", "userId": project_details['loggedin_id'], "userCompanyId": user_details['linkedin_company_id'], "slug": project_slug, "skills": [], "addlSkills": [], "userCompany": company_details['name'], "forCompanyId": project_details['companyId'], "forCompanyName": project_details['company'], "name": project_details['name'] } for skill in project_details['skills']: if skill['skill'] not in event_data['skills']: event_data['skills'].append(skill['skill']) for addlskill in project_details['addlSkills']: if addlskill not in event_data['addlSkills']: event_data['addlSkills'].append(addlskill) recordEvent.delay('siteActions', event_data) except: rollbar.report_exc_info() def event_record_create_position(self, project_slug, position_slug, user_id): position_details = self.db_position.find_one({'project': project_slug, 'slug': position_slug, 'loggedin_id': user_id}) if position_details: try: user_details = self.db_user.find_one({'linkedin_id': position_details['loggedin_id']}) company_details = self.db_linkedincompany.find_one({'id': user_details['linkedin_company_id']}) project_details = self.db_project.find_one({'slug': project_slug}) event_data = { "action": "position creation", "userId": user_details['linkedin_id'], "companyId": user_details['linkedin_company_id'], "slug": position_details['slug'], "projectslug": position_details['project'], "skills": [], "addlSkills": [], "userCompany": company_details['name'], "forCompanyId": project_details['companyId'], "forCompanyName": project_details['company'], "title": position_details['title'], "projectName": project_details['name'] } for skill in position_details['skills']: if skill['skill'] not in event_data['skills']: event_data['skills'].append(skill['skill']) for addlskill in position_details['addlSkills']: if addlskill not in event_data['addlSkills']: event_data['addlSkills'].append(addlskill) recordEvent.delay('siteActions', event_data) except: rollbar.report_exc_info() def event_record_resumesearch(self, position_slug, loggedin_id): resumesearch_details = self.db_searchlog.find_one({'slug': position_slug, 'loggedin_id': loggedin_id}) if resumesearch_details: try: user_details = self.db_user.find_one({'linkedin_id': loggedin_id}) company_details = self.db_linkedincompany.find_one({'id': user_details['linkedin_company_id']}) position_details = self.db_position.find_one({'loggedin_id': loggedin_id, 'slug': position_slug}) project_details = self.db_project.find_one({'slug': position_details['project']}) event_data = { "action": "resume search", "userId": loggedin_id, "companyId": user_details['linkedin_company_id'], "positionslug": position_slug, "projectslug": position_details['project'], "userCompany": company_details['name'], "forCompanyId": project_details['companyId'], "forCompanyName": project_details['company'], "title": position_details['title'], "projectName": project_details['name'], "results": resumesearch_details['results'], "site": resumesearch_details['site'] } recordEvent.delay('siteActions', event_data) except: rollbar.report_exc_info() def event_record_resumedownload(self, position_slug, loggedin_id, doc_id): download_details = self.db_positionexternalrel.find_one({'position_slug': position_slug, 'loggedin_id': loggedin_id, 'doc_id': doc_id}) if download_details: try: user_details = self.db_user.find_one({'linkedin_id': loggedin_id}) company_details = self.db_linkedincompany.find_one({'id': user_details['linkedin_company_id']}) position_details = self.db_position.find_one({'loggedin_id': loggedin_id, 'slug': position_slug}) project_details = self.db_project.find_one({'slug': position_details['project']}) event_data = { "action": "resume download", "userId": loggedin_id, "companyId": user_details['linkedin_company_id'], "positionslug": position_slug, "projectslug": position_details['project'], "userCompany": company_details['name'], "forCompanyId": project_details['companyId'], "forCompanyName": project_details['company'], "title": position_details['title'], "projectName": project_details['name'], "site": download_details['source'], "resumeid": doc_id } recordEvent.delay('siteActions', event_data) except: rollbar.report_exc_info()
} } def random_use(d): a = model[day(d)][hour(d)] b = random.randrange(int(a - 0.2 * a), int(a + 0.2 * a)) + random.random() return b - (0.1 * b) # <codecell> cur = start while cur < stop: use = random_use(cur) data = { "keen": { "timestamp": cur.isoformat() }, "device": "230c51eb6e4936ee", "volume": use } client.add_event("flow", data) cur = cur + one_hour # <codecell> stop.isoformat() # <codecell>
def test_direct_persistence_strategy(self): project_id = "5004ded1163d66114f000000" api_key = "2e79c6ec1d0145be8891bf668599c79a" write_key = scoped_keys.encrypt(api_key, {"allowed_operations": ["write"]}) client = KeenClient(project_id, write_key=write_key) client.add_event("python_test", {"hello": "goodbye"})
class Alerter: def __init__(self): logging.basicConfig() self.logger = logging.getLogger() self.logger.setLevel(logging.INFO) self.garage_data = anyconfig.load("garage_data.json")['garage_data'] self.sg = sendgrid.SendGridClient(SENDGRID_USERNAME, SENDGRID_PASSWORD) self.keen_client = None def __keen_client(self): if KEEN_CLIENT_ENABLED and self.keen_client == None: self.keen_client = KeenClient(project_id=KEEN_PROJECT_ID, write_key=KEEN_WRITE_KEY, read_key=KEEN_READ_KEY, base_url=KEEN_API_URL) return self.keen_client def is_email(self, address): assert isinstance(address, str) return "@" in address def is_phone(self, address): assert isinstance(address, str) address = address.replace("-", "") pattern = re.compile("^[\dA-Z]{3}[\dA-Z]{3}[\dA-Z]{4}$", re.IGNORECASE) return pattern.match(address) is not None @newrelic.agent.background_task() def send_alert(self, address, garage): if self.is_email(address): self.send_email(address, garage) elif self.is_phone(address): self.send_txt(address, garage) self.clear_subs_for_user(address) @newrelic.agent.background_task() def send_email(self, address, garage): self.logger.info("send_email(): Sending email about {} to {}".format( garage, address)) message = sendgrid.Mail() message.add_to(address) message_text = "{} has a new spot open".format(garage) message.set_subject(message_text) message.set_text(message_text) #todo add how many spots are there message.set_from(SENDGRID_EMAIL_FROM) self.sg.send(message) @newrelic.agent.background_task() def send_txt(self, address, garage): self.logger.info("send_txt(): Sending txt about {} to {}".format( garage, address)) body = "{} has a new spot open".format(garage), EasySms.send_sms(to=address, body=body) @newrelic.agent.background_task() def find_changes(self): current = json.loads(self.redis_connection.hget("current", "data")) previous = json.loads(self.redis_connection.hget("previous", "data")) cur_stations = {} prev_stations = {} for garage in current.itervalues(): cur_stations.update(garage['stations']) for garage in previous.itervalues(): prev_stations.update(garage['stations']) stations_with_new_spots = [] for station_name in cur_stations.keys(): if cur_stations[station_name] > prev_stations[station_name]: stations_with_new_spots.append(station_name) all_changes = {} for station_name in cur_stations.keys(): if cur_stations[station_name] != prev_stations[station_name]: all_changes[station_name] = cur_stations[station_name] self.logger.info( "find_changes(): all chargers changes: {}".format(all_changes)) if KEEN_CLIENT_ENABLED and all_changes > 0: self.logger.info( "find_changes(): sending keen events: {}".format(all_changes)) self.keen_client.add_event("chargers", all_changes) self.logger.info("find_changes(): stations with new spots {}".format( stations_with_new_spots)) return stations_with_new_spots @newrelic.agent.background_task() def clear_subs_for_user(self, target): self.logger.info( "clear_subs_for_user(): Clearing sub for user {}".format(target)) for key in self.redis_connection.keys("SUB-*"): if self.redis_connection.type(key) == "set": self.redis_connection.srem(key, target) self.logger.info( "clear_subs_for_user(): Removing user {} from subscription to {}" .format(target, key)) def find_garage(self, station): # station = PG3-STATION 26 for example # PG1 is Hilltop, PG2 is Central, PG3 is Creekside garages = ['Hilltop', 'Central', 'Creekside'] garage_array_index = int(station[2]) - 1 return garages[garage_array_index] @newrelic.agent.background_task() def main_loop(self): self.redis_connection = redis.StrictRedis.from_url(REDIS_URL) pubsub = self.redis_connection.pubsub() pubsub.subscribe(REDIS_CHANNEL) # todo add tests for item in pubsub.listen(): self.logger.info( "alerter.main_loop(): Got a new alert. Processing ...") if item['type'] == "message": self.logger.info( "alerter.main_loop(): received alert of new info with timstamp {}" .format(item['data'])) for station in self.find_changes(): self.logger.info( "alerter.main_loop(): Found new station {}...checking for subscriptions" .format(station)) garage_name = self.find_garage(station) queue_name = "SUB-{}".format(garage_name) self.logger.info( "alerter.main_loop(): Checking queue {} for members". format(queue_name)) queue_members = self.redis_connection.smembers(queue_name) if len(queue_members) == 0: self.logger.info( "alerter.main_loop(): No notifications to send for garage {}" .format(garage_name)) for target in queue_members: self.logger.info( "alerter.main_loop(): Notifying {} for {} changes." .format(target, garage_name)) self.send_alert(target, garage_name) self.logger.info("alerter.main_loop(): done processing alert.")