diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
commit | 09911bf300f1a419907a9412154760efd0b7abc3 (patch) | |
tree | f131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/metrics_service.h | |
parent | 586acc5fe142f498261f52c66862fa417c3d52d2 (diff) | |
download | chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2 |
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/metrics_service.h')
-rw-r--r-- | chrome/browser/metrics_service.h | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/chrome/browser/metrics_service.h b/chrome/browser/metrics_service.h new file mode 100644 index 0000000..d16c6ca --- /dev/null +++ b/chrome/browser/metrics_service.h @@ -0,0 +1,345 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file defines a service that collects information about the user +// experience in order to help improve future versions of the app. + +#ifndef CHROME_BROWSER_METRICS_SERVICE_H__ +#define CHROME_BROWSER_METRICS_SERVICE_H__ + +#include <list> +#include <map> +#include <set> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/histogram.h" +#include "base/scoped_ptr.h" +#include "base/values.h" +#include "chrome/browser/metrics_log.h" +#include "chrome/browser/url_fetcher.h" +#include "chrome/common/notification_service.h" +#include "webkit/glue/webplugin.h" + +class BookmarkBarModel; +class BookmarkBarNode; +class PrefService; +class Profile; +class TemplateURLModel; + +// This is used to quickly log stats from plugin-related notifications in +// MetricsService::plugin_stats_buffer_. The buffer's contents are transferred +// out when Local State is periodically saved. The information is then +// reported to the UMA server on next launch. +struct PluginStats { + public: + PluginStats() : process_launches(0), process_crashes(0), instances(0) {} + + // The number of times that the given plugin process has been launched + int process_launches; + + // The number of times that the given plugin process has crashed + int process_crashes; + + // The number of instances of this plugin that have been created. + // An instance is a DOM object rendered by this plugin during a page load. + int instances; +}; + +class MetricsService : public NotificationObserver, + public URLFetcher::Delegate { + public: + MetricsService(); + virtual ~MetricsService(); + + // At startup, prefs needs to be called with a list of all the pref names and + // types we'll be using. + static void RegisterPrefs(PrefService* local_state); + + // Sets and gets whether metrics recording is active. + // SetRecording(false) also forces a persistent save of logging state (if + // anything has been recorded, or transmitted). + void SetRecording(bool enabled); + bool IsRecording() const; + + // Enable/disable transmission of accumulated logs and crash reports (dumps). + // Return value "true" indicates setting was definitively set as requested). + // Return value of "false" indicates that the enable state is effectively + // stuck in the other logical setting. + // Google Update maintains the authoritative preference in the registry, so + // the caller *might* not be able to actually change the setting. + // It is always possible to set this to at least one value, which matches the + // current value reported by querying Google Update. + bool EnableReporting(bool enable); + + // Implementation of NotificationObserver + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // This should be called when the application is shutting down, to record + // the fact that this was a clean shutdown in the stability metrics. + void RecordCleanShutdown(); + + // Invoked when we get a WM_SESSIONEND. This places a value in prefs that is + // reset when RecordCompletedSessionEnd is invoked. + void RecordStartOfSessionEnd(); + + // This should be called when the application is shutting down. It records + // that session end was successful. + void RecordCompletedSessionEnd(); + + // Callback to let us knew that the plugin list is warmed up. + void OnGetPluginListTaskComplete(); + + // Save any unsent logs into a persistent store in a pref. We always do this + // at shutdown, but we can do it as we reduce the list as well. + void StoreUnsentLogs(); + + private: + // The MetricsService has a lifecycle that is stored as a state. + // See metrics_service.cc for description of this lifecycle. + enum State { + INITIALIZED, // Constructor was called. + PLUGIN_LIST_REQUESTED, // Waiting for DLL list to be loaded. + PLUGIN_LIST_ARRIVED, // Waiting for timer to send initial log. + INITIAL_LOG_READY, // Initial log generated, and waiting for reply. + SEND_OLD_INITIAL_LOGS, // Sending unsent logs from previous session. + SENDING_OLD_LOGS, // Sending unsent logs from previous session. + SENDING_CURRENT_LOGS, // Sending standard current logs as they acrue. + }; + + // Maintain a map of histogram names to the sample stats we've sent. + typedef std::map<std::string, Histogram::SampleSet> LoggedSampleMap; + + class GetPluginListTask; + class GetPluginListTaskComplete; + + // Set up client ID, session ID, etc. + void InitializeMetricsState(); + // Generates a new client ID to use to identify self to metrics server. + static std::string GenerateClientID(); + // Schedule the next save of LocalState information. This is called + // automatically by the task that performs each save to schedule the next one. + void ScheduleNextStateSave(); + // Save the LocalState information immediately. This should not be called by + // anybody other than the scheduler to avoid doing too many writes. When you + // make a change, call ScheduleNextStateSave() instead. + void SaveLocalState(); + + // Called to start recording user experience metrics. + void StartRecording(); + // Called to stop recording user experience metrics. The caller takes + // ownership of the resulting MetricsLog object via the log parameter, + // or passes in NULL to indicate that the log should simply be deleted. + void StopRecording(MetricsLog** log); + void ListenerRegistration(bool start_listening); + // Adds or Removes (depending on the value of is_add) the given observer + // to the given notification type for all sources. + static void AddOrRemoveObserver(NotificationObserver* observer, + NotificationType type, + bool is_add); + + // Deletes pending_log_ and current_log_, and pushes their text into the + // appropriate unsent_log vectors. + void PushPendingLogsToUnsentLists(); + + // Start timer for next log transmission. + void StartLogTransmissionTimer(); + // Do not call TryToStartTransmission() directly. + // Use StartLogTransmissionTimer() to schedule a call. + void TryToStartTransmission(); + // Internal function to collect process memory information. + void CollectMemoryDetails(); + // Check to see if there is a log that needs to be, or is being, transmitted. + bool pending_log() const { + return pending_log_ || !pending_log_text_.empty(); + } + // Check to see if there are any unsent logs from previous sessions. + bool unsent_logs() const { + return !unsent_initial_logs_.empty() || !unsent_ongoing_logs_.empty(); + } + // Record stats, client ID, Session ID, etc. in a special "first" log. + void PrepareInitialLog(); + // Pull copies of unsent logs from prefs into instance variables. + void RecallUnsentLogs(); + // Convert pending_log_ to XML in pending_log_text_ for transmission. + void PreparePendingLogText(); + // Convert pending_log_ to XML, compress it, and prepare to pass to server. + void PreparePendingLogForTransmission(); + // Discard pending_log_, and clear pending_log_text_. Called after processing + // of this log is complete. + void DiscardPendingLog(); + // Compress the report log in input using bzip2, store the result in output. + bool Bzip2Compress(const std::string& input, std::string* output); + // Implementation of URLFetcher::Delegate. Called after transmission + // completes (either successfully or with failure). + virtual void OnURLFetchComplete(const URLFetcher* source, + const GURL& url, + const URLRequestStatus& status, + int response_code, + const ResponseCookies& cookies, + const std::string& data); + // Extract the time interval suggested by the server for waiting after a log + // transmision before starting the next transmision. The result is set into + // interlog_duration_. + void GetSuggestedInterlogTime(const std::string& server_data); + + // Records a window-related notification. + void LogWindowChange(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Records a renderer process crash. + void LogRendererCrash(); + + // Records a renderer process hang. + void LogRendererHang(); + + // Records the desktop security status of a renderer in the sandbox at + // creation time. + void LogRendererInSandbox(bool on_sandbox_desktop); + + // Set the value in preferences for for the number of bookmarks and folders + // in node. The pref key for the number of bookmarks in num_bookmarks_key and + // the pref key for number of folders in num_folders_key. + void LogBookmarks(BookmarkBarNode* node, + const wchar_t* num_bookmarks_key, + const wchar_t* num_folders_key); + + // Sets preferences for the for the number of bookmarks in model. + void LogBookmarks(BookmarkBarModel* model); + + // Records a plugin-related notification. These are recorded to an in-object + // buffer because these notifications are sent on page load, and we don't + // want to slow that down. + void LogPluginChange(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Logs keywords specific metrics. Keyword metrics are recorded in the + // profile specific metrics. + void LogKeywords(const TemplateURLModel* url_model); + + // Saves plugin-related updates from the in-object buffer to Local State + // for retrieval next time we send a Profile log (generally next launch). + void RecordPluginChanges(PrefService* pref); + + // Records state that should be periodically saved, like uptime and + // buffered plugin stability statistics. + void RecordCurrentState(PrefService* pref); + + // Record complete list of histograms. Called when we close a log. + void RecordCurrentHistograms(); + // Record a specific histogram. + void RecordHistogram(const Histogram& histogram); + + // Logs the initiation of a page load + void LogLoadStarted(); + + // Records a page load notification. + void LogLoadComplete(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Adds a profile metric with the specified key/value pair. + void AddProfileMetric(Profile* profile, const std::wstring& key, + int value); + + // Checks whether a notification can be logged. + bool CanLogNotification(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Sets the value of the specified path in prefs and schedules a save. + void RecordBooleanPrefValue(const wchar_t* path, bool value); + + bool recording_; + bool reporting_; // if false, metrics logs are discarded rather than sent + + // The progession of states made by the browser are recorded in the following + // state. + State state_; + + // A log that we are currently transmiting, or about to try to transmit. + MetricsLog* pending_log_; + // An alternate form of pending_log_. We persistently save this text version + // into prefs if we can't transmit it. As a result, sometimes all we have is + // the text version (recalled from a previous session). + std::string pending_log_text_; + // The outstanding transmission appears as a URL Fetch operation. + scoped_ptr<URLFetcher> current_fetch_; + // The log that we are still appending to. + MetricsLog* current_log_; + // The identifier that's sent to the server with the log reports. + std::string client_id_; + // A number that identifies the how many times the app has been launched. + int session_id_; + + // When logs were not sent during a previous session they are queued to be + // sent instead of currently accumulating logs. We give preference to sending + // our inital log first, then unsent intial logs, then unsent ongoing logs. + // Unsent logs are gathered at shutdown, and save in a persistent pref, one + // log in each string in the following arrays. + // Note that the vector has the oldest logs listed first (early in the + // vector), and we'll discard old logs if we have gathered too many logs. + std::vector<std::string> unsent_initial_logs_; + std::vector<std::string> unsent_ongoing_logs_; + + typedef std::map<uintptr_t, int> WindowMap; + WindowMap window_map_; + int next_window_id_; + + // Buffer of plugin notifications for quick access. See PluginStats + // documentation above for more details. + std::map<std::wstring, PluginStats> plugin_stats_buffer_; + + ScopedRunnableMethodFactory<MetricsService> log_sender_factory_; + ScopedRunnableMethodFactory<MetricsService> state_saver_factory_; + + // Dictionary containing all the profile specific metrics. This is set + // at creation time from the prefs. + scoped_ptr<DictionaryValue> profile_dictionary_; + + // For histograms, record what we've already logged (as a sample for each + // histogram) so that we can send only the delta with the next log. + MetricsService::LoggedSampleMap logged_samples_; + + // The duration for which we build up a log. After that period, we try to + // send the log (unless another log is already pending). + TimeDelta interlog_duration_; + // Indicate that a timer for sending the next log has already been queued, + // or that a URLFetch (i.e., log transmission) is in progress. + bool timer_pending_; + + DISALLOW_EVIL_CONSTRUCTORS(MetricsService); +}; + +#endif // CHROME_BROWSER_METRICS_SERVICE_H__ |