from argparse import ArgumentParser from itertools import chain from typing import Iterable from src.logic.neo4j import ( get_auto_followed_subaccounts, get_auto_followed_vendors, get_explicitly_followed_subaccounts, get_explicitly_followed_vendors, ) from src.utils.datadog import get_traces_url, get_logs_url from .base import BaseCommand class CheckSubscriptions(BaseCommand): # TODO: move to constants available_subscriptions_types: list[str] = [ "label_video_product_rejection", "label_video_product_approval", "label_release_approval", "label_spike_detector", "label_analytics_digest", "email_notification_rejection", "email_notification_new_release", ] description = "Get subscriptions from neo4j database and provide links to check events for subscribed vendors" def add_arguments(self, parser: ArgumentParser) -> None: parser.add_argument( "subscription_type", type=str, help="Subscription type to check", choices=self.available_subscriptions_types ) parser.add_argument( "-e", "--email", type=str, help="E-mail address of the user (identity)", required=True ) parser.add_argument( "-v", "--verbose", action="store_true", help="Display information about subscribed vendors", default=False ) parser.add_argument( "-t", "--trace", action="store_true", help="Generate trace urls instead of logs", default=False ) def run(self, *, email: str, subscription_type: str, verbose: bool, trace: bool) -> None: explicitly_followed_vendors = get_explicitly_followed_vendors(email, subscription_type) auto_followed_vendors = get_auto_followed_vendors(email, subscription_type) explicitly_followed_subaccounts = get_explicitly_followed_subaccounts(email, subscription_type) auto_followed_subaccounts = get_auto_followed_subaccounts(email, subscription_type) if not any( [ explicitly_followed_vendors, auto_followed_vendors, explicitly_followed_subaccounts, auto_followed_subaccounts, ] ): print("No subscriptions found") return vendor_ids: set[int] = set( row["vendor"]["vendorId"] for row in chain(auto_followed_vendors, explicitly_followed_vendors) ) subaccount_ids: set[int] = set( row["subaccount"]["id"] for row in chain(explicitly_followed_subaccounts, auto_followed_subaccounts) ) if verbose: self._print_vendor_subscription_info(subscription_type, explicitly_followed_vendors, auto_followed_vendors) self._print_subaccount_subscription_info( subscription_type, explicitly_followed_subaccounts, auto_followed_subaccounts ) print(f"User has followed {len(vendor_ids)} vendors in total") print(f"ids: {list(vendor_ids)}") print(f"User has followed {len(subaccount_ids)} subaccounts in total") print(f"ids: {list(subaccount_ids)}") if trace: events_url = self.get_swf_activity_detector_trace_url(vendor_ids, subaccount_ids, subscription_type) print(f"\nLink to check activity detector events for vendors and subaccounts: {events_url}\n") processing_url = self.get_ows_notifications_trace_url(vendor_ids, subaccount_ids, subscription_type) print(f"\nLink to check ows notifications cals for vendors and subaccounts: {processing_url}\n") emails_url = self.get_daemon_notifications_delivery_trace_url(vendor_ids, subaccount_ids, subscription_type) print(f"\nLink to check sent emails by notifications delivery for user: {emails_url}\n") else: logs_url = self.get_logs_url(vendor_ids, subaccount_ids, subscription_type) print(f"\nLink to check related logs: {logs_url}\n") def get_logs_url(self, vendor_ids: Iterable[int], subaccount_ids: Iterable[int], subscription_type: str) -> str: prefix = "resources." query = ( f"@environment:prod " f"@{prefix}feed_name:{subscription_type} " f"({self._get_feed_id_query(vendor_ids, subaccount_ids, prefix=prefix)})" ) return get_logs_url(query, cols=("service", f"@{prefix}feed_name", f"@{prefix}feed_id")) def get_swf_activity_detector_trace_url( self, vendor_ids: Iterable[int], subaccount_ids: Iterable[int], subscription_type: str ) -> str: query = ( f"env:prod service:swf-activity-detector " f"resource_name:task.{subscription_type} ({self._get_feed_id_query(vendor_ids, subaccount_ids)})" ) return get_traces_url(query) def get_ows_notifications_trace_url( self, vendor_ids: Iterable[int], subaccount_ids: Iterable[int], subscription_type: str ): prefix = "activity." query = ( f"env:prod service:ows-notifications " f"@{prefix}feed_name:{subscription_type} " f"({self._get_feed_id_query(vendor_ids, subaccount_ids, prefix=prefix)})" ) return get_traces_url(query, cols=("service", "resource_name", f"@{prefix}feed_name", f"@{prefix}feed_id")) def get_daemon_notifications_delivery_trace_url( self, vendor_ids: Iterable[int], subaccount_ids: Iterable[int], subscription_type: str ) -> str: query = ( f"env:prod service:daemon-notifications-delivery " f"@feed_name:{subscription_type} ({self._get_feed_id_query(vendor_ids, subaccount_ids)})" ) return get_traces_url(query, extra={"spanType": "all"}) @staticmethod def _get_feed_id_query(vendor_ids: Iterable[int], subaccount_ids: Iterable[int], *, prefix: str = "") -> str: vendors_str = [f"@{prefix}feed_id:vendor_{vendor_id}" for vendor_id in vendor_ids] subaccounts_str = [f"@{prefix}feed_id:subaccount_{subaccount_id}" for subaccount_id in subaccount_ids] return " OR ".join(chain(vendors_str, subaccounts_str)) @classmethod def _print_vendor_subscription_info( cls, subscription_type: str, explicitly_followed_vendors: list, auto_followed_vendors: list ): if explicitly_followed_vendors: print( f"\nUser should receive {subscription_type} e-mails for {len(explicitly_followed_vendors)}" f" vendors because they explicitly follow:" ) for row in explicitly_followed_vendors: cls._print_vendor_info(row) print() if auto_followed_vendors: print( f"\nUser should receive {subscription_type} e-mails for {len(auto_followed_vendors)}" f" vendors because they auto followed:" ) for row in auto_followed_vendors: cls._print_vendor_info(row) print() @classmethod def _print_subaccount_subscription_info( cls, subscription_type: str, explicitly_followed_subaccounts: list, auto_followed_subaccounts: list ): if explicitly_followed_subaccounts: print( f"\nUser should receive {subscription_type} e-mails for {len(explicitly_followed_subaccounts)}" f" vendors because they explicitly follow:" ) for row in explicitly_followed_subaccounts: cls._print_subaccount_info(row) print() if auto_followed_subaccounts: print( f"\nUser should receive {subscription_type} e-mails for {len(auto_followed_subaccounts)}" f" vendors because they auto followed:" ) for row in auto_followed_subaccounts: cls._print_subaccount_info(row) print() @staticmethod def _print_vendor_info(row): print( f'{"-" * 80}\n' f'profile id: {row["profile"]["profileId"]}\n' f'brand: {row["profile"]["brand"]}\n' f'vendor name: {row["vendor"]["name"]}\n' f'vendor id: {row["vendor"]["vendorId"]}' ) @staticmethod def _print_subaccount_info(row): print( f'{"-" * 80}\n' f'profile id: {row["profile"]["profileId"]}\n' f'brand: {row["profile"]["brand"]}\n' f'subaccount id: {row["subaccount"]["id"]}\n' f'subaccount name: {row["subaccount"]["name"]}' )