xref: /aosp_15_r20/external/aws-crt-java/codebuild/CanaryWrapper.py (revision 3c7ae9de214676c52d19f01067dc1a404272dc11)
1*3c7ae9deSAndroid Build Coastguard Worker# Python wrapper script for collecting Canary metrics, setting-up/tearing-down alarms, reporting metrics to Cloudwatch,
2*3c7ae9deSAndroid Build Coastguard Worker# checking the alarms to ensure everything is correct at the end of the run, and pushing the log to S3 if successful.
3*3c7ae9deSAndroid Build Coastguard Worker
4*3c7ae9deSAndroid Build Coastguard Worker# Needs to be installed prior to running
5*3c7ae9deSAndroid Build Coastguard Worker# Part of standard packages in Python 3.4+
6*3c7ae9deSAndroid Build Coastguard Workerimport argparse
7*3c7ae9deSAndroid Build Coastguard Workerimport time
8*3c7ae9deSAndroid Build Coastguard Workerimport datetime
9*3c7ae9deSAndroid Build Coastguard Worker# Dependencies in project folder
10*3c7ae9deSAndroid Build Coastguard Workerfrom CanaryWrapper_Classes import *
11*3c7ae9deSAndroid Build Coastguard Workerfrom CanaryWrapper_MetricFunctions import *
12*3c7ae9deSAndroid Build Coastguard Worker
13*3c7ae9deSAndroid Build Coastguard Worker# Code for command line argument parsing
14*3c7ae9deSAndroid Build Coastguard Worker# ================================================================================
15*3c7ae9deSAndroid Build Coastguard Workercommand_parser = argparse.ArgumentParser("CanaryWrapper")
16*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--canary_executable", type=str, required=True,
17*3c7ae9deSAndroid Build Coastguard Worker    help="The path to the canary executable (or program - like 'python3')")
18*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--canary_arguments", type=str, default="",
19*3c7ae9deSAndroid Build Coastguard Worker    help="The arguments to pass/launch the canary executable with")
20*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--git_hash", type=str, required=True,
21*3c7ae9deSAndroid Build Coastguard Worker    help="The Git commit hash that we are running the canary with")
22*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--git_repo_name", type=str, required=True,
23*3c7ae9deSAndroid Build Coastguard Worker    help="The name of the Git repository")
24*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--git_hash_as_namespace", type=bool, default=False,
25*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default=False) If true, the git hash will be used as the name of the Cloudwatch namespace")
26*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--output_log_filepath", type=str, default="output.log",
27*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default=output.log) The file to output log info to. Set to 'None' to disable")
28*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--output_to_console", type=bool, default=True,
29*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default=True) If true, info will be output to the console")
30*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--cloudwatch_region", type=str, default="us-east-1",
31*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default=us-east-1) The AWS region for Cloudwatch")
32*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--s3_bucket_name", type=str, default="canary-wrapper-folder",
33*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default=canary-wrapper-folder) The name of the S3 bucket where success logs will be stored")
34*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--snapshot_wait_time", type=int, default=600,
35*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default=600) The number of seconds between gathering and sending snapshot reports")
36*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--ticket_category", type=str, default="AWS",
37*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default=AWS) The category to register the ticket under")
38*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--ticket_type", type=str, default="SDKs and Tools",
39*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default='SDKs and Tools') The type to register the ticket under")
40*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--ticket_item", type=str, default="IoT SDK for CPP",
41*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default='IoT SDK for CPP') The item to register the ticket under")
42*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--ticket_group", type=str, default="AWS IoT Device SDK",
43*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default='AWS IoT Device SDK') The group to register the ticket under")
44*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--dependencies", type=str, default="",
45*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default='') Any dependencies and their commit hashes. \
46*3c7ae9deSAndroid Build Coastguard Worker        Current expected format is '(name or path);(hash);(next name or path);(hash);(etc...)'.")
47*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--lambda_name", type=str, default="iot-send-email-lambda",
48*3c7ae9deSAndroid Build Coastguard Worker    help="(OPTIONAL, default='CanarySendEmailLambda') The name of the Lambda used to send emails")
49*3c7ae9deSAndroid Build Coastguard Workercommand_parser.add_argument("--codebuild_log_path", type=str, default="",
50*3c7ae9deSAndroid Build Coastguard Worker    help="The CODEBUILD_LOG_PATH environment variable. Leave blank to ignore")
51*3c7ae9deSAndroid Build Coastguard Workercommand_parser_arguments = command_parser.parse_args()
52*3c7ae9deSAndroid Build Coastguard Worker
53*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.output_log_filepath == "None"):
54*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.output_log_filepath = None
55*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.snapshot_wait_time <= 0):
56*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.snapshot_wait_time = 60
57*3c7ae9deSAndroid Build Coastguard Worker
58*3c7ae9deSAndroid Build Coastguard Worker# Deal with possibly empty values in semi-critical commands/arguments
59*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.canary_executable == ""):
60*3c7ae9deSAndroid Build Coastguard Worker    print ("ERROR - required canary_executable is empty!", flush=True)
61*3c7ae9deSAndroid Build Coastguard Worker    exit (1) # cannot run without a canary executable
62*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.git_hash == ""):
63*3c7ae9deSAndroid Build Coastguard Worker    print ("ERROR - required git_hash is empty!", flush=True)
64*3c7ae9deSAndroid Build Coastguard Worker    exit (1) # cannot run without git hash
65*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.git_repo_name == ""):
66*3c7ae9deSAndroid Build Coastguard Worker    print ("ERROR - required git_repo_name is empty!", flush=True)
67*3c7ae9deSAndroid Build Coastguard Worker    exit (1) # cannot run without git repo name
68*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.git_hash_as_namespace is not True and command_parser_arguments.git_hash_as_namespace is not False):
69*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.git_hash_as_namespace = False
70*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.output_log_filepath == ""):
71*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.output_log_filepath = None
72*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.output_to_console != True and command_parser_arguments.output_to_console != False):
73*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.output_to_console = True
74*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.cloudwatch_region == ""):
75*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.cloudwatch_region = "us-east-1"
76*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.s3_bucket_name == ""):
77*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.s3_bucket_name = "canary-wrapper-folder"
78*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.ticket_category == ""):
79*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.ticket_category = "AWS"
80*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.ticket_type == ""):
81*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.ticket_type = "SDKs and Tools"
82*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.ticket_item == ""):
83*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.ticket_item = "IoT SDK for CPP"
84*3c7ae9deSAndroid Build Coastguard Workerif (command_parser_arguments.ticket_group == ""):
85*3c7ae9deSAndroid Build Coastguard Worker    command_parser_arguments.ticket_group = "AWS IoT Device SDK"
86*3c7ae9deSAndroid Build Coastguard Worker
87*3c7ae9deSAndroid Build Coastguard Worker
88*3c7ae9deSAndroid Build Coastguard Worker
89*3c7ae9deSAndroid Build Coastguard Worker# ================================================================================
90*3c7ae9deSAndroid Build Coastguard Worker
91*3c7ae9deSAndroid Build Coastguard Workerdatetime_now = datetime.datetime.now()
92*3c7ae9deSAndroid Build Coastguard Workerdatetime_string = datetime_now.strftime("%d-%m-%Y/%H-%M-%S")
93*3c7ae9deSAndroid Build Coastguard Workerprint("Datetime string is: " + datetime_string, flush=True)
94*3c7ae9deSAndroid Build Coastguard Worker
95*3c7ae9deSAndroid Build Coastguard Worker# Make the snapshot class
96*3c7ae9deSAndroid Build Coastguard Workerdata_snapshot = DataSnapshot(
97*3c7ae9deSAndroid Build Coastguard Worker    git_hash=command_parser_arguments.git_hash,
98*3c7ae9deSAndroid Build Coastguard Worker    git_repo_name=command_parser_arguments.git_repo_name,
99*3c7ae9deSAndroid Build Coastguard Worker    datetime_string=datetime_string,
100*3c7ae9deSAndroid Build Coastguard Worker    git_hash_as_namespace=command_parser_arguments.git_hash_as_namespace,
101*3c7ae9deSAndroid Build Coastguard Worker    git_fixed_namespace_text="mqtt5_canary",
102*3c7ae9deSAndroid Build Coastguard Worker    output_log_filepath="output.txt",
103*3c7ae9deSAndroid Build Coastguard Worker    output_to_console=command_parser_arguments.output_to_console,
104*3c7ae9deSAndroid Build Coastguard Worker    cloudwatch_region="us-east-1",
105*3c7ae9deSAndroid Build Coastguard Worker    cloudwatch_make_dashboard=False,
106*3c7ae9deSAndroid Build Coastguard Worker    cloudwatch_teardown_alarms_on_complete=True,
107*3c7ae9deSAndroid Build Coastguard Worker    cloudwatch_teardown_dashboard_on_complete=True,
108*3c7ae9deSAndroid Build Coastguard Worker    s3_bucket_name=command_parser_arguments.s3_bucket_name,
109*3c7ae9deSAndroid Build Coastguard Worker    s3_bucket_upload_on_complete=True,
110*3c7ae9deSAndroid Build Coastguard Worker    lambda_name=command_parser_arguments.lambda_name,
111*3c7ae9deSAndroid Build Coastguard Worker    metric_frequency=command_parser_arguments.snapshot_wait_time)
112*3c7ae9deSAndroid Build Coastguard Worker
113*3c7ae9deSAndroid Build Coastguard Worker# Make sure nothing failed
114*3c7ae9deSAndroid Build Coastguard Workerif (data_snapshot.abort_due_to_internal_error == True):
115*3c7ae9deSAndroid Build Coastguard Worker    print ("INFO - Stopping application due to error caused by credentials")
116*3c7ae9deSAndroid Build Coastguard Worker    print ("Please fix your credentials and then restart this application again", flush=True)
117*3c7ae9deSAndroid Build Coastguard Worker    exit(0)
118*3c7ae9deSAndroid Build Coastguard Worker
119*3c7ae9deSAndroid Build Coastguard Worker# Register metrics
120*3c7ae9deSAndroid Build Coastguard Workerdata_snapshot.register_metric(
121*3c7ae9deSAndroid Build Coastguard Worker    new_metric_name="total_cpu_usage",
122*3c7ae9deSAndroid Build Coastguard Worker    new_metric_function=get_metric_total_cpu_usage,
123*3c7ae9deSAndroid Build Coastguard Worker    new_metric_unit="Percent",
124*3c7ae9deSAndroid Build Coastguard Worker    new_metric_alarm_threshold=70,
125*3c7ae9deSAndroid Build Coastguard Worker    new_metric_reports_to_skip=1,
126*3c7ae9deSAndroid Build Coastguard Worker    new_metric_alarm_severity=5,
127*3c7ae9deSAndroid Build Coastguard Worker    is_percent=True)
128*3c7ae9deSAndroid Build Coastguard Workerdata_snapshot.register_metric(
129*3c7ae9deSAndroid Build Coastguard Worker    new_metric_name="total_memory_usage_value",
130*3c7ae9deSAndroid Build Coastguard Worker    new_metric_function=get_metric_total_memory_usage_value,
131*3c7ae9deSAndroid Build Coastguard Worker    new_metric_unit="Bytes")
132*3c7ae9deSAndroid Build Coastguard Workerdata_snapshot.register_metric(
133*3c7ae9deSAndroid Build Coastguard Worker    new_metric_name="total_memory_usage_percent",
134*3c7ae9deSAndroid Build Coastguard Worker    new_metric_function=get_metric_total_memory_usage_percent,
135*3c7ae9deSAndroid Build Coastguard Worker    new_metric_unit="Percent",
136*3c7ae9deSAndroid Build Coastguard Worker    new_metric_alarm_threshold=70,
137*3c7ae9deSAndroid Build Coastguard Worker    new_metric_reports_to_skip=0,
138*3c7ae9deSAndroid Build Coastguard Worker    new_metric_alarm_severity=5,
139*3c7ae9deSAndroid Build Coastguard Worker    is_percent=True)
140*3c7ae9deSAndroid Build Coastguard Worker
141*3c7ae9deSAndroid Build Coastguard Worker# Print diagnosis information
142*3c7ae9deSAndroid Build Coastguard Workerdata_snapshot.output_diagnosis_information(command_parser_arguments.dependencies)
143*3c7ae9deSAndroid Build Coastguard Worker
144*3c7ae9deSAndroid Build Coastguard Worker# Make the snapshot (metrics) monitor
145*3c7ae9deSAndroid Build Coastguard Workersnapshot_monitor = SnapshotMonitor(
146*3c7ae9deSAndroid Build Coastguard Worker    wrapper_data_snapshot=data_snapshot,
147*3c7ae9deSAndroid Build Coastguard Worker    wrapper_metrics_wait_time=command_parser_arguments.snapshot_wait_time)
148*3c7ae9deSAndroid Build Coastguard Worker
149*3c7ae9deSAndroid Build Coastguard Worker# Make sure nothing failed
150*3c7ae9deSAndroid Build Coastguard Workerif (snapshot_monitor.had_internal_error == True):
151*3c7ae9deSAndroid Build Coastguard Worker    print ("INFO - Stopping application due to error caused by credentials")
152*3c7ae9deSAndroid Build Coastguard Worker    print ("Please fix your credentials and then restart this application again", flush=True)
153*3c7ae9deSAndroid Build Coastguard Worker    exit(0)
154*3c7ae9deSAndroid Build Coastguard Worker
155*3c7ae9deSAndroid Build Coastguard Worker# Make the application monitor
156*3c7ae9deSAndroid Build Coastguard Workerapplication_monitor = ApplicationMonitor(
157*3c7ae9deSAndroid Build Coastguard Worker    wrapper_application_path=command_parser_arguments.canary_executable,
158*3c7ae9deSAndroid Build Coastguard Worker    wrapper_application_arguments=command_parser_arguments.canary_arguments,
159*3c7ae9deSAndroid Build Coastguard Worker    wrapper_application_restart_on_finish=False,
160*3c7ae9deSAndroid Build Coastguard Worker    data_snapshot=data_snapshot # pass the data_snapshot for printing to the log
161*3c7ae9deSAndroid Build Coastguard Worker)
162*3c7ae9deSAndroid Build Coastguard Worker
163*3c7ae9deSAndroid Build Coastguard Worker# Make sure nothing failed
164*3c7ae9deSAndroid Build Coastguard Workerif (application_monitor.error_has_occurred == True):
165*3c7ae9deSAndroid Build Coastguard Worker    print ("INFO - Stopping application due to error caused by credentials")
166*3c7ae9deSAndroid Build Coastguard Worker    print ("Please fix your credentials and then restart this application again", flush=True)
167*3c7ae9deSAndroid Build Coastguard Worker    exit(0)
168*3c7ae9deSAndroid Build Coastguard Worker
169*3c7ae9deSAndroid Build Coastguard Worker# For tracking if we stopped due to a metric alarm
170*3c7ae9deSAndroid Build Coastguard Workerstopped_due_to_metric_alarm = False
171*3c7ae9deSAndroid Build Coastguard Worker
172*3c7ae9deSAndroid Build Coastguard Workerexecution_sleep_time = 30
173*3c7ae9deSAndroid Build Coastguard Workerdef execution_loop():
174*3c7ae9deSAndroid Build Coastguard Worker    while True:
175*3c7ae9deSAndroid Build Coastguard Worker        snapshot_monitor.monitor_loop_function(
176*3c7ae9deSAndroid Build Coastguard Worker            time_passed=execution_sleep_time, psutil_process=application_monitor.application_process_psutil)
177*3c7ae9deSAndroid Build Coastguard Worker        application_monitor.monitor_loop_function(
178*3c7ae9deSAndroid Build Coastguard Worker            time_passed=execution_sleep_time)
179*3c7ae9deSAndroid Build Coastguard Worker
180*3c7ae9deSAndroid Build Coastguard Worker        # Did a metric go into alarm?
181*3c7ae9deSAndroid Build Coastguard Worker        if (snapshot_monitor.has_cut_ticket == True):
182*3c7ae9deSAndroid Build Coastguard Worker            # Set that we had an 'internal error' so we go down the right code path
183*3c7ae9deSAndroid Build Coastguard Worker            snapshot_monitor.had_internal_error = True
184*3c7ae9deSAndroid Build Coastguard Worker            break
185*3c7ae9deSAndroid Build Coastguard Worker
186*3c7ae9deSAndroid Build Coastguard Worker        # If an error has occurred or otherwise this thread needs to stop, then break the loop
187*3c7ae9deSAndroid Build Coastguard Worker        if (application_monitor.error_has_occurred == True or snapshot_monitor.had_internal_error == True):
188*3c7ae9deSAndroid Build Coastguard Worker            break
189*3c7ae9deSAndroid Build Coastguard Worker
190*3c7ae9deSAndroid Build Coastguard Worker        time.sleep(execution_sleep_time)
191*3c7ae9deSAndroid Build Coastguard Worker
192*3c7ae9deSAndroid Build Coastguard Worker
193*3c7ae9deSAndroid Build Coastguard Workerdef application_thread():
194*3c7ae9deSAndroid Build Coastguard Worker
195*3c7ae9deSAndroid Build Coastguard Worker    start_email_body = "MQTT5 Short Running Canary Wrapper has started for "
196*3c7ae9deSAndroid Build Coastguard Worker    start_email_body += "\"" + command_parser_arguments.git_repo_name + "\" commit \"" + command_parser_arguments.git_hash + "\""
197*3c7ae9deSAndroid Build Coastguard Worker    start_email_body += "\nThe wrapper will run for the length the MQTT5 Canary application is set to run for, which is determined by "
198*3c7ae9deSAndroid Build Coastguard Worker    start_email_body += "the arguments set. The arguments used for this run are listed below:"
199*3c7ae9deSAndroid Build Coastguard Worker    start_email_body += "\n  Arguments: " + command_parser_arguments.canary_arguments
200*3c7ae9deSAndroid Build Coastguard Worker    snapshot_monitor.send_email(email_body=start_email_body, email_subject_text_append="Started")
201*3c7ae9deSAndroid Build Coastguard Worker
202*3c7ae9deSAndroid Build Coastguard Worker    # Start the application going
203*3c7ae9deSAndroid Build Coastguard Worker    snapshot_monitor.start_monitoring()
204*3c7ae9deSAndroid Build Coastguard Worker    application_monitor.start_monitoring()
205*3c7ae9deSAndroid Build Coastguard Worker    # Allow the snapshot monitor to cut tickets
206*3c7ae9deSAndroid Build Coastguard Worker    snapshot_monitor.can_cut_ticket = True
207*3c7ae9deSAndroid Build Coastguard Worker
208*3c7ae9deSAndroid Build Coastguard Worker    # Start the execution loop
209*3c7ae9deSAndroid Build Coastguard Worker    execution_loop()
210*3c7ae9deSAndroid Build Coastguard Worker
211*3c7ae9deSAndroid Build Coastguard Worker    # Make sure everything is stopped
212*3c7ae9deSAndroid Build Coastguard Worker    snapshot_monitor.stop_monitoring()
213*3c7ae9deSAndroid Build Coastguard Worker    application_monitor.stop_monitoring()
214*3c7ae9deSAndroid Build Coastguard Worker
215*3c7ae9deSAndroid Build Coastguard Worker    # Track whether this counts as an error (and therefore we should cleanup accordingly) or not
216*3c7ae9deSAndroid Build Coastguard Worker    wrapper_error_occurred = False
217*3c7ae9deSAndroid Build Coastguard Worker    # Finished Email
218*3c7ae9deSAndroid Build Coastguard Worker    send_finished_email = True
219*3c7ae9deSAndroid Build Coastguard Worker    finished_email_body = "MQTT5 Short Running Canary Wrapper has stopped."
220*3c7ae9deSAndroid Build Coastguard Worker    finished_email_body += "\n\n"
221*3c7ae9deSAndroid Build Coastguard Worker
222*3c7ae9deSAndroid Build Coastguard Worker    try:
223*3c7ae9deSAndroid Build Coastguard Worker        # Find out why we stopped
224*3c7ae9deSAndroid Build Coastguard Worker        if (snapshot_monitor.had_internal_error == True):
225*3c7ae9deSAndroid Build Coastguard Worker            if (snapshot_monitor.has_cut_ticket == True):
226*3c7ae9deSAndroid Build Coastguard Worker                # We do not need to cut a ticket here - it's cut by the snapshot monitor!
227*3c7ae9deSAndroid Build Coastguard Worker                print ("ERROR - Snapshot monitor stopped due to metric in alarm!", flush=True)
228*3c7ae9deSAndroid Build Coastguard Worker                finished_email_body += "Failure due to required metrics being in alarm! A new ticket should have been cut!"
229*3c7ae9deSAndroid Build Coastguard Worker                finished_email_body += "\nMetrics in Alarm: " + str(snapshot_monitor.cloudwatch_current_alarms_triggered)
230*3c7ae9deSAndroid Build Coastguard Worker                wrapper_error_occurred = True
231*3c7ae9deSAndroid Build Coastguard Worker            else:
232*3c7ae9deSAndroid Build Coastguard Worker                print ("ERROR - Snapshot monitor stopped due to internal error!", flush=True)
233*3c7ae9deSAndroid Build Coastguard Worker                cut_ticket_using_cloudwatch(
234*3c7ae9deSAndroid Build Coastguard Worker                    git_repo_name=command_parser_arguments.git_repo_name,
235*3c7ae9deSAndroid Build Coastguard Worker                    git_hash=command_parser_arguments.git_hash,
236*3c7ae9deSAndroid Build Coastguard Worker                    git_hash_as_namespace=command_parser_arguments.git_hash_as_namespace,
237*3c7ae9deSAndroid Build Coastguard Worker                    git_fixed_namespace_text="mqtt5_canary",
238*3c7ae9deSAndroid Build Coastguard Worker                    cloudwatch_region="us-east-1",
239*3c7ae9deSAndroid Build Coastguard Worker                    ticket_description="Snapshot monitor stopped due to internal error! Reason info: " + snapshot_monitor.internal_error_reason,
240*3c7ae9deSAndroid Build Coastguard Worker                    ticket_reason="Snapshot monitor stopped due to internal error",
241*3c7ae9deSAndroid Build Coastguard Worker                    ticket_allow_duplicates=True,
242*3c7ae9deSAndroid Build Coastguard Worker                    ticket_category=command_parser_arguments.ticket_category,
243*3c7ae9deSAndroid Build Coastguard Worker                    ticket_item=command_parser_arguments.ticket_item,
244*3c7ae9deSAndroid Build Coastguard Worker                    ticket_group=command_parser_arguments.ticket_group,
245*3c7ae9deSAndroid Build Coastguard Worker                    ticket_type=command_parser_arguments.ticket_type,
246*3c7ae9deSAndroid Build Coastguard Worker                    ticket_severity=4)
247*3c7ae9deSAndroid Build Coastguard Worker                wrapper_error_occurred = True
248*3c7ae9deSAndroid Build Coastguard Worker                finished_email_body += "Failure due to Snapshot monitor stopping due to an internal error."
249*3c7ae9deSAndroid Build Coastguard Worker                finished_email_body += " Reason given for error: " + snapshot_monitor.internal_error_reason
250*3c7ae9deSAndroid Build Coastguard Worker
251*3c7ae9deSAndroid Build Coastguard Worker        elif (application_monitor.error_has_occurred == True):
252*3c7ae9deSAndroid Build Coastguard Worker            if (application_monitor.error_due_to_credentials == True):
253*3c7ae9deSAndroid Build Coastguard Worker                print ("INFO - Stopping application due to error caused by credentials")
254*3c7ae9deSAndroid Build Coastguard Worker                print ("Please fix your credentials and then restart this application again", flush=True)
255*3c7ae9deSAndroid Build Coastguard Worker                wrapper_error_occurred = True
256*3c7ae9deSAndroid Build Coastguard Worker                send_finished_email = False
257*3c7ae9deSAndroid Build Coastguard Worker            else:
258*3c7ae9deSAndroid Build Coastguard Worker                # Is the error something in the canary failed?
259*3c7ae9deSAndroid Build Coastguard Worker                if (application_monitor.error_code != 0):
260*3c7ae9deSAndroid Build Coastguard Worker                    cut_ticket_using_cloudwatch(
261*3c7ae9deSAndroid Build Coastguard Worker                        git_repo_name=command_parser_arguments.git_repo_name,
262*3c7ae9deSAndroid Build Coastguard Worker                        git_hash=command_parser_arguments.git_hash,
263*3c7ae9deSAndroid Build Coastguard Worker                        git_hash_as_namespace=command_parser_arguments.git_hash_as_namespace,
264*3c7ae9deSAndroid Build Coastguard Worker                        git_fixed_namespace_text="mqtt5_canary",
265*3c7ae9deSAndroid Build Coastguard Worker                        cloudwatch_region="us-east-1",
266*3c7ae9deSAndroid Build Coastguard Worker                        ticket_description="The Short Running Canary exited with a non-zero exit code! This likely means something in the canary failed.",
267*3c7ae9deSAndroid Build Coastguard Worker                        ticket_reason="The Short Running Canary exited with a non-zero exit code",
268*3c7ae9deSAndroid Build Coastguard Worker                        ticket_allow_duplicates=True,
269*3c7ae9deSAndroid Build Coastguard Worker                        ticket_category=command_parser_arguments.ticket_category,
270*3c7ae9deSAndroid Build Coastguard Worker                        ticket_item=command_parser_arguments.ticket_item,
271*3c7ae9deSAndroid Build Coastguard Worker                        ticket_group=command_parser_arguments.ticket_group,
272*3c7ae9deSAndroid Build Coastguard Worker                        ticket_type=command_parser_arguments.ticket_type,
273*3c7ae9deSAndroid Build Coastguard Worker                        ticket_severity=4)
274*3c7ae9deSAndroid Build Coastguard Worker                    wrapper_error_occurred = True
275*3c7ae9deSAndroid Build Coastguard Worker                    finished_email_body += "Failure due to MQTT5 application exiting with a non-zero exit code! This means something in the Canary application itself failed"
276*3c7ae9deSAndroid Build Coastguard Worker                else:
277*3c7ae9deSAndroid Build Coastguard Worker                    print ("INFO - Stopping application. No error has occurred, application has stopped normally", flush=True)
278*3c7ae9deSAndroid Build Coastguard Worker                    application_monitor.print_stdout()
279*3c7ae9deSAndroid Build Coastguard Worker                    finished_email_body += "Short Running Canary finished successfully and run without errors!"
280*3c7ae9deSAndroid Build Coastguard Worker                    wrapper_error_occurred = False
281*3c7ae9deSAndroid Build Coastguard Worker        else:
282*3c7ae9deSAndroid Build Coastguard Worker            print ("ERROR - Short Running Canary stopped due to unknown reason!", flush=True)
283*3c7ae9deSAndroid Build Coastguard Worker            cut_ticket_using_cloudwatch(
284*3c7ae9deSAndroid Build Coastguard Worker                git_repo_name=command_parser_arguments.git_repo_name,
285*3c7ae9deSAndroid Build Coastguard Worker                git_hash=command_parser_arguments.git_hash,
286*3c7ae9deSAndroid Build Coastguard Worker                git_hash_as_namespace=command_parser_arguments.git_hash_as_namespace,
287*3c7ae9deSAndroid Build Coastguard Worker                git_fixed_namespace_text="mqtt5_canary",
288*3c7ae9deSAndroid Build Coastguard Worker                cloudwatch_region="us-east-1",
289*3c7ae9deSAndroid Build Coastguard Worker                ticket_description="The Short Running Canary stopped for an unknown reason!",
290*3c7ae9deSAndroid Build Coastguard Worker                ticket_reason="The Short Running Canary stopped for unknown reason",
291*3c7ae9deSAndroid Build Coastguard Worker                ticket_allow_duplicates=True,
292*3c7ae9deSAndroid Build Coastguard Worker                ticket_category=command_parser_arguments.ticket_category,
293*3c7ae9deSAndroid Build Coastguard Worker                ticket_item=command_parser_arguments.ticket_item,
294*3c7ae9deSAndroid Build Coastguard Worker                ticket_group=command_parser_arguments.ticket_group,
295*3c7ae9deSAndroid Build Coastguard Worker                ticket_type=command_parser_arguments.ticket_type,
296*3c7ae9deSAndroid Build Coastguard Worker                ticket_severity=4)
297*3c7ae9deSAndroid Build Coastguard Worker            wrapper_error_occurred = True
298*3c7ae9deSAndroid Build Coastguard Worker            finished_email_body += "Failure due to unknown reason! This shouldn't happen and means something has gone wrong!"
299*3c7ae9deSAndroid Build Coastguard Worker    except Exception as e:
300*3c7ae9deSAndroid Build Coastguard Worker        print ("ERROR: Could not (possibly) cut ticket due to exception!")
301*3c7ae9deSAndroid Build Coastguard Worker        print ("Exception: " + str(e), flush=True)
302*3c7ae9deSAndroid Build Coastguard Worker
303*3c7ae9deSAndroid Build Coastguard Worker    # Clean everything up and stop
304*3c7ae9deSAndroid Build Coastguard Worker    snapshot_monitor.cleanup_monitor(error_occurred=wrapper_error_occurred)
305*3c7ae9deSAndroid Build Coastguard Worker    application_monitor.cleanup_monitor(error_occurred=wrapper_error_occurred)
306*3c7ae9deSAndroid Build Coastguard Worker    print ("Short Running Canary finished!", flush=True)
307*3c7ae9deSAndroid Build Coastguard Worker
308*3c7ae9deSAndroid Build Coastguard Worker    finished_email_body += "\n\nYou can find the log file for this run at the following S3 location: "
309*3c7ae9deSAndroid Build Coastguard Worker    finished_email_body += "https://s3.console.aws.amazon.com/s3/object/"
310*3c7ae9deSAndroid Build Coastguard Worker    finished_email_body += command_parser_arguments.s3_bucket_name
311*3c7ae9deSAndroid Build Coastguard Worker    finished_email_body += "?region=" + command_parser_arguments.cloudwatch_region
312*3c7ae9deSAndroid Build Coastguard Worker    finished_email_body += "&prefix=" + command_parser_arguments.git_repo_name + "/" + datetime_string + "/"
313*3c7ae9deSAndroid Build Coastguard Worker    if (wrapper_error_occurred == True):
314*3c7ae9deSAndroid Build Coastguard Worker        finished_email_body += "Failed_Logs/"
315*3c7ae9deSAndroid Build Coastguard Worker    finished_email_body += command_parser_arguments.git_hash + ".log"
316*3c7ae9deSAndroid Build Coastguard Worker    if (command_parser_arguments.codebuild_log_path != ""):
317*3c7ae9deSAndroid Build Coastguard Worker        print ("\n Codebuild log path: " + command_parser_arguments.codebuild_log_path + "\n")
318*3c7ae9deSAndroid Build Coastguard Worker
319*3c7ae9deSAndroid Build Coastguard Worker    # Send the finish email
320*3c7ae9deSAndroid Build Coastguard Worker    if (send_finished_email == True):
321*3c7ae9deSAndroid Build Coastguard Worker        if (wrapper_error_occurred == True):
322*3c7ae9deSAndroid Build Coastguard Worker            snapshot_monitor.send_email(email_body=finished_email_body, email_subject_text_append="Had an error")
323*3c7ae9deSAndroid Build Coastguard Worker        else:
324*3c7ae9deSAndroid Build Coastguard Worker            snapshot_monitor.send_email(email_body=finished_email_body, email_subject_text_append="Finished")
325*3c7ae9deSAndroid Build Coastguard Worker
326*3c7ae9deSAndroid Build Coastguard Worker    exit (application_monitor.error_code)
327*3c7ae9deSAndroid Build Coastguard Worker
328*3c7ae9deSAndroid Build Coastguard Worker
329*3c7ae9deSAndroid Build Coastguard Worker# Start the application!
330*3c7ae9deSAndroid Build Coastguard Workerapplication_thread()
331