| # Copyright 2025 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """ Writes logs to indicate a long-run process to avoid being killed by luci. |
| """ |
| |
| import logging |
| |
| from contextlib import AbstractContextManager |
| from threading import Timer |
| |
| |
| class RepeatingLog(AbstractContextManager): |
| """Starts writing the log once a while after the initial wait. Luci swarming |
| considers a long run job being dead if it does not output for a while. |
| It's an issue for tasks like video analysis which may take up to several |
| minutes. So this is a simple way to workaround the restriction.""" |
| |
| def __init__(self, msg: str): |
| self.msg = msg |
| self.counter = 0 |
| self.timer = None |
| |
| def __enter__(self): |
| self._schedule() |
| |
| def _schedule(self) -> None: |
| self.timer = Timer(15, self._log_and_schedule) |
| self.timer.start() |
| |
| def _log_and_schedule(self) -> None: |
| self.counter += 1 |
| # Use warning to avoid being ignored by the log-level. |
| logging.warning('[After %s seconds] - %s', self.counter * 15, self.msg) |
| self._schedule() |
| |
| def __exit__(self, exc_type, exc_value, traceback): |
| if self.timer: |
| self.timer.cancel() |