From 457d96b56c9979190b58e07bc1304ac53be49c4c Mon Sep 17 00:00:00 2001 From: George Burgess IV Date: Mon, 3 Jan 2022 16:00:24 -0800 Subject: pgo_tools: make monitor_pgo_profiles fail rather than emailing Prior to these changes, this script sends emails directly. These are... not as nice to work with as bugs. Since we run this through our new bug-filing cron bits, just make this script output to stdout/stderr & provide a meaningful exit code. Having bugs to track when these profiles are out-of-date is nicer than tracking N emails. BUG=None TEST=Unittests Change-Id: Id5f7838340df78006bddb36c3bc128016eb2acb5 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/3358469 Tested-by: George Burgess Auto-Submit: George Burgess Reviewed-by: Denis Nikitin Commit-Queue: Denis Nikitin --- pgo_tools/monitor_pgo_profiles.py | 70 ++++++++-------------------- pgo_tools/monitor_pgo_profiles_unittest.py | 74 +++++++++++++----------------- 2 files changed, 52 insertions(+), 92 deletions(-) diff --git a/pgo_tools/monitor_pgo_profiles.py b/pgo_tools/monitor_pgo_profiles.py index be159b94..5c17423b 100755 --- a/pgo_tools/monitor_pgo_profiles.py +++ b/pgo_tools/monitor_pgo_profiles.py @@ -7,14 +7,11 @@ import argparse import datetime -import sys -import subprocess import logging +import subprocess +import sys from typing import List, NamedTuple, Optional, Tuple -from cros_utils import email_sender -from cros_utils import tiny_render - PGO_BUILDBOT_LINK = ('https://ci.chromium.org/p/chromeos/builders/toolchain/' 'pgo-generate-llvm-next-orchestrator') @@ -54,47 +51,35 @@ def fetch_most_recent_profdata(arch: str) -> ProfdataInfo: return max(infos) -def compose_complaint_email( +def compose_complaint( out_of_date_profiles: List[Tuple[datetime.datetime, ProfdataInfo]] -) -> Optional[Tuple[str, tiny_render.Piece]]: +) -> Optional[str]: if not out_of_date_profiles: return None if len(out_of_date_profiles) == 1: - subject = '1 llvm profile is out of date' - body = ['out-of-date profile:'] + body_lines = ['1 profile is out of date:'] else: - subject = f'{len(out_of_date_profiles)} llvm profiles are out of date' - body = ['out-of-date profiles:'] + body_lines = [f'{len(out_of_date_profiles)} profiles are out of date:'] - out_of_date_items = [] for arch, profdata_info in out_of_date_profiles: - out_of_date_items.append( - f'{arch} (most recent profile was from {profdata_info.date} at ' + body_lines.append( + f'- {arch} (most recent profile was from {profdata_info.date} at ' f'{profdata_info.location!r})') - body += [ - tiny_render.UnorderedList(out_of_date_items), - tiny_render.line_break, - tiny_render.line_break, + body_lines.append('\n') + body_lines.append( 'PTAL to see if the llvm-pgo-generate bots are functioning normally. ' - 'Their status can be found at ', - tiny_render.Link(href=PGO_BUILDBOT_LINK, inner=PGO_BUILDBOT_LINK), - '.', - ] - return subject, body + f'Their status can be found at {PGO_BUILDBOT_LINK}.') + return '\n'.join(body_lines) def main() -> None: logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser( - description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument( - '--dry_run', - action='store_true', - help="Don't actually send an email", - ) + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( '--max_age_days', # These builders run ~weekly. If we fail to generate two in a row, @@ -119,29 +104,12 @@ def main() -> None: if age >= max_age: out_of_date_profiles.append((arch, most_recent)) - email = compose_complaint_email(out_of_date_profiles) - if not email: - logging.info('No email to send; quit') - return - - subject, body = email + complaint = compose_complaint(out_of_date_profiles) + if complaint: + logging.error('%s', complaint) + sys.exit(1) - identifier = 'llvm-pgo-monitor' - subject = f'[{identifier}] {subject}' - - logging.info('Sending email with title %r', subject) - if args.dry_run: - logging.info('Dry run specified\nSubject: %s\nBody:\n%s', subject, - tiny_render.render_text_pieces(body)) - else: - email_sender.EmailSender().SendX20Email( - subject=subject, - identifier=identifier, - well_known_recipients=['mage'], - direct_recipients=['gbiv@google.com'], - text_body=tiny_render.render_text_pieces(body), - html_body=tiny_render.render_html_pieces(body), - ) + logging.info('Nothing seems wrong') if __name__ == '__main__': diff --git a/pgo_tools/monitor_pgo_profiles_unittest.py b/pgo_tools/monitor_pgo_profiles_unittest.py index b4e085ec..eef33887 100755 --- a/pgo_tools/monitor_pgo_profiles_unittest.py +++ b/pgo_tools/monitor_pgo_profiles_unittest.py @@ -11,41 +11,36 @@ import unittest import unittest.mock import monitor_pgo_profiles -from cros_utils import tiny_render class Test(unittest.TestCase): """Tests for monitor_pgo_profiles.""" + def test_compose_complaint_with_zero_out_of_date(self): + self.assertIsNone(monitor_pgo_profiles.compose_complaint([])) - def test_compose_complaint_email_with_zero_out_of_date(self): - self.assertIsNone(monitor_pgo_profiles.compose_complaint_email([])) - - def test_compose_complaint_email_with_one_out_of_date(self): + def test_compose_complaint_with_one_out_of_date(self): profdata_info = monitor_pgo_profiles.ProfdataInfo( date=datetime.datetime(2020, 1, 2, 3, 4, 5), location='gs://somewhere', ) - result = monitor_pgo_profiles.compose_complaint_email([ + result = monitor_pgo_profiles.compose_complaint([ ('some_arch', profdata_info), ]) - self.assertEqual(result, ('1 llvm profile is out of date', [ - 'out-of-date profile:', - tiny_render.UnorderedList([ - f'some_arch (most recent profile was from {profdata_info.date} at ' - f'{profdata_info.location!r})' - ]), - tiny_render.line_break, - tiny_render.line_break, - 'PTAL to see if the llvm-pgo-generate bots are functioning normally. ' - 'Their status can be found at ', - tiny_render.Link( - href=monitor_pgo_profiles.PGO_BUILDBOT_LINK, - inner=monitor_pgo_profiles.PGO_BUILDBOT_LINK, - ), - '.', - ])) + self.assertEqual( + result, + '\n'.join(( + '1 profile is out of date:', + f'- some_arch (most recent profile was from {profdata_info.date} ' + f'at {profdata_info.location!r})', + '', + '', + 'PTAL to see if the llvm-pgo-generate bots are functioning ' + 'normally. Their status can be found at ' + f'{monitor_pgo_profiles.PGO_BUILDBOT_LINK}.', + )), + ) - def test_compose_complaint_email_with_two_out_of_date(self): + def test_compose_complaint_with_two_out_of_date(self): profdata_info_1 = monitor_pgo_profiles.ProfdataInfo( date=datetime.datetime(2020, 1, 2, 3, 4, 5), location='gs://somewhere', @@ -54,28 +49,25 @@ class Test(unittest.TestCase): date=datetime.datetime(2020, 3, 2, 1, 4, 5), location='gs://somewhere-else', ) - result = monitor_pgo_profiles.compose_complaint_email([ + result = monitor_pgo_profiles.compose_complaint([ ('some_arch', profdata_info_1), ('some_other_arch', profdata_info_2), ]) - self.assertEqual(result, ('2 llvm profiles are out of date', [ - 'out-of-date profiles:', - tiny_render.UnorderedList([ - f'some_arch (most recent profile was from {profdata_info_1.date} ' + self.assertEqual( + result, + '\n'.join(( + '2 profiles are out of date:', + f'- some_arch (most recent profile was from {profdata_info_1.date} ' f'at {profdata_info_1.location!r})', - f'some_other_arch (most recent profile was from ' - f'{profdata_info_2.date} at {profdata_info_2.location!r})' - ]), - tiny_render.line_break, - tiny_render.line_break, - 'PTAL to see if the llvm-pgo-generate bots are functioning normally. ' - 'Their status can be found at ', - tiny_render.Link( - href=monitor_pgo_profiles.PGO_BUILDBOT_LINK, - inner=monitor_pgo_profiles.PGO_BUILDBOT_LINK, - ), - '.', - ])) + f'- some_other_arch (most recent profile was from ' + f'{profdata_info_2.date} at {profdata_info_2.location!r})', + '', + '', + 'PTAL to see if the llvm-pgo-generate bots are functioning ' + 'normally. Their status can be found at ' + f'{monitor_pgo_profiles.PGO_BUILDBOT_LINK}.', + )), + ) @unittest.mock.patch.object(subprocess, 'run') def test_fetching_profdata_functions(self, subprocess_run_mock): -- cgit v1.2.3