boot_times_loader.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 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
5#ifndef CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_
6#define CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_
7
8#include <set>
9#include <string>
10
11#include "base/atomic_sequence_num.h"
12#include "base/callback_forward.h"
13#include "base/compiler_specific.h"
14#include "base/time.h"
15#include "chrome/browser/common/cancelable_request.h"
16#include "content/public/browser/notification_observer.h"
17#include "content/public/browser/notification_registrar.h"
18#include "content/public/browser/render_widget_host.h"
19
20namespace chromeos {
21
22// BootTimesLoader loads the bootimes of Chrome OS from the file system.
23// Loading is done asynchronously on the file thread. Once loaded,
24// BootTimesLoader calls back to a method of your choice with the boot times.
25// To use BootTimesLoader do the following:
26//
27// . In your class define a member field of type chromeos::BootTimesLoader and
28//   CancelableRequestConsumerBase.
29// . Define the callback method, something like:
30//   void OnBootTimesLoader(chromeos::BootTimesLoader::Handle,
31//                             BootTimesLoader::BootTimes boot_times);
32// . When you want the version invoke: loader.GetBootTimes(&consumer, callback);
33class BootTimesLoader
34    : public CancelableRequestProvider,
35      public content::NotificationObserver {
36 public:
37  BootTimesLoader();
38  virtual ~BootTimesLoader();
39
40  // All fields are 0.0 if they couldn't be found.
41  typedef struct BootTimes {
42    double firmware;           // Time from power button to kernel being loaded.
43    double pre_startup;        // Time from kernel to system code being called.
44    double x_started;          // Time X server is ready to be connected to.
45    double chrome_exec;        // Time session manager executed Chrome.
46    double chrome_main;        // Time chrome's main() was called.
47    double login_prompt_ready; // Time login (or OOB) panel is displayed.
48    double system;             // Time system took to start chrome.
49    double chrome;             // Time chrome took to display login panel.
50    double total;              // Time from power button to login panel.
51
52    BootTimes() : firmware(0),
53                  pre_startup(0),
54                  x_started(0),
55                  chrome_exec(0),
56                  chrome_main(0),
57                  login_prompt_ready(0),
58                  system(0),
59                  chrome(0),
60                  total(0) {}
61  } BootTimes;
62
63  // Signature
64  typedef base::Callback<void(Handle, BootTimes)> GetBootTimesCallback;
65
66  typedef CancelableRequest<GetBootTimesCallback> GetBootTimesRequest;
67
68  static BootTimesLoader* Get();
69
70  // Asynchronously requests the info.
71  Handle GetBootTimes(
72      CancelableRequestConsumerBase* consumer,
73      const GetBootTimesCallback& callback);
74
75  // Add a time marker for login. A timeline will be dumped to
76  // /tmp/login-times-sent after login is done. If |send_to_uma| is true
77  // the time between this marker and the last will be sent to UMA with
78  // the identifier BootTime.|marker_name|.
79  void AddLoginTimeMarker(const std::string& marker_name, bool send_to_uma);
80
81  // Add a time marker for logout. A timeline will be dumped to
82  // /tmp/logout-times-sent after logout is done. If |send_to_uma| is true
83  // the time between this marker and the last will be sent to UMA with
84  // the identifier ShutdownTime.|marker_name|.
85  void AddLogoutTimeMarker(const std::string& marker_name, bool send_to_uma);
86
87  // Records current uptime and disk usage for metrics use.
88  // Posts task to file thread.
89  // name will be used as part of file names in /tmp.
90  // Existing stats files will not be overwritten.
91  void RecordCurrentStats(const std::string& name);
92
93  // Saves away the stats at main, so the can be recorded later. At main() time
94  // the necessary threads don't exist yet for recording the data.
95  void SaveChromeMainStats();
96
97  // Records the data previously saved by SaveChromeMainStats(), using the
98  // file thread. Existing stats files will not be overwritten.
99  void RecordChromeMainStats();
100
101  // Records the time that a login was attempted. This will overwrite any
102  // previous login attempt times.
103  void RecordLoginAttempted();
104
105  // content::NotificationObserver implementation.
106  virtual void Observe(int type,
107                       const content::NotificationSource& source,
108                       const content::NotificationDetails& details) OVERRIDE;
109
110  // Writes the logout times to a /tmp/logout-times-sent. Unlike login
111  // times, we manually call this function for logout times, as we cannot
112  // rely on notification service to tell when the logout is done.
113  void WriteLogoutTimes();
114
115 private:
116  // BootTimesLoader calls into the Backend on the file thread to load
117  // the boot times.
118  class Backend : public base::RefCountedThreadSafe<Backend> {
119   public:
120    Backend() {}
121
122    void GetBootTimes(const scoped_refptr<GetBootTimesRequest>& request);
123
124   private:
125    friend class base::RefCountedThreadSafe<Backend>;
126
127    ~Backend() {}
128
129    DISALLOW_COPY_AND_ASSIGN(Backend);
130  };
131
132  class TimeMarker {
133   public:
134    TimeMarker(const std::string& name, bool send_to_uma)
135        : name_(name),
136          time_(base::Time::NowFromSystemTime()),
137          send_to_uma_(send_to_uma) {}
138    std::string name() const { return name_; }
139    base::Time time() const { return time_; }
140    bool send_to_uma() const { return send_to_uma_; }
141
142    // comparitor for sorting
143    bool operator<(const TimeMarker& other) const {
144      return time_ < other.time_;
145    }
146
147   private:
148    friend class std::vector<TimeMarker>;
149    std::string name_;
150    base::Time time_;
151    bool send_to_uma_;
152  };
153
154  struct Stats {
155   public:
156    std::string uptime;
157    std::string disk;
158  };
159
160  static void RecordStats(
161      const std::string& name, const Stats& stats);
162  static Stats GetCurrentStats();
163  static void WriteTimes(const std::string base_name,
164                         const std::string uma_name,
165                         const std::string uma_prefix,
166                         std::vector<TimeMarker> login_times);
167  static void AddMarker(std::vector<TimeMarker>* vector, TimeMarker marker);
168
169  void LoginDone();
170
171  // Used to hold the stats at main().
172  Stats chrome_main_stats_;
173  scoped_refptr<Backend> backend_;
174
175  // Used to track notifications for login.
176  content::NotificationRegistrar registrar_;
177  base::AtomicSequenceNumber num_tabs_;
178  bool have_registered_;
179
180  std::vector<TimeMarker> login_time_markers_;
181  std::vector<TimeMarker> logout_time_markers_;
182  std::set<content::RenderWidgetHost*> render_widget_hosts_loading_;
183
184  DISALLOW_COPY_AND_ASSIGN(BootTimesLoader);
185};
186
187}  // namespace chromeos
188
189#endif  // CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_
190