Bug 1702410 - Reflect backfill bot' s new name in logs

* rename backfill bot' s packages to Sherlock
* slight logs adjustments to Sherlock
* replace 'Perfsheriff bot' prefix with 'Sherlock'
* adjust comment referring to Sherlock
* rename SecretaryTool to Secretary
This commit is contained in:
ionutgoldan 2021-04-05 16:27:38 +03:00 коммит произвёл GitHub
Родитель b2dc38e2a8
Коммит a7e1f79283
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
34 изменённых файлов: 132 добавлений и 147 удалений

Просмотреть файл

@ -1,6 +1,6 @@
{
"title": "PerfSheriffBot's schema for storing logs",
"description": "Used to store the outcome of PerfSheriffBot actions (i.e. backfill, retrigger)",
"title": "Sherlock' schema for storing logs",
"description": "Used to store the outcome of Sherlock' s actions (i.e. backfill, retrigger)",
"type": "object",
"properties": {
"action": {

Просмотреть файл

@ -1,13 +1,15 @@
from copy import copy, deepcopy
from datetime import datetime, timedelta
from unittest.mock import MagicMock
import pytest
import simplejson as json
import taskcluster
from freezegun import freeze_time
from tests.conftest import SampleDataJSONLoader, create_perf_signature, create_perf_alert
from treeherder.model.models import MachinePlatform, Job
from treeherder.perf.auto_perf_sheriffing.secretary_tool import SecretaryTool
from treeherder.perf.auto_perf_sherrifing.secretary import Secretary
from treeherder.perf.models import (
BackfillReport,
BackfillRecord,
@ -16,10 +18,11 @@ from treeherder.perf.models import (
PerformanceAlert,
)
# For testing PerfSheriffBot
# For testing Sherlock
from treeherder.services.taskcluster import notify_client_factory
from treeherder.utils import default_serializer
load_json_fixture = SampleDataJSONLoader('perf_sheriff_bot')
load_json_fixture = SampleDataJSONLoader('sherlock')
@pytest.fixture(scope="module")
@ -116,11 +119,11 @@ def backfill_tool_mock():
@pytest.fixture
def secretary():
return SecretaryTool()
return Secretary()
@pytest.fixture
def sheriff_settings(secretary, db):
def sherlock_settings(secretary, db):
secretary.validate_settings()
return PerformanceSettings.objects.get(name='perf_sheriff_bot')
@ -133,7 +136,7 @@ def empty_sheriff_settings(secretary):
return PerformanceSettings.objects.get(name='perf_sheriff_bot')
# For testing SecretaryTool
# For testing Secretary
@pytest.fixture
def performance_settings(db):
settings = {
@ -165,3 +168,20 @@ def create_record():
return BackfillRecord.objects.create(alert=alert, report=report)
return _create_record
@pytest.fixture
def notify_client_mock() -> taskcluster.Notify:
return MagicMock(
spec=notify_client_factory('https://fakerooturl.org', 'FAKE_CLIENT_ID', 'FAKE_ACCESS_TOKEN')
)
@pytest.fixture
def job_from_try(eleven_job_blobs, create_jobs):
job_blob = eleven_job_blobs[0]
job = create_jobs([job_blob])[0]
job.repository.is_try_repo = True
job.repository.save()
return job

Просмотреть файл

@ -8,7 +8,7 @@ import pytest
from tests.conftest import create_perf_alert
from treeherder.model.models import Job, Option, OptionCollection, MachinePlatform
from treeherder.perf.auto_perf_sheriffing.backfill_reports import AlertsPicker
from treeherder.perf.auto_perf_sherrifing.backfill_reports import AlertsPicker
from treeherder.perf.models import PerformanceAlert, PerformanceDatum, PerformanceSignature
# For testing BackfillReportMaintainer

Просмотреть файл

@ -3,7 +3,7 @@ from unittest.mock import Mock
import pytest
from treeherder.perf.auto_perf_sheriffing.backfill_reports import AlertsPicker
from treeherder.perf.auto_perf_sherrifing.backfill_reports import AlertsPicker
def test_init():

Просмотреть файл

@ -1,7 +1,7 @@
import datetime
from typing import Tuple
from treeherder.perf.auto_perf_sheriffing.backfill_reports import (
from treeherder.perf.auto_perf_sherrifing.backfill_reports import (
BackfillReportMaintainer,
)
from treeherder.perf.models import (

Просмотреть файл

@ -5,7 +5,7 @@ from operator import itemgetter as get_key
import pytest
from .conftest import NON_RETRIGGERABLE_JOB_ID, ONE_DAY_INTERVAL
from treeherder.perf.auto_perf_sheriffing.backfill_reports import IdentifyAlertRetriggerables
from treeherder.perf.auto_perf_sherrifing.backfill_reports import IdentifyAlertRetriggerables
# Unit tests

Просмотреть файл

@ -1,6 +1,6 @@
import pytest
from treeherder.perf.auto_perf_sheriffing.backfill_tool import BackfillTool
from treeherder.perf.auto_perf_sherrifing.backfill_tool import BackfillTool
from treeherder.perf.exceptions import CannotBackfill
from treeherder.services.taskcluster import TaskclusterModelProxy

Просмотреть файл

@ -7,10 +7,10 @@ import simplejson as json
from django.db.models import Q
from treeherder.config.settings import IS_WINDOWS
from treeherder.perf.auto_perf_sheriffing.secretary_tool import SecretaryTool
from treeherder.perf.auto_perf_sherrifing.secretary import Secretary
from treeherder.model.models import Job, Push
from treeherder.perf.models import BackfillRecord, BackfillReport, PerformanceSettings
from treeherder.perf.auto_perf_sheriffing.outcome_checker import OutcomeChecker, OutcomeStatus
from treeherder.perf.auto_perf_sherrifing.outcome_checker import OutcomeChecker, OutcomeStatus
# we're testing against this (automatically provided by fixtures)
JOB_TYPE_ID = 1
@ -125,7 +125,7 @@ def get_outcome_checker_mock():
@pytest.mark.skipif(IS_WINDOWS, reason="datetime logic does not work when OS not on GMT")
def test_secretary_tool_updates_only_matured_reports(
def test_secretary_updates_only_matured_reports(
test_perf_alert, create_record, record_from_mature_report
):
# create new report with records
@ -134,36 +134,36 @@ def test_secretary_tool_updates_only_matured_reports(
assert BackfillRecord.objects.count() == 2
assert BackfillRecord.objects.filter(status=BackfillRecord.PRELIMINARY).count() == 2
SecretaryTool.mark_reports_for_backfill()
Secretary.mark_reports_for_backfill()
assert BackfillRecord.objects.filter(status=BackfillRecord.PRELIMINARY).count() == 1
def test_secretary_tool_uses_existing_settings(performance_settings):
def test_secretary_uses_existing_settings(performance_settings):
assert PerformanceSettings.objects.count() == 1
last_reset_date_before = json.loads(performance_settings.settings)["last_reset_date"]
SecretaryTool.validate_settings()
Secretary.validate_settings()
assert PerformanceSettings.objects.count() == 1
settings_after = PerformanceSettings.objects.filter(name="perf_sheriff_bot").first()
assert json.loads(settings_after.settings)["last_reset_date"] == last_reset_date_before
def test_secretary_tool_resets_settings_if_expired(expired_performance_settings):
def test_secretary_resets_settings_if_expired(expired_performance_settings):
assert PerformanceSettings.objects.count() == 1
expired_last_reset_date = json.loads(expired_performance_settings.settings)["last_reset_date"]
SecretaryTool.validate_settings()
Secretary.validate_settings()
assert PerformanceSettings.objects.count() == 1
settings_after = PerformanceSettings.objects.filter(name="perf_sheriff_bot").first()
assert json.loads(settings_after.settings)["last_reset_date"] != expired_last_reset_date
def test_secretary_tool_creates_new_settings_if_none_exist(db):
def test_secretary_creates_new_settings_if_none_exist(db):
assert PerformanceSettings.objects.count() == 0
SecretaryTool.validate_settings()
Secretary.validate_settings()
assert PerformanceSettings.objects.count() == 1
@ -201,7 +201,7 @@ def test_outcome_checker_identifies_pushes_in_range(
def test_check_outcome_after_success(get_outcome_checker_mock, record_backfilled):
outcome_checker_mock = get_outcome_checker_mock(OutcomeStatus.SUCCESSFUL)
secretary = SecretaryTool(outcome_checker_mock)
secretary = Secretary(outcome_checker_mock)
assert BackfillRecord.objects.filter(status=BackfillRecord.BACKFILLED).count() == 1
assert BackfillRecord.objects.filter(status=BackfillRecord.SUCCESSFUL).count() == 0
@ -212,7 +212,7 @@ def test_check_outcome_after_success(get_outcome_checker_mock, record_backfilled
def test_check_outcome_after_fail(get_outcome_checker_mock, record_backfilled):
outcome_checker_mock = get_outcome_checker_mock(OutcomeStatus.FAILED)
secretary = SecretaryTool(outcome_checker_mock)
secretary = Secretary(outcome_checker_mock)
assert BackfillRecord.objects.filter(status=BackfillRecord.BACKFILLED).count() == 1
assert BackfillRecord.objects.filter(status=BackfillRecord.FAILED).count() == 0
@ -223,7 +223,7 @@ def test_check_outcome_after_fail(get_outcome_checker_mock, record_backfilled):
def test_no_action_when_in_progress(get_outcome_checker_mock, record_backfilled):
outcome_checker_mock = get_outcome_checker_mock(OutcomeStatus.IN_PROGRESS)
secretary = SecretaryTool(outcome_checker_mock)
secretary = Secretary(outcome_checker_mock)
assert BackfillRecord.objects.filter(status=BackfillRecord.BACKFILLED).count() == 1
secretary.check_outcome()

Просмотреть файл

@ -6,7 +6,7 @@ import pytest
from django.db import models
from treeherder.model.models import Job, Push
from treeherder.perf.auto_perf_sheriffing.perf_sheriff_bot import PerfSheriffBot
from treeherder.perf.auto_perf_sherrifing.sherlock import Sherlock
from treeherder.perf.email import BackfillNotificationWriter
from treeherder.perf.exceptions import MaxRuntimeExceeded
from treeherder.perf.models import BackfillRecord, BackfillReport
@ -33,18 +33,18 @@ class TestEmailIntegration:
backfill_tool_mock,
secretary,
record_ready_for_processing,
sheriff_settings,
sherlock_settings,
notify_client_mock,
):
sheriff_bot = PerfSheriffBot(
sherlock = Sherlock(
report_maintainer_mock,
backfill_tool_mock,
secretary,
notify_client_mock,
email_writer=self.email_writer_mock(),
)
sheriff_bot.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
sherlock.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
record_ready_for_processing.refresh_from_db()
assert notify_client_mock.email.call_count == 1
@ -55,7 +55,7 @@ class TestEmailIntegration:
backfill_tool_mock,
secretary,
record_ready_for_processing,
sheriff_settings,
sherlock_settings,
notify_client_mock,
broken_context_str,
# Note: parametrizes the test
@ -63,13 +63,13 @@ class TestEmailIntegration:
record_ready_for_processing.context = broken_context_str
record_ready_for_processing.save()
sheriff_bot = PerfSheriffBot(
sherlock = Sherlock(
report_maintainer_mock,
backfill_tool_mock,
secretary,
notify_client_mock,
)
sheriff_bot.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
sherlock.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
assert notify_client_mock.email.call_count == 1
@ -79,18 +79,16 @@ class TestEmailIntegration:
backfill_tool_mock,
secretary,
record_ready_for_processing,
sheriff_settings,
sherlock_settings,
notify_client_mock,
):
no_time_left = timedelta(seconds=0)
sheriff_bot = PerfSheriffBot(
sherlock = Sherlock(
report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock, no_time_left
)
try:
sheriff_bot.sheriff(
since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland']
)
sherlock.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
except MaxRuntimeExceeded:
pass
@ -108,7 +106,7 @@ def test_records_change_to_ready_for_processing(
report_maintainer_mock,
backfill_tool_mock,
secretary,
sheriff_settings,
sherlock_settings,
notify_client_mock,
):
# create new report with records - the report will not be mature
@ -121,13 +119,13 @@ def test_records_change_to_ready_for_processing(
assert ready_records.count() == 0
assert frozen_reports.count() == 0
sheriff_bot = PerfSheriffBot(
sherlock = Sherlock(
report_maintainer_mock,
backfill_tool_mock,
secretary,
notify_client_mock,
)
sheriff_bot.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
sherlock.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
assert preliminary_records.count() == 1
assert ready_records.count() == 1
@ -139,16 +137,16 @@ def test_assert_can_run_throws_exception_when_runtime_exceeded(
backfill_tool_mock,
secretary,
record_ready_for_processing,
sheriff_settings,
sherlock_settings,
notify_client_mock,
):
no_time_left = timedelta(seconds=0)
sheriff_bot = PerfSheriffBot(
sherlock_bot = Sherlock(
report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock, no_time_left
)
with pytest.raises(MaxRuntimeExceeded):
sheriff_bot.assert_can_run()
sherlock_bot.assert_can_run()
def test_assert_can_run_doesnt_throw_exception_when_enough_time_left(
@ -157,15 +155,15 @@ def test_assert_can_run_doesnt_throw_exception_when_enough_time_left(
secretary,
notify_client_mock,
record_ready_for_processing,
sheriff_settings,
sherlock_settings,
):
enough_time_left = timedelta(minutes=10)
sheriff_bot = PerfSheriffBot(
sherlock = Sherlock(
report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock, enough_time_left
)
try:
sheriff_bot.assert_can_run()
sherlock.assert_can_run()
except MaxRuntimeExceeded:
pytest.fail()
@ -175,16 +173,14 @@ def test_records_and_db_limits_remain_unchanged_if_no_records_suitable_for_backf
backfill_tool_mock,
secretary,
notify_client_mock,
sheriff_settings,
sherlock_settings,
record_unsuited_for_backfill,
):
sheriff_bot = PerfSheriffBot(
report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock
)
sheriff_bot._backfill()
sherlock = Sherlock(report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock)
sherlock._backfill()
assert not has_changed(record_unsuited_for_backfill)
assert not has_changed(sheriff_settings)
assert not has_changed(sherlock_settings)
def test_records_remain_unchanged_if_no_backfills_left(
@ -195,10 +191,8 @@ def test_records_remain_unchanged_if_no_backfills_left(
record_ready_for_processing,
empty_sheriff_settings,
):
sheriff_bot = PerfSheriffBot(
report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock
)
sheriff_bot._backfill()
sherlock = Sherlock(report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock)
sherlock._backfill()
assert not has_changed(record_ready_for_processing)
@ -208,20 +202,20 @@ def test_records_and_db_limits_remain_unchanged_if_runtime_exceeded(
backfill_tool_mock,
secretary,
record_ready_for_processing,
sheriff_settings,
sherlock_settings,
notify_client_mock,
):
no_time_left = timedelta(seconds=0)
sheriff_bot = PerfSheriffBot(
sherlock = Sherlock(
report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock, no_time_left
)
try:
sheriff_bot.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
sherlock.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
except MaxRuntimeExceeded:
pass
assert not has_changed(record_ready_for_processing)
assert not has_changed(sheriff_settings)
assert not has_changed(sherlock_settings)
def test_db_limits_update_if_backfills_left(
@ -229,14 +223,12 @@ def test_db_limits_update_if_backfills_left(
backfill_tool_mock,
secretary,
record_ready_for_processing,
sheriff_settings,
sherlock_settings,
notify_client_mock,
):
initial_backfills = secretary.backfills_left(on_platform='linux')
sheriff_bot = PerfSheriffBot(
report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock
)
sheriff_bot.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
sherlock = Sherlock(report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock)
sherlock.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
record_ready_for_processing.refresh_from_db()
assert record_ready_for_processing.status == BackfillRecord.BACKFILLED
@ -248,22 +240,20 @@ def test_backfilling_gracefully_handles_invalid_json_contexts_without_blowing_up
backfill_tool_mock,
secretary,
record_ready_for_processing,
sheriff_settings,
sherlock_settings,
notify_client_mock,
broken_context_str, # Note: parametrizes the test
):
record_ready_for_processing.context = broken_context_str
record_ready_for_processing.save()
sheriff_bot = PerfSheriffBot(
report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock
)
sherlock = Sherlock(report_maintainer_mock, backfill_tool_mock, secretary, notify_client_mock)
try:
sheriff_bot.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
sherlock.sheriff(since=EPOCH, frameworks=['raptor', 'talos'], repositories=['autoland'])
except (JSONDecodeError, KeyError, Job.DoesNotExist, Push.DoesNotExist):
pytest.fail()
record_ready_for_processing.refresh_from_db()
assert record_ready_for_processing.status == BackfillRecord.FAILED
assert not has_changed(sheriff_settings)
assert not has_changed(sherlock_settings)

Просмотреть файл

@ -5,7 +5,6 @@ from requests import Session
from treeherder.perf.sheriffing_criteria import NonBlockableSession
CASSETTE_LIBRARY_DIR = 'tests/sample_data/betamax_cassettes/perf_sheriffing_criteria'
CASSETTES_RECORDING_DATE = 'June 2nd, 2020' # when VCR has been conducted

Просмотреть файл

@ -1,27 +1,3 @@
from unittest.mock import MagicMock
import pytest
import taskcluster
from treeherder.services.taskcluster import notify_client_factory
from tests.conftest import SampleDataJSONLoader
load_json_fixture = SampleDataJSONLoader('perf_sheriff_bot')
@pytest.fixture
def job_from_try(eleven_job_blobs, create_jobs):
job_blob = eleven_job_blobs[0]
job = create_jobs([job_blob])[0]
job.repository.is_try_repo = True
job.repository.save()
return job
@pytest.fixture
def notify_client_mock() -> taskcluster.Notify:
return MagicMock(
spec=notify_client_factory('https://fakerooturl.org', 'FAKE_CLIENT_ID', 'FAKE_ACCESS_TOKEN')
)
load_json_fixture = SampleDataJSONLoader('sherlock')

Просмотреть файл

@ -8,7 +8,7 @@ from treeherder.services.taskcluster import (
NotifyAdapter,
)
load_json_fixture = SampleDataJSONLoader('perf_sheriff_bot')
load_json_fixture = SampleDataJSONLoader('sherlock')
@pytest.fixture(scope="module")

Просмотреть файл

@ -464,14 +464,15 @@ PERFHERDER_ENABLE_MULTIDATA_INGESTION = env.bool(
'PERFHERDER_ENABLE_MULTIDATA_INGESTION', default=True
)
# Performance sheriff bot settings
# Sherlock' settings (the performance sheriff robot)
MAX_BACKFILLS_PER_PLATFORM = {
'linux': 200,
}
RESET_BACKFILL_LIMITS = timedelta(hours=24)
TIME_TO_MATURE = timedelta(hours=4)
# Taskcluster credentials for PerfSheriffBot
# Taskcluster credentials for Sherlock
# TODO: rename PERF_SHERIFF_BOT prefixes to SHERLOCK
PERF_SHERIFF_BOT_CLIENT_ID = env('PERF_SHERIFF_BOT_CLIENT_ID', default=None)
PERF_SHERIFF_BOT_ACCESS_TOKEN = env('PERF_SHERIFF_BOT_ACCESS_TOKEN', default=None)

Просмотреть файл

@ -2,25 +2,25 @@ from datetime import timedelta
from django.conf import settings
from treeherder.perf.auto_perf_sheriffing.backfill_reports import (
from treeherder.perf.auto_perf_sherrifing.backfill_reports import (
BackfillReportMaintainer,
AlertsPicker,
IdentifyAlertRetriggerables,
)
from treeherder.perf.auto_perf_sheriffing.backfill_tool import BackfillTool
from treeherder.perf.auto_perf_sheriffing.perf_sheriff_bot import PerfSheriffBot
from treeherder.perf.auto_perf_sheriffing.secretary_tool import SecretaryTool
from treeherder.perf.auto_perf_sherrifing.backfill_tool import BackfillTool
from treeherder.perf.auto_perf_sherrifing.sherlock import Sherlock
from treeherder.perf.auto_perf_sherrifing.secretary import Secretary
from treeherder.services.taskcluster import DEFAULT_ROOT_URL, notify_client_factory
from treeherder.services.taskcluster import TaskclusterModelProxy
def perf_sheriff_bot_factory(days_to_lookup: timedelta) -> PerfSheriffBot:
def sherlock_factory(days_to_lookup: timedelta) -> Sherlock:
report_maintainer = __report_maintainer_factory(days_to_lookup)
backfill_tool = __backfill_tool_factory()
secretary_tool = SecretaryTool()
secretary = Secretary()
notify_client = notify_client_factory()
return PerfSheriffBot(report_maintainer, backfill_tool, secretary_tool, notify_client)
return Sherlock(report_maintainer, backfill_tool, secretary, notify_client)
def __report_maintainer_factory(days_to_lookup: timedelta) -> BackfillReportMaintainer:

Просмотреть файл

@ -6,14 +6,14 @@ from django.conf import settings as django_settings
from treeherder.perf.models import BackfillRecord, BackfillReport, PerformanceSettings
from treeherder.utils import default_serializer
from treeherder.perf.auto_perf_sheriffing.outcome_checker import OutcomeChecker, OutcomeStatus
from treeherder.perf.auto_perf_sherrifing.outcome_checker import OutcomeChecker, OutcomeStatus
logger = logging.getLogger(__name__)
# TODO: update the backfill status using data (bug 1626548)
# TODO: consider making this a singleton (bug 1639112)
class SecretaryTool:
class Secretary:
"""
* marks which records can be backfilled
* provides & maintains backfill limits
@ -25,7 +25,8 @@ class SecretaryTool:
@classmethod
def validate_settings(cls):
perf_sheriff_settings, created = PerformanceSettings.objects.get_or_create(
sherlock_settings, created = PerformanceSettings.objects.get_or_create(
# TODO: rename perf_sheriff_bot settings name to sherlock
name="perf_sheriff_bot",
defaults={"settings": cls._get_default_settings()},
)
@ -37,13 +38,13 @@ class SecretaryTool:
return
# reset limits if the settings expired
settings = json.loads(perf_sheriff_settings.settings)
logger.info(f"Perfsheriff bot settings: {settings}")
settings = json.loads(sherlock_settings.settings)
logger.info(f"Sherlock settings: {settings}.")
if cls.are_expired(settings):
logger.info(f"Settings are expired. Expired settings: {settings}")
logger.info(f"Settings are expired. Expired settings: {settings}.")
perf_sheriff_settings.settings = cls._get_default_settings()
perf_sheriff_settings.save()
sherlock_settings.settings = cls._get_default_settings()
sherlock_settings.save()
@classmethod
def mark_reports_for_backfill(cls):
@ -53,7 +54,7 @@ class SecretaryTool:
frozen=False, last_updated__lte=mature_date_limit
)
logger.info('Perfsheriff bot: %s mature reports found', mature_reports.count())
logger.info(f"Sherlock: {mature_reports.count()} mature reports found.")
# Only for logging alternative strategy for choosing maturity limit
alternative_date_limit = datetime.utcnow() - timedelta(days=1)
@ -61,20 +62,16 @@ class SecretaryTool:
frozen=False, created__lte=alternative_date_limit
)
logger.info(
'Perfsheriff bot: %s mature reports found with alternative strategy (not marking)',
alternative_mature_reports.count(),
f"Sherlock: {alternative_mature_reports.count()} mature reports found with alternative strategy (not marking).",
)
for report in mature_reports:
should_freeze = False
logger.info(
'Perfsheriff bot: marking report with id %s for backfill', report.summary.id
)
logger.info(f"Sherlock: Marking report with id {report.summary.id} for backfill...")
for record in report.records.all():
if record.status == BackfillRecord.PRELIMINARY:
logger.info(
'Perfsheriff bot: marking record with id %s READY_FOR_PROCESSING',
record.alert.id,
f"Sherlock: Marking record with id {record.alert.id} READY_FOR_PROCESSING..."
)
record.status = BackfillRecord.READY_FOR_PROCESSING
record.save()

Просмотреть файл

@ -10,9 +10,9 @@ from django.db.models import QuerySet
from taskcluster.helper import TaskclusterConfig
from treeherder.model.models import Job
from treeherder.perf.auto_perf_sheriffing.backfill_reports import BackfillReportMaintainer
from treeherder.perf.auto_perf_sheriffing.backfill_tool import BackfillTool
from treeherder.perf.auto_perf_sheriffing.secretary_tool import SecretaryTool
from treeherder.perf.auto_perf_sherrifing.backfill_reports import BackfillReportMaintainer
from treeherder.perf.auto_perf_sherrifing.backfill_tool import BackfillTool
from treeherder.perf.auto_perf_sherrifing.secretary import Secretary
from treeherder.perf.email import BackfillNotificationWriter, EmailWriter
from treeherder.perf.exceptions import CannotBackfill, MaxRuntimeExceeded
from treeherder.perf.models import BackfillRecord, BackfillReport
@ -23,8 +23,10 @@ CLIENT_ID = settings.PERF_SHERIFF_BOT_CLIENT_ID
ACCESS_TOKEN = settings.PERF_SHERIFF_BOT_ACCESS_TOKEN
class PerfSheriffBot:
class Sherlock:
"""
Robot variant of a performance sheriff (the main class)
Automates backfilling of skipped perf jobs.
"""
@ -34,14 +36,14 @@ class PerfSheriffBot:
self,
report_maintainer: BackfillReportMaintainer,
backfill_tool: BackfillTool,
secretary_tool: SecretaryTool,
secretary: Secretary,
notify_client: taskcluster.Notify,
max_runtime: timedelta = None,
email_writer: EmailWriter = None,
):
self.report_maintainer = report_maintainer
self.backfill_tool = backfill_tool
self.secretary = secretary_tool
self.secretary = secretary
self._notify = notify_client
self._max_runtime = self.DEFAULT_MAX_RUNTIME if max_runtime is None else max_runtime
self._email_writer = email_writer or BackfillNotificationWriter()
@ -51,28 +53,28 @@ class PerfSheriffBot:
def sheriff(self, since: datetime, frameworks: List[str], repositories: List[str]):
self.assert_can_run()
logger.info('Perfsheriff bot: Validating settings')
logger.info("Sherlock: Validating settings...")
self.secretary.validate_settings()
logger.info('Perfsheriff bot: Marking reports for backfill')
logger.info("Sherlock: Marking reports for backfill...")
self.secretary.mark_reports_for_backfill()
self.assert_can_run()
# secretary tool checks the status of all backfilled jobs
# secretary checks the status of all backfilled jobs
# TODO: should not be enabled during soft launch - enable for the real launch
# self.secretary.check_outcome()
# reporter tool should always run *(only handles preliminary records/reports)*
logger.info('Perfsheriff bot: Reporter tool is creating/maintaining reports')
logger.info("Sherlock: Reporter tool is creating/maintaining reports...")
self._report(since, frameworks, repositories)
self.assert_can_run()
# backfill tool follows
logger.info('Perfsheriff bot: Start backfills')
logger.info("Sherlock: Starting to backfill...")
self._backfill()
self.assert_can_run()
logger.info('Perfsheriff bot: Notify backfill outcome')
logger.info("Sherlock: Notifying backfill outcome...")
self._notify_backfill_outcome()
def runtime_exceeded(self) -> bool:
@ -94,18 +96,18 @@ class PerfSheriffBot:
# TODO: make this platform generic
records_to_backfill = self.__fetch_records_requiring_backfills()
logger.info('Perfsheriff bot: %s records found to backfill', records_to_backfill.count())
logger.info(f"Sherlock: {records_to_backfill.count()} records found to backfill.")
for record in records_to_backfill:
if left <= 0 or self.runtime_exceeded():
break
left, consumed = self._backfill_record(record, left)
logger.info('Perfsheriff bot: backfilled record with id %s', record.alert.id)
logger.info(f"Sherlock: Backfilled record with id {record.alert.id}.")
self.backfilled_records.append(record)
total_consumed += consumed
self.secretary.consume_backfills('linux', total_consumed)
logger.info('Perfsheriff bot: consumed %s backfills for linux', total_consumed)
logger.debug(f'Perfsheriff bot: Having {left} backfills left.')
logger.info(f"Sherlock: Consumed {total_consumed} backfills for Linux.")
logger.debug(f"Sherlock: Having {left} backfills left.")
@staticmethod
def __fetch_records_requiring_backfills() -> QuerySet:
@ -187,7 +189,7 @@ class PerfSheriffBot:
@staticmethod
def _is_queue_overloaded(provisioner_id: str, worker_type: str, acceptable_limit=100) -> bool:
"""
Helper method for PerfSheriffBot to check load on processing queue.
Helper method for Sherlock to check load on processing queue.
Usage example: _queue_is_too_loaded('gecko-3', 'b-linux')
:return: True/False
"""

Просмотреть файл

@ -10,7 +10,7 @@ functionality of the `BackfillTool`.
from django.conf import settings
from django.core.management.base import BaseCommand
from treeherder.perf.auto_perf_sheriffing.backfill_tool import BackfillTool
from treeherder.perf.auto_perf_sherrifing.backfill_tool import BackfillTool
from treeherder.services.taskcluster import DEFAULT_ROOT_URL as root_url
from treeherder.services.taskcluster import TaskclusterModel

Просмотреть файл

@ -5,7 +5,7 @@ from typing import List, Tuple
from django.core.management.base import BaseCommand
from treeherder.model.models import Repository
from treeherder.perf.auto_perf_sheriffing.factories import perf_sheriff_bot_factory
from treeherder.perf.auto_perf_sherrifing.factories import sherlock_factory
from treeherder.perf.exceptions import MaxRuntimeExceeded
from treeherder.perf.models import PerformanceFramework
@ -49,13 +49,13 @@ class Command(BaseCommand):
def handle(self, *args, **options):
frameworks, repositories, since, days_to_lookup = self._parse_args(**options)
perf_sheriff_bot = perf_sheriff_bot_factory(days_to_lookup)
sherlock = sherlock_factory(days_to_lookup)
try:
perf_sheriff_bot.sheriff(since, frameworks, repositories)
sherlock.sheriff(since, frameworks, repositories)
except MaxRuntimeExceeded as ex:
logging.info(ex)
logging.info("Perfsheriff bot: Going back to sleep")
logging.info("Sherlock: Going back to sleep.")
def _parse_args(self, **options) -> Tuple[List, List, datetime, timedelta]:
return (

Просмотреть файл

@ -535,7 +535,7 @@ class PerformanceBugTemplate(models.Model):
return '{} bug template'.format(self.framework.name)
# TODO: we actually need this name for the PerfSheriffBot' s hourly report
# TODO: we actually need this name for the Sherlock' s hourly report
class BackfillReport(models.Model):
"""
Groups & stores all context required to retrigger/backfill