Ejemplo n.º 1
0
def TracerMain_(log, storage_path, backend_name, device_id, pid, interval,
    count, trace_native_heap):
  """Entry point for the background periodic tracer task."""
  # Initialize storage.
  storage = file_storage.Storage(storage_path)

  # Initialize the backend.
  backend = backends.GetBackend(backend_name)
  for k, v in storage.LoadSettings(backend_name).iteritems():
    backend.settings[k] = v

  # Initialize the device.
  device = backends.GetDevice(backend_name, device_id)
  for k, v in storage.LoadSettings(device_id).iteritems():
    device.settings[k] = v

  # Start periodic tracing.
  process = device.GetProcess(pid)
  log.put((1, 'Starting trace (%d dumps x %s s.). Device: %s, process: %s' % (
      count, interval, device.name, process.name)))
  datetime_str = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M')
  archive_name = '%s - %s - %s' % (datetime_str, device.name, process.name)
  archive = storage.OpenArchive(archive_name, create=True)
  heaps_to_symbolize = []

  for i in xrange(1, count + 1):  # [1, count] range is easier to handle.
    process = device.GetProcess(pid)
    if not process:
      log.put((100, 'Process %d died.' % pid))
      return 1
    # Calculate the completion rate proportionally to 80%. We keep the remaining
    # 20% for the final symbolization step (just an approximate estimation).
    completion = 80 * i / count
    log.put((completion, 'Dumping trace %d of %d' % (i, count)))
    archive.StartNewSnapshot()
    mmaps = process.DumpMemoryMaps()
    log.put((completion, 'Dumped %d memory maps' % len(mmaps)))
    archive.StoreMemMaps(mmaps)
    if trace_native_heap:
      nheap = process.DumpNativeHeap()
      log.put((completion, 'Dumped %d native allocs' % len(nheap.allocations)))
      archive.StoreNativeHeap(nheap)
      heaps_to_symbolize += [nheap]

    if i < count:
      time.sleep(interval)

  log.put((90, 'Symbolizing'))
  symbols = backend.ExtractSymbols(heaps_to_symbolize,
                                   device.settings['native_symbol_paths'] or '')

  expected_symbols_count = len(set.union(
      *[set(x.stack_frames.iterkeys()) for x in heaps_to_symbolize]))
  log.put((99, 'Symbolization complete. Got %d symbols (%.1f%%).' % (
      len(symbols), 100.0 * len(symbols) / expected_symbols_count)))

  archive.StoreSymbols(symbols)

  log.put((100, 'Trace complete.'))
  return 0
Ejemplo n.º 2
0
_HTTP_OK = '200 OK'
_HTTP_GONE = '410 Gone'
_HTTP_NOT_FOUND = '404 Not Found'
_HTTP_INTERNAL_ERROR = '500 Internal Server Error'
_PERSISTENT_STORAGE_PATH = os.path.join(os.path.expanduser('~'), '.config',
                                        'memory_inspector')
_CONTENT_DIR = os.path.abspath(
    os.path.join(os.path.dirname(__file__), 'www_content'))
_APP_PROCESS_RE = r'^[\w.:]+$'  # Regex for matching app processes.
_STATS_HIST_SIZE = 120  # Keep at most 120 samples of stats per process.
_CACHE_LEN = 10  # Max length of |_cached_objs|.

# |_cached_objs| keeps the state of short-lived objects that the client needs to
# _cached_objs subsequent AJAX calls.
_cached_objs = collections.OrderedDict()
_persistent_storage = file_storage.Storage(_PERSISTENT_STORAGE_PATH)
_proc_stats_history = {
}  # /Android/device/PID -> deque([stats@T=0, stats@T=1])


class UriHandler(object):
    """Base decorator used to automatically route /requests/by/path.

  Each handler is called with the following args:
    args: a tuple of the matching regex groups.
    req_vars: a dictionary of request args (querystring for GET, body for POST).
  Each handler must return a tuple with the following elements:
    http_code: a string with the HTTP status code (e.g., '200 - OK')
    headers: a list of HTTP headers (e.g., [('Content-Type': 'foo/bar')])
    body: the HTTP response body.
  """
Ejemplo n.º 3
0
 def setUp(self):
   self._storage_path = tempfile.mkdtemp()
   self._storage = file_storage.Storage(self._storage_path)