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

Unified 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: Fix typo. 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/sessions/session_restore_stats_collector.h
diff --git a/chrome/browser/sessions/session_restore_stats_collector.h b/chrome/browser/sessions/session_restore_stats_collector.h
index 668e2c01b77a52e1a1ed57ea4017da9d870f44fd..48da96e1da8fac0f53d66e9a2256828da0fb15e1 100644
--- a/chrome/browser/sessions/session_restore_stats_collector.h
+++ b/chrome/browser/sessions/session_restore_stats_collector.h
@@ -5,9 +5,10 @@
#ifndef CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_
#define CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_
-#include <set>
+#include <map>
#include "base/callback_list.h"
+#include "base/time/tick_clock.h"
#include "chrome/browser/sessions/session_restore.h"
#include "chrome/browser/sessions/session_restore_delegate.h"
#include "content/public/browser/notification_observer.h"
@@ -20,83 +21,252 @@ class NavigationController;
// SessionRestoreStatsCollector observes SessionRestore events ands records UMA
// accordingly.
+//
+// A SessionRestoreStatsCollector is tied to an instance of a session restore,
+// currently being instantianted and owned by the TabLoader. It has two main
+// phases to its life:
+//
+// 1. The session restore is active and ongoing (the TabLoader is still
+// scheduling tabs for loading). This phases ends when there are no
+// non-deferred tabs left to be loaded. During this phases statistics are
+// gathered in a structure before being emitted as UMA metrics at the end of
+// this phase. At this point the TabLoader ceases to exist and destroys it's
+// reference to the SessionRestoreStatsCollector.
+// 2. If any tabs have been deferred the SessionRestoreStatsCollector continues
+// tracking deferred tabs. This continues to observe the tabs to see which
+// (if any) of the deferred tabs are subsequently forced to be loaded by the
+// user. Since such tabs may exist until the end of the browsers life the
+// statistics are emitted immediately, or risk being lost entirely. When
+// there are no longer deferred tabs to track the
+// SessionRestoreStatsCollector will destroy itself.
+//
+// TODO(chrisha): Many of these metrics don't make sense to collect in the
+// presence of an unavailable network, or when tabs are closed during loading.
+// Rethink the collection in these cases.
class SessionRestoreStatsCollector
: public content::NotificationObserver,
public base::RefCounted<SessionRestoreStatsCollector> {
public:
- // Called to start tracking tabs. If a restore is already occuring, the tabs
- // are added to the existing list of tracked tabs.
- static void TrackTabs(
- const std::vector<SessionRestoreDelegate::RestoredTab>& tabs,
- const base::TimeTicks& restore_started);
-
- // Called to start tracking only active tabs. If a restore is already
- // occuring, the tabs are added to the existing list of tracked tabs.
- static void TrackActiveTabs(
- const std::vector<SessionRestoreDelegate::RestoredTab>& tabs,
- const base::TimeTicks& restore_started);
+ // Houses all of the statistics gathered by the SessionRestoreStatsCollector
+ // while the underlying TabLoader is active. These statistics are all reported
+ // at once via the reporting delegate.
+ struct TabLoaderStats {
+ // Constructor that initializes everything to zero.
+ TabLoaderStats();
+
+ // The number of tabs involved in all overlapping session restores being
+ // tracked by this SessionRestoreStatsCollector. This corresponds to the
+ // "SessionRestore.TabCount" metric and one bucket of the
+ // "SessionRestore.TabActions" histogram.
+ size_t tab_count;
+
+ // The number of tabs loaded automatically because they are active, and
+ // explicitly caused to be loaded by the TabLoader. This corresponds to one
+ // bucket of the "SessionRestore.TabActions" histogram.
+ size_t tabs_loaded;
+
+ // The time elapsed between |restore_started| and reception of the first
+ // NOTIFICATION_LOAD_STOP event for any of the active tabs involved in the
+ // session restore. If this is zero it is because it has not been
+ // recorded (all visible tabs were closed before they finished loading, or
+ // the user switched to an already loaded tab before a visible session
+ // restore tab finished loading). Corresponds to
+ // "SessionRestore.ForegroundTabFirstLoaded" and its _XX variants.
+ base::TimeDelta foreground_tab_first_loaded;
+
+ // The time elapsed between |restore_started| and reception of the first
+ // NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE event for any of
+ // the tabs involved in the session restore. If this is zero it is because
+ // it has not been recorded (all visible tabs were closed or switched away
+ // from before they were painted). Corresponds to
+ // "SessionRestore.ForegroundTabFirstPaint3" and its _XX variants.
+ base::TimeDelta foreground_tab_first_paint;
+
+ // The time taken for all non-deferred tabs to be loaded. This corresponds
+ // to the "SessionRestore.AllTabsLoaded" metric and its _XX variants
+ // (vaguely named for historical reasons, as it predates the concept of
+ // deferred tabs).
+ base::TimeDelta non_deferred_tabs_loaded;
+
+ // The maximum number of tabs loading in parallel. This corresponds to the
+ // "SessionRestore.ParallelTabLoads" metric.
+ size_t parallel_tab_loads;
+ };
+
+ // The StatsReportingDelegate is responsible for delivering statistics
+ // reported by the SessionRestoreStatsCollector.
+ class StatsReportingDelegate;
+
+ // An implementation of StatsReportingDelegate for reporting via UMA.
+ class UmaStatsReportingDelegate;
+
+ // Constructs a SessionRestoreStatsCollector.
+ SessionRestoreStatsCollector(
+ const base::TimeTicks& restore_started,
+ scoped_ptr<StatsReportingDelegate> reporting_delegate);
+
+ // Adds new tabs to the list of tracked tabs.
+ void TrackTabs(const std::vector<SessionRestoreDelegate::RestoredTab>& tabs);
+
+ // Called to indicate that the loading of a tab has been deferred by session
+ // restore.
+ void DeferTab(content::NavigationController* tab);
+
+ // Exposed for unittesting.
+ const TabLoaderStats& tab_loader_stats() const { return tab_loader_stats_; }
private:
+ friend class TestSessionRestoreStatsCollector;
friend class base::RefCounted<SessionRestoreStatsCollector>;
- using RenderWidgetHostSet = std::set<content::RenderWidgetHost*>;
+ enum TabLoadingState { TAB_IS_NOT_LOADING, TAB_IS_LOADING, TAB_IS_LOADED };
+
+ // State that is tracked for a tab while it is being observed.
+ struct TabState {
+ explicit TabState(content::NavigationController* controller);
+
+ // The NavigationController associated with the tab. This is the primary
+ // index for it and is never null.
+ content::NavigationController* controller;
+
+ // The RenderWidgetHost associated with the tab. This is the secondary
+ // index and starts out being null. If it is not null it is because the tab
+ // is actively loading or waiting to be painted.
+ content::RenderWidgetHost* render_widget_host;
+
+ // Set to true if the tab has been deferred by the TabLoader.
+ bool is_deferred;
+
+ // The current loading state of the tab.
+ TabLoadingState loading_state;
+ };
+
+ // Maps a NavigationController to its state. This is the primary map and
+ // physically houses the state.
+ using NavigationControllerMap =
+ std::map<content::NavigationController*, TabState>;
- explicit SessionRestoreStatsCollector(const base::TimeTicks& restore_started);
~SessionRestoreStatsCollector() override;
- // NotificationObserver method.
+ // NotificationObserver method. This is the workhorse of the class and drives
+ // all state transitions.
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
- // Adds new tabs to the list of tracked tabs.
- void AddTabs(const std::vector<SessionRestoreDelegate::RestoredTab>& tabs);
-
- // Called when a tab is no longer tracked.
+ // Called when a tab is no longer tracked. This is called by the 'Observe'
+ // notification callback. Takes care of unregistering all observers and
+ // removing the tab from all internal data structures.
void RemoveTab(content::NavigationController* tab);
- // Registers for relevant notifications for a tab.
- void RegisterForNotifications(content::NavigationController* tab);
+ // Registers for relevant notifications for a tab and inserts the tab into
+ // to tabs_tracked_ map. Return a pointer to the newly created TabState.
+ TabState* RegisterForNotifications(content::NavigationController* tab);
// Returns the RenderWidgetHost of a tab.
content::RenderWidgetHost* GetRenderWidgetHost(
content::NavigationController* tab);
- // Have we recorded the times for a foreground tab load?
+ // Returns the tab state, nullptr if not found.
+ TabState* GetTabState(content::NavigationController* tab);
+ TabState* GetTabState(content::RenderWidgetHost* tab);
+
+ // Marks a tab as loading.
+ void MarkTabAsLoading(TabState* tab_state);
+
+ // Checks to see if the SessionRestoreStatsCollector has finished collecting,
+ // and if so, releases the self reference to the shared pointer.
+ void ReleaseIfDoneTracking();
+
+ // Testing seam for configuring the tick clock in use.
+ void set_tick_clock(scoped_ptr<base::TickClock> tick_clock) {
+ tick_clock_ = tick_clock.Pass();
+ }
+
+ // Has ReleaseIfDoneTracking determined that there are no non-deferred tabs to
+ // track?
+ bool done_tracking_non_deferred_tabs_;
+
+ // Has the time for foreground tab load been recorded?
bool got_first_foreground_load_;
- // Have we recorded the times for a foreground tab paint?
+ // Has the time for foreground tab paint been recorded?
bool got_first_paint_;
// The time the restore process started.
- base::TimeTicks restore_started_;
+ const base::TimeTicks restore_started_;
- // The renderers we have started loading into.
- RenderWidgetHostSet render_widget_hosts_loading_;
+ // List of tracked tabs, mapped to their TabState.
+ NavigationControllerMap tabs_tracked_;
- // The renderers we have loaded and are waiting on to paint.
- RenderWidgetHostSet render_widget_hosts_to_paint_;
+ // Counts the number of non-deferred tabs that the
+ // SessionRestoreStatsCollector is waiting to see load.
+ size_t waiting_for_load_tab_count_;
- // List of tracked tabs.
- std::set<content::NavigationController*> tabs_tracked_;
+ // Counts the current number of actively loading tabs.
+ size_t loading_tab_count_;
- // The number of tabs that have been restored.
- int tab_count_;
-
- // Max number of tabs that were loaded in parallel (for metrics).
- size_t max_parallel_tab_loads_;
+ // Counts the number of deferred tabs.
+ size_t deferred_tab_count_;
// Notification registrar.
content::NotificationRegistrar registrar_;
- // To keep the collector alive as long as needed.
- scoped_refptr<SessionRestoreStatsCollector> this_retainer_;
+ // Statistics gathered regarding the TabLoader.
+ TabLoaderStats tab_loader_stats_;
+
+ // The source of ticks used for taking timing information. This is
+ // configurable as a testing seam. Defaults to using base::DefaultTickClock,
+ // which in turn uses base::TimeTicks.
+ scoped_ptr<base::TickClock> tick_clock_;
- // The shared SessionRestoreNotifier instance for all SessionRestores running
- // at this time.
- static SessionRestoreStatsCollector* shared_collector_;
+ // The reporting delegate used to report gathered statistics.
+ scoped_ptr<StatsReportingDelegate> reporting_delegate_;
+
+ // For keeping SessionRestoreStatsCollector alive while it is still working
+ // even if no TabLoader references it. The object only lives on if it still
+ // has deferred tabs remaining from an interrupted session restore.
+ scoped_refptr<SessionRestoreStatsCollector> this_retainer_;
DISALLOW_COPY_AND_ASSIGN(SessionRestoreStatsCollector);
};
+// An abstract reporting delegate is used as a testing seam.
+class SessionRestoreStatsCollector::StatsReportingDelegate {
+ public:
+ StatsReportingDelegate() {}
+ virtual ~StatsReportingDelegate() {}
+
+ // Called when TabLoader has completed its work.
+ virtual void ReportTabLoaderStats(const TabLoaderStats& tab_loader_stats) = 0;
+
+ // Called when a tab has been deferred.
+ virtual void ReportTabDeferred() = 0;
+
+ // Called when a deferred tab has been loaded.
+ virtual void ReportDeferredTabLoaded() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StatsReportingDelegate);
+};
+
+// The default reporting delegate, which reports statistics via UMA.
+class SessionRestoreStatsCollector::UmaStatsReportingDelegate
+ : public StatsReportingDelegate {
+ public:
+ UmaStatsReportingDelegate();
+ ~UmaStatsReportingDelegate() override {}
+
+ // StatsReportingDelegate:
+ void ReportTabLoaderStats(const TabLoaderStats& tab_loader_stats) override;
+ void ReportTabDeferred() override;
+ void ReportDeferredTabLoaded() override;
+
+ private:
+ // Has ReportTabDeferred been called?
+ bool got_report_tab_deferred_;
+
+ DISALLOW_COPY_AND_ASSIGN(UmaStatsReportingDelegate);
+};
+
#endif // CHROME_BROWSER_SESSIONS_SESSION_RESTORE_STATS_COLLECTOR_H_
« no previous file with comments | « chrome/browser/sessions/session_restore_delegate.cc ('k') | chrome/browser/sessions/session_restore_stats_collector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698