<commit_before># Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# pylint: disable=unused-argument

import errno
import logging
import os
import re
import shutil
import tempfile
import threading
import time

from devil.android import decorators
from devil.android import device_errors
from devil.android.sdk import adb_wrapper
from devil.utils import reraiser_thread


class LogcatMonitor(object):

  _RECORD_THREAD_JOIN_WAIT = 2.0
  _WAIT_TIME = 0.2
  _THREADTIME_RE_FORMAT = (
      r'(?P<date>\S*) +(?P<time>\S*) +(?P<proc_id>%s) +(?P<thread_id>%s) +'
      r'(?P<log_level>%s) +(?P<component>%s) *: +(?P<message>%s)$')

  def __init__(self, adb, clear=True, filter_specs=None, output_file=None):
    """Create a LogcatMonitor instance.

    Args:
      adb: An instance of adb_wrapper.AdbWrapper.
      clear: If True, clear the logcat when monitoring starts.
      filter_specs: An optional list of '<tag>[:priority]' strings.
      output_file: File path to save recorded logcat.
    """
    if isinstance(adb, adb_wrapper.AdbWrapper):
      self._adb = adb
    else:
      raise ValueError('Unsupported type passed for argument "device"')
    self._clear = clear
    self._filter_specs = filter_specs
    self._output_file = output_file
    self._record_file = None
    self._record_file_lock = threading.Lock()
    self._record_thread = None
    self._stop_recording_event = threading.Event()

  @decorators.WithTimeoutAndRetriesDefaults(10, 0)
  def WaitFor(self, success_regex, failure_regex=None, timeout=None,
              retries=None):
    """Wait for a matching logcat line or until a timeout occurs.

    This will attempt to match lines in the logcat against both |success_regex|
    and |failure_regex| (if provided). Note that this calls re.search on each
    logcat line, not re.match, so the provided regular expressions don't have
    to match an entire line.

    Args:
      success_regex: The regular expression to search for.
      failure_regex: An optional regular expression that, if hit, causes this
        to stop looking for a match. Can be None.
      timeout: timeout in seconds
      retries: number of retries

    Returns:<commit_msg>[Devil] Add output_file property to logcat monitor.<commit_after># Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# pylint: disable=unused-argument

import errno
import logging
import os
import re
import shutil
import tempfile
import threading
import time

from devil.android import decorators
from devil.android import device_errors
from devil.android.sdk import adb_wrapper
from devil.utils import reraiser_thread


class LogcatMonitor(object):

  _RECORD_THREAD_JOIN_WAIT = 2.0
  _WAIT_TIME = 0.2
  _THREADTIME_RE_FORMAT = (
      r'(?P<date>\S*) +(?P<time>\S*) +(?P<proc_id>%s) +(?P<thread_id>%s) +'
      r'(?P<log_level>%s) +(?P<component>%s) *: +(?P<message>%s)$')

  def __init__(self, adb, clear=True, filter_specs=None, output_file=None):
    """Create a LogcatMonitor instance.

    Args:
      adb: An instance of adb_wrapper.AdbWrapper.
      clear: If True, clear the logcat when monitoring starts.
      filter_specs: An optional list of '<tag>[:priority]' strings.
      output_file: File path to save recorded logcat.
    """
    if isinstance(adb, adb_wrapper.AdbWrapper):
      self._adb = adb
    else:
      raise ValueError('Unsupported type passed for argument "device"')
    self._clear = clear
    self._filter_specs = filter_specs
    self._output_file = output_file
    self._record_file = None
    self._record_file_lock = threading.Lock()
    self._record_thread = None
    self._stop_recording_event = threading.Event()

  @property
  def output_file(self):
    return self._output_file

  @decorators.WithTimeoutAndRetriesDefaults(10, 0)
  def WaitFor(self, success_regex, failure_regex=None, timeout=None,
              retries=None):
    """Wait for a matching logcat line or until a timeout occurs.

    This will attempt to match lines in the logcat against both |success_regex|
    and |failure_regex| (if provided). Note that this calls re.search on each
    logcat line, not re.match, so the provided regular expressions don't have
    to match an entire line.

    Args:
      success_regex: The regular expression to search for.
      failure_regex: An optional regular expression that, if hit, causes this
        to stop looking for a match. Can be None.
      timeout: timeout in seconds
      retries: number of retries

    Returns:
{'fraction_non_alphanumeric': 0.08638015822108189, 'fraction_numerical': 0.004703870002138123, 'mean_word_length': 3.6920762286860582, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5756435', 'n_tokens_mistral': 1441, 'n_tokens_neox': 1398, 'n_words': 482}