1# Copyright 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import collections
6
7from telemetry.core import exceptions
8
9class Profiler(object):
10  """A sampling profiler provided by the platform.
11
12  A profiler is started on its constructor, and should
13  gather data until CollectProfile().
14  The life cycle is normally tied to a single page,
15  i.e., multiple profilers will be created for a page set.
16  WillCloseBrowser() is called right before the browser
17  is closed to allow any further cleanup.
18  """
19
20  def __init__(self, browser_backend, platform_backend, output_path, state):
21    self._browser_backend = browser_backend
22    self._platform_backend = platform_backend
23    self._output_path = output_path
24    self._state = state
25
26  @classmethod
27  def name(cls):
28    """User-friendly name of this profiler."""
29    raise NotImplementedError()
30
31  @classmethod
32  def is_supported(cls, browser_type):
33    """True iff this profiler is currently supported by the platform."""
34    raise NotImplementedError()
35
36  @classmethod
37  def CustomizeBrowserOptions(cls, browser_type, options):
38    """Override to customize the Browser's options before it is created."""
39    pass
40
41  @classmethod
42  def WillCloseBrowser(cls, browser_backend, platform_backend):
43    """Called before the browser is stopped."""
44    pass
45
46  def _GetProcessOutputFileMap(self):
47    """Returns a dict with pid: output_file."""
48    all_pids = ([self._browser_backend.pid] +
49                self._platform_backend.GetChildPids(self._browser_backend.pid))
50
51    process_name_counts = collections.defaultdict(int)
52    process_output_file_map = {}
53    for pid in all_pids:
54      try:
55        cmd_line = self._platform_backend.GetCommandLine(pid)
56        process_name = self._browser_backend.GetProcessName(cmd_line)
57        output_file = '%s.%s%s' % (self._output_path, process_name,
58                                   process_name_counts[process_name])
59        process_name_counts[process_name] += 1
60        process_output_file_map[pid] = output_file
61      except exceptions.ProcessGoneException:
62        # Ignore processes that disappeared since calling GetChildPids().
63        continue
64    return process_output_file_map
65
66  def CollectProfile(self):
67    """Collect the profile from the profiler."""
68    raise NotImplementedError()
69