tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

log_manager.py (3605B)


      1 # Copyright 2022 The Chromium Authors
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 """Reads log data from a device."""
      5 
      6 import os
      7 import subprocess
      8 import sys
      9 
     10 from contextlib import AbstractContextManager
     11 from typing import Iterable, Optional, TextIO
     12 
     13 from common import run_continuous_ffx_command
     14 from ffx_integration import run_symbolizer
     15 
     16 
     17 class LogManager(AbstractContextManager):
     18    """Handles opening and closing file streams for logging purposes."""
     19 
     20    def __init__(self, logs_dir: Optional[str]) -> None:
     21        self._logs_dir = logs_dir
     22 
     23        # A dictionary with the log file path as the key and a file stream as
     24        # value.
     25        self._log_files = {}
     26        self._log_procs = []
     27        self._scoped_ffx_log = None
     28 
     29    def __enter__(self):
     30        return self
     31 
     32    def is_logging_enabled(self) -> bool:
     33        """Check whether logging is turned on."""
     34 
     35        return self._logs_dir is not None
     36 
     37    def add_log_process(self, process: subprocess.Popen) -> None:
     38        """Register a logging process to LogManager to be killed at LogManager
     39        teardown."""
     40 
     41        self._log_procs.append(process)
     42 
     43    def open_log_file(self, log_file_name: str) -> TextIO:
     44        """Open a file stream with log_file_name in the logs directory."""
     45 
     46        assert self._logs_dir, 'Logging directory is not specified.'
     47        log_file_path = os.path.join(self._logs_dir, log_file_name)
     48        log_file = open(log_file_path, 'w', buffering=1)
     49        self._log_files[log_file_path] = log_file
     50        return log_file
     51 
     52    def __exit__(self, exc_type, exc_value, traceback):
     53        """Stop all active logging instances."""
     54        for proc in self._log_procs:
     55            proc.kill()
     56        for log in self._log_files.values():
     57            log.close()
     58        return False
     59 
     60 
     61 def start_system_log(log_manager: LogManager,
     62                     log_to_stdout: bool,
     63                     pkg_paths: Optional[Iterable[str]] = None,
     64                     log_args: Optional[Iterable[str]] = None,
     65                     target_id: Optional[str] = None) -> None:
     66    """
     67    Start system logging.
     68 
     69    Args:
     70        log_manager: A LogManager class that manages the log file and process.
     71        log_to_stdout: If set to True, print logs directly to stdout.
     72        pkg_paths: Path to the packages
     73        log_args: Arguments forwarded to `ffx log` command.
     74        target_id: Specify a target to use.
     75    """
     76 
     77    if not log_manager.is_logging_enabled() and not log_to_stdout:
     78        return
     79    symbol_paths = None
     80    if pkg_paths:
     81        symbol_paths = []
     82 
     83        # Locate debug symbols for each package.
     84        for pkg_path in pkg_paths:
     85            assert os.path.isfile(pkg_path), '%s does not exist' % pkg_path
     86            symbol_paths.append(
     87                os.path.join(os.path.dirname(pkg_path), 'ids.txt'))
     88 
     89    if log_to_stdout:
     90        system_log = sys.stdout
     91    else:
     92        system_log = log_manager.open_log_file('system_log')
     93    log_cmd = ['log', '--symbolize', 'off', '--no-color']
     94    if log_args:
     95        log_cmd.extend(log_args)
     96    if symbol_paths:
     97        log_proc = run_continuous_ffx_command(log_cmd,
     98                                              target_id,
     99                                              stdout=subprocess.PIPE)
    100        log_manager.add_log_process(log_proc)
    101        log_manager.add_log_process(
    102            run_symbolizer(symbol_paths, log_proc.stdout, system_log))
    103    else:
    104        log_manager.add_log_process(
    105            run_continuous_ffx_command(log_cmd, target_id, stdout=system_log))