Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: chrome/browser/sessions/session_restore_stats_collector.h

Issue 1136523004: [Sessions] Add detailed logging of SessionRestore events. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_ 5 #ifndef CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_
6 #define CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_ 6 #define CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_
7 7
8 #include <set> 8 #include <map>
9 9
10 #include "base/callback_list.h" 10 #include "base/callback_list.h"
11 #include "base/time/tick_clock.h"
11 #include "chrome/browser/sessions/session_restore.h" 12 #include "chrome/browser/sessions/session_restore.h"
12 #include "chrome/browser/sessions/session_restore_delegate.h" 13 #include "chrome/browser/sessions/session_restore_delegate.h"
13 #include "content/public/browser/notification_observer.h" 14 #include "content/public/browser/notification_observer.h"
14 #include "content/public/browser/notification_registrar.h" 15 #include "content/public/browser/notification_registrar.h"
15 #include "content/public/browser/render_widget_host.h" 16 #include "content/public/browser/render_widget_host.h"
16 17
17 namespace content { 18 namespace content {
18 class NavigationController; 19 class NavigationController;
19 } 20 }
20 21
21 // SessionRestoreStatsCollector observes SessionRestore events ands records UMA 22 // SessionRestoreStatsCollector observes SessionRestore events ands records UMA
22 // accordingly. 23 // accordingly.
24 //
25 // A SessionRestoreStatsCollector is tied to an instance of a session restore,
26 // currently being instantianted and owned by the TabLoader. It has two main
27 // phases to its life:
28 //
29 // 1. The session restore is active and ongoing (the TabLoader is still
30 // scheduling tabs for loading). This phases ends when there are no
31 // non-deferred tabs left to be loaded. During this phases statistics are
32 // gathered in a structure before being emitted as UMA metrics at the end of
33 // this phase. At this point the TabLoader ceases to exist and destroys it's
34 // reference to the SessionRestoreStatsCollector.
35 // 2. If any tabs have been deferred the SessionRestoreStatsCollector continues
36 // tracking deferred tabs. This continues to observe the tabs to see which
37 // (if any) of the deferred tabs are subsequently forced to be loaded by the
38 // user. Since such tabs may exist until the end of the browsers life the
39 // statistics are emitted immediately, or risk being lost entirely. When
40 // there are no longer deferred tabs to track the
41 // SessionRestoreStatsCollector will destroy itself.
42 //
43 // TODO(chrisha): Many of these metrics don't make sense to collect in the
44 // presence of an unavailable network, or when tabs are closed during loading.
45 // Rethink the collection in these cases.
23 class SessionRestoreStatsCollector 46 class SessionRestoreStatsCollector
24 : public content::NotificationObserver, 47 : public content::NotificationObserver,
25 public base::RefCounted<SessionRestoreStatsCollector> { 48 public base::RefCounted<SessionRestoreStatsCollector> {
26 public: 49 public:
27 // Called to start tracking tabs. If a restore is already occuring, the tabs 50 // Houses all of the statistics gathered by the SessionRestoreStatsCollector
28 // are added to the existing list of tracked tabs. 51 // while the underlying TabLoader is active. These statistics are all reported
29 static void TrackTabs( 52 // at once via the reporting delegate.
30 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs, 53 struct TabLoaderStats {
31 const base::TimeTicks& restore_started); 54 // Constructor that initializes everything to zero.
32 55 TabLoaderStats();
33 // Called to start tracking only active tabs. If a restore is already 56
34 // occuring, the tabs are added to the existing list of tracked tabs. 57 // The number of tabs involved in all overlapping session restores being
35 static void TrackActiveTabs( 58 // tracked by this SessionRestoreStatsCollector. This corresponds to the
36 const std::vector<SessionRestoreDelegate::RestoredTab>& tabs, 59 // "SessionRestore.TabCount" metric and one bucket of the
37 const base::TimeTicks& restore_started); 60 // "SessionRestore.TabActions" histogram.
38 61 size_t tab_count;
39 private: 62
63 // The number of tabs loaded automatically because they are active, and
64 // explicitly caused to be loaded by the TabLoader. This corresponds to one
65 // bucket of the "SessionRestore.TabActions" histogram.
66 size_t tabs_loaded;
67
68 // The time elapsed between |restore_started| and reception of the first
69 // NOTIFICATION_LOAD_STOP event for any of the active tabs involved in the
70 // session restore. If this is zero it is because it has not been
71 // recorded (all visible tabs were closed before they finished loading, or
72 // the user switched to an already loaded tab before a visible session
73 // restore tab finished loading). Corresponds to
74 // "SessionRestore.ForegroundTabFirstLoaded" and its _XX variants.
75 base::TimeDelta foreground_tab_first_loaded;
76
77 // The time elapsed between |restore_started| and reception of the first
78 // NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE event for any of
79 // the tabs involved in the session restore. If this is zero it is because
80 // it has not been recorded (all visible tabs were closed or switched away
81 // from before they were painted). Corresponds to
82 // "SessionRestore.ForegroundTabFirstPaint3" and its _XX variants.
83 base::TimeDelta foreground_tab_first_paint;
84
85 // The time taken for all non-deferred tabs to be loaded. This corresponds
86 // to the "SessionRestore.AllTabsLoaded" metric and its _XX variants
87 // (vaguely named for historical reasons, as it predates the concept of
88 // deferred tabs).
89 base::TimeDelta non_deferred_tabs_loaded;
90
91 // The maximum number of tabs loading in parallel. This corresponds to the
92 // "SessionRestore.ParallelTabLoads" metric.
93 size_t parallel_tab_loads;
94 };
95
96 // The StatsReportingDelegate is responsible for delivering statistics
97 // reported by the SessionRestoreStatsCollector.
98 class StatsReportingDelegate;
99
100 // An implementation of StatsReportingDelegate for reporting via UMA.
101 class UmaStatsReportingDelegate;
102
103 // Constructs a SessionRestoreStatsCollector. Ownership of
sky 2015/06/17 15:33:54 I would nuke the second sentence. It is implied by
chrisha 2015/06/17 17:44:34 Done.
104 // |reporting_delegate| is passed to this object.
105 SessionRestoreStatsCollector(
106 const base::TimeTicks& restore_started,
107 scoped_ptr<StatsReportingDelegate> reporting_delegate);
108
109 // Adds new tabs to the list of tracked tabs.
110 void TrackTabs(const std::vector<SessionRestoreDelegate::RestoredTab>& tabs);
111
112 // Called to indicate that the loading of a tab has been deferred by session
113 // restore.
114 void DeferTab(content::NavigationController* tab);
115
116 // Exposed for unittesting.
117 const TabLoaderStats& tab_loader_stats() const { return tab_loader_stats_; }
118
119 protected:
sky 2015/06/17 15:33:54 Style guide says no protected members.
chrisha 2015/06/17 17:44:34 Was just to make them unittest accessible. Will us
40 friend class base::RefCounted<SessionRestoreStatsCollector>; 120 friend class base::RefCounted<SessionRestoreStatsCollector>;
41 121
42 using RenderWidgetHostSet = std::set<content::RenderWidgetHost*>; 122 // Indicates whether the loading state of a tab.
43 123 enum TabLoadingState {
44 explicit SessionRestoreStatsCollector(const base::TimeTicks& restore_started); 124 TAB_IS_NOT_LOADING,
45 ~SessionRestoreStatsCollector() override; 125 TAB_IS_LOADING,
46 126 TAB_IS_LOADED
47 // NotificationObserver method. 127 };
128
129 // State that is tracked for a tab while it is being observed.
130 struct TabState {
131 explicit TabState(content::NavigationController* controller);
132
133 // The NavigationController associated with the tab. This is the primary
134 // index for it and is never null.
135 content::NavigationController* controller;
136
137 // The RenderWidgetHost associated with the tab. This is the secondary
138 // index and starts out being null. If it is not null it is because the tab
139 // is actively loading or waiting to be painted.
140 content::RenderWidgetHost* render_widget_host;
141
142 // Set to true if the tab has been deferred by the TabLoader.
143 bool is_deferred;
144
145 // The current loading state of the tab.
146 TabLoadingState loading_state;
147 };
148
149 // Maps a NavigationController to its state. This is the primary map and
150 // physically houses the state.
151 using NavigationControllerMap = std::map<content::NavigationController*,
152 TabState>;
153
154 virtual ~SessionRestoreStatsCollector();
155
156 // NotificationObserver method. This is the workhorse of the class and drives
157 // all state transitions.
48 void Observe(int type, 158 void Observe(int type,
49 const content::NotificationSource& source, 159 const content::NotificationSource& source,
50 const content::NotificationDetails& details) override; 160 const content::NotificationDetails& details) override;
51 161
52 // Adds new tabs to the list of tracked tabs. 162 // Called when a tab is no longer tracked. This is called by the 'Observe'
53 void AddTabs(const std::vector<SessionRestoreDelegate::RestoredTab>& tabs); 163 // notification callback. Takes care of unregistering all observers and
54 164 // removing the tab from all internal data structures.
55 // Called when a tab is no longer tracked.
56 void RemoveTab(content::NavigationController* tab); 165 void RemoveTab(content::NavigationController* tab);
57 166
58 // Registers for relevant notifications for a tab. 167 // Registers for relevant notifications for a tab and inserts the tab into
59 void RegisterForNotifications(content::NavigationController* tab); 168 // to tabs_tracked_ map. Return a pointer to the newly created TabState.
169 TabState* RegisterForNotifications(content::NavigationController* tab);
60 170
61 // Returns the RenderWidgetHost of a tab. 171 // Returns the RenderWidgetHost of a tab.
62 content::RenderWidgetHost* GetRenderWidgetHost( 172 content::RenderWidgetHost* GetRenderWidgetHost(
63 content::NavigationController* tab); 173 content::NavigationController* tab);
64 174
65 // Have we recorded the times for a foreground tab load? 175 // Returns the tab state, nullptr if not found.
176 TabState* GetTabState(content::NavigationController* tab);
177 TabState* GetTabState(content::RenderWidgetHost* tab);
178
179 // Marks a tab as loading.
180 void MarkTabAsLoading(TabState* tab_state);
181
182 // Checks to see if the SessionRestoreStatsCollector has finished collecting,
183 // and cleans itself up if it has.
184 void CleanupIfDoneTracking();
185
186 // Testing seam for configuring the tick clock in use. Ownership of the clock
187 // is passed to this object.
188 void set_tick_clock(scoped_ptr<base::TickClock> tick_clock);
sky 2015/06/17 15:33:54 Generally we inline functions in unix_hacker_style
chrisha 2015/06/17 17:44:34 Done.
189
190 // Has CleanIfDoneTracking determined that there are no non-deferred tabs to
191 // track?
192 bool done_tracking_non_deferred_tabs_;
193
194 // Has the time for foreground tab load been recorded?
66 bool got_first_foreground_load_; 195 bool got_first_foreground_load_;
67 196
68 // Have we recorded the times for a foreground tab paint? 197 // Has the time for foreground tab paint been recorded?
69 bool got_first_paint_; 198 bool got_first_paint_;
70 199
71 // The time the restore process started. 200 // The time the restore process started.
72 base::TimeTicks restore_started_; 201 const base::TimeTicks restore_started_;
73 202
74 // The renderers we have started loading into. 203 // List of tracked tabs, mapped to their TabState.
75 RenderWidgetHostSet render_widget_hosts_loading_; 204 NavigationControllerMap tabs_tracked_;
76 205
77 // The renderers we have loaded and are waiting on to paint. 206 // Counts the number of non-deferred tabs that the
78 RenderWidgetHostSet render_widget_hosts_to_paint_; 207 // SessionRestoreStatsCollector is waiting to see load.
79 208 size_t waiting_for_load_tab_count_;
80 // List of tracked tabs. 209
81 std::set<content::NavigationController*> tabs_tracked_; 210 // Counts the current number of actively loading tabs.
82 211 size_t loading_tab_count_;
83 // The number of tabs that have been restored.
84 int tab_count_;
85
86 // Max number of tabs that were loaded in parallel (for metrics).
87 size_t max_parallel_tab_loads_;
88 212
89 // Notification registrar. 213 // Notification registrar.
90 content::NotificationRegistrar registrar_; 214 content::NotificationRegistrar registrar_;
91 215
92 // To keep the collector alive as long as needed. 216 // Statistics gathered regarding the TabLoader.
217 TabLoaderStats tab_loader_stats_;
218
219 // The source of ticks used for taking timing information. This is
220 // configurable as a testing seam. Defaults to using base::DefaultTickClock,
221 // which in turn uses base::TimeTicks.
222 scoped_ptr<base::TickClock> tick_clock_;
223
224 // The reporting delegate used to report gathered statistics.
225 scoped_ptr<StatsReportingDelegate> reporting_delegate_;
226
227 // For keeping SessionRestoreStatsCollector alive while it is still working
228 // even if no TabLoader references it. The object only lives on if it still
229 // has deferred tabs remaining from an interrupted session restore.
93 scoped_refptr<SessionRestoreStatsCollector> this_retainer_; 230 scoped_refptr<SessionRestoreStatsCollector> this_retainer_;
94 231
95 // The shared SessionRestoreNotifier instance for all SessionRestores running
96 // at this time.
97 static SessionRestoreStatsCollector* shared_collector_;
98
99 DISALLOW_COPY_AND_ASSIGN(SessionRestoreStatsCollector); 232 DISALLOW_COPY_AND_ASSIGN(SessionRestoreStatsCollector);
100 }; 233 };
101 234
235 // An abstract reporting delegate is used as a testing seam.
236 class SessionRestoreStatsCollector::StatsReportingDelegate {
237 public:
238 StatsReportingDelegate() { }
sky 2015/06/17 15:33:54 nit: { } -> {} here, next line and 258. Make sure
chrisha 2015/06/17 17:44:34 Yeah, neglected to run format. Done now.
239 virtual ~StatsReportingDelegate() { }
240
241 // Called when TabLoader has completed its work.
242 virtual void ReportTabLoaderStats(
243 const TabLoaderStats& tab_loader_stats) = 0;
244 // Called when a tab has been deferred.
245 virtual void ReportTabDeferred() = 0;
246 // Called when a deferred tab has been loaded.
247 virtual void ReportDeferredTabLoaded() = 0;
248
249 private:
250 DISALLOW_COPY_AND_ASSIGN(StatsReportingDelegate);
251 };
252
253 // The default reporting delegate, which reports statistics via UMA.
254 class SessionRestoreStatsCollector::UmaStatsReportingDelegate
255 : public StatsReportingDelegate {
256 public:
257 UmaStatsReportingDelegate();
258 virtual ~UmaStatsReportingDelegate() { }
sky 2015/06/17 15:33:54 This should be override, no virtual.
chrisha 2015/06/17 17:44:34 Done.
259
260 // StatsReportingDelegate implementation.
261 void ReportTabLoaderStats(
262 const TabLoaderStats& tab_loader_stats) override;
263 void ReportTabDeferred() override;
264 void ReportDeferredTabLoaded() override;
265
266 private:
267 // Has ReportTabDeferred been called?
268 bool got_report_tab_deferred_;
269
270 DISALLOW_COPY_AND_ASSIGN(UmaStatsReportingDelegate);
271 };
272
102 #endif // CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_ 273 #endif // CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698