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

Unified Diff: ios/chrome/today_extension/today_metrics_logger.mm

Issue 2586713002: Upstream code and resources for Chrome on iOS extensions. (Closed)
Patch Set: Created 4 years 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: ios/chrome/today_extension/today_metrics_logger.mm
diff --git a/ios/chrome/today_extension/today_metrics_logger.mm b/ios/chrome/today_extension/today_metrics_logger.mm
new file mode 100644
index 0000000000000000000000000000000000000000..859b9b2e4121b26f54ae794d147b082e7bdd3dd4
--- /dev/null
+++ b/ios/chrome/today_extension/today_metrics_logger.mm
@@ -0,0 +1,302 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <UIKit/UIKit.h>
+
+#import "ios/chrome/today_extension/today_metrics_logger.h"
+
+#include "base/base64.h"
+#include "base/cpu.h"
+#include "base/mac/bind_objc_block.h"
+#import "base/mac/scoped_nsobject.h"
+#include "base/metrics/histogram_base.h"
+#include "base/metrics/statistics_recorder.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/sys_info.h"
+#include "components/metrics/metrics_log.h"
+#include "components/metrics/metrics_log_uploader.h"
+#include "components/metrics/metrics_pref_names.h"
+#include "components/metrics/metrics_service_client.h"
+#include "components/metrics/net/version_utils.h"
+#include "components/prefs/json_pref_store.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/pref_service_factory.h"
+#include "components/prefs/value_map_pref_store.h"
+#include "components/variations/active_field_trials.h"
+#include "components/version_info/version_info.h"
+#import "ios/chrome/common/app_group/app_group_constants.h"
+#import "ios/chrome/common/app_group/app_group_metrics.h"
+#import "ios/chrome/common/app_group/app_group_metrics_client.h"
+#include "ios/chrome/common/channel_info.h"
+
+namespace {
+
+// User default key to keep track of the current log session ID. Increased every
+// time a log is created. This ID must be offset using
+// app_group::AppGroupSessionID.
+NSString* const kTodayExtensionMetricsSessionID = @"MetricsSessionID";
+
+// User default key to the current log serialized. In case of an extension
+// restart, this log can be written to disk for upload.
+NSString* const kTodayExtensionMetricsCurrentLog = @"MetricsCurrentLog";
+
+// Maximum number of event in a log.
+const int kMaxEventsPerLog = 1000;
+
+// Maximum age of a log.
+const int kMaxLogLifeTimeInSeconds = 86400;
+
+// A simple implementation of metrics::MetricsServiceClient.
+// As logs are uploaded by Chrome application, not all methods are needed.
+// Only the method needed to initialize the metrics logs are implementsd.
+class TodayMetricsServiceClient : public metrics::MetricsServiceClient {
+ public:
+ TodayMetricsServiceClient() {}
+ metrics::MetricsService* GetMetricsService() override;
+ void SetMetricsClientId(const std::string& client_id) override;
+ int32_t GetProduct() override;
+ std::string GetApplicationLocale() override;
+ bool GetBrand(std::string* brand_code) override;
+ metrics::SystemProfileProto::Channel GetChannel() override;
+ std::string GetVersionString() override;
+ void OnLogUploadComplete() override;
+ void InitializeSystemProfileMetrics(
+ const base::Closure& done_callback) override;
+ void CollectFinalMetricsForLog(const base::Closure& done_callback) override;
+ std::unique_ptr<metrics::MetricsLogUploader> CreateUploader(
+ const base::Callback<void(int)>& on_upload_complete) override;
+ base::TimeDelta GetStandardUploadInterval() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TodayMetricsServiceClient);
+};
+
+class TodayMetricsLog : public metrics::MetricsLog {
+ public:
+ // Creates a new today metrics log of the specified type.
+ // TodayMetricsLog is similar to metrics::MetricsLog but allow serialization
+ // of open logs.
+ TodayMetricsLog(const std::string& client_id,
+ int session_id,
+ LogType log_type,
+ TodayMetricsServiceClient* client,
+ PrefService* local_state);
+
+ // Fills |encoded_log| with the serialized protobuf representation of the
+ // record. Can be called even on open log.
+ void GetOpenEncodedLog(std::string* encoded_log) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TodayMetricsLog);
+};
+
+metrics::MetricsService* TodayMetricsServiceClient::GetMetricsService() {
+ NOTREACHED();
+ return nullptr;
+}
+
+void TodayMetricsServiceClient::SetMetricsClientId(
+ const std::string& client_id) {
+ NOTREACHED();
+}
+
+int32_t TodayMetricsServiceClient::GetProduct() {
+ return metrics::ChromeUserMetricsExtension::CHROME;
+}
+
+bool TodayMetricsServiceClient::GetBrand(std::string* brand_code) {
+ base::scoped_nsobject<NSUserDefaults> shared_defaults(
+ [[NSUserDefaults alloc] initWithSuiteName:app_group::ApplicationGroup()]);
+
+ NSString* ns_brand_code = [shared_defaults
+ stringForKey:base::SysUTF8ToNSString(app_group::kBrandCode)];
+ if (!ns_brand_code)
+ return false;
+
+ *brand_code = base::SysNSStringToUTF8(ns_brand_code);
+ return true;
+}
+
+metrics::SystemProfileProto::Channel TodayMetricsServiceClient::GetChannel() {
+ return metrics::AsProtobufChannel(::GetChannel());
+}
+
+std::string TodayMetricsServiceClient::GetApplicationLocale() {
+ return base::SysNSStringToUTF8(
+ [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]);
+}
+
+std::string TodayMetricsServiceClient::GetVersionString() {
+ return metrics::GetVersionString();
+}
+
+void TodayMetricsServiceClient::OnLogUploadComplete() {
+ NOTREACHED();
+}
+
+void TodayMetricsServiceClient::InitializeSystemProfileMetrics(
+ const base::Closure& done_callback) {
+ NOTREACHED();
+}
+
+void TodayMetricsServiceClient::CollectFinalMetricsForLog(
+ const base::Closure& done_callback) {
+ NOTREACHED();
+}
+
+std::unique_ptr<metrics::MetricsLogUploader>
+TodayMetricsServiceClient::CreateUploader(
+ const base::Callback<void(int)>& on_upload_complete) {
+ NOTREACHED();
+ return nullptr;
+}
+
+base::TimeDelta TodayMetricsServiceClient::GetStandardUploadInterval() {
+ NOTREACHED();
+ return base::TimeDelta::FromSeconds(0);
+}
+
+TodayMetricsLog::TodayMetricsLog(const std::string& client_id,
+ int session_id,
+ LogType log_type,
+ TodayMetricsServiceClient* client,
+ PrefService* local_state)
+ : metrics::MetricsLog(client_id,
+ session_id,
+ log_type,
+ client,
+ local_state) {}
+
+void TodayMetricsLog::GetOpenEncodedLog(std::string* encoded_log) const {
+ uma_proto()->SerializeToString(encoded_log);
+}
+
+} // namespace
+
+TodayMetricsLogger* TodayMetricsLogger::GetInstance() {
+ // |logger| is a singleton that should live as long as the application.
+ // We do not delete it and it will be deleted when the application dies.
+ static TodayMetricsLogger* logger = new TodayMetricsLogger();
+ return logger;
+}
+
+void TodayMetricsLogger::RecordUserAction(base::UserMetricsAction action) {
+ if (!log_ && !CreateNewLog()) {
+ return;
+ }
+ log_->RecordUserAction(action.str_);
+ PersistLogs();
+}
+
+void TodayMetricsLogger::PersistLogs() {
+ histogram_snapshot_manager_.PrepareDeltas(
+ base::StatisticsRecorder::begin(false), base::StatisticsRecorder::end(),
+ base::Histogram::kNoFlags, base::Histogram::kNoFlags);
+ std::string encoded_log;
+ log_->GetOpenEncodedLog(&encoded_log);
+ NSData* ns_encoded_log =
+ [NSData dataWithBytes:encoded_log.c_str() length:encoded_log.length()];
+ [[NSUserDefaults standardUserDefaults]
+ setObject:ns_encoded_log
+ forKey:kTodayExtensionMetricsCurrentLog];
+ if (log_->num_events() >= kMaxEventsPerLog ||
+ (base::TimeTicks::Now() - log_->creation_time()).InSeconds() >=
+ kMaxLogLifeTimeInSeconds) {
+ CreateNewLog();
+ }
+}
+
+bool TodayMetricsLogger::CreateNewLog() {
+ id previous_log = [[NSUserDefaults standardUserDefaults]
+ dataForKey:kTodayExtensionMetricsCurrentLog];
+ if (previous_log) {
+ app_group::client_app::AddPendingLog(previous_log,
+ app_group::APP_GROUP_TODAY_EXTENSION);
+ thread_pool_->PostTask(
+ FROM_HERE, base::Bind(&app_group::client_app::CleanOldPendingLogs));
+ }
+
+ base::scoped_nsobject<NSUserDefaults> shared_defaults(
+ [[NSUserDefaults alloc] initWithSuiteName:app_group::ApplicationGroup()]);
+
+ NSString* client_id = [shared_defaults
+ stringForKey:base::SysUTF8ToNSString(app_group::kChromeAppClientID)];
+ NSString* enabled_date = [shared_defaults
+ stringForKey:base::SysUTF8ToNSString(app_group::kUserMetricsEnabledDate)];
+
+ NSString* install_date = [shared_defaults
+ stringForKey:base::SysUTF8ToNSString(app_group::kInstallDate)];
+
+ if (!client_id || !enabled_date || !install_date) {
+ return false;
+ }
+
+ int session_id = [[NSUserDefaults standardUserDefaults]
+ integerForKey:kTodayExtensionMetricsSessionID];
+ [[NSUserDefaults standardUserDefaults]
+ setInteger:session_id + 1
+ forKey:kTodayExtensionMetricsSessionID];
+ session_id = app_group::AppGroupSessionID(
+ session_id, app_group::APP_GROUP_TODAY_EXTENSION);
+ log_.reset(new TodayMetricsLog(base::SysNSStringToUTF8(client_id), session_id,
+ metrics::MetricsLog::ONGOING_LOG,
+ metrics_service_client_.get(),
+ pref_service_.get()));
+
+ log_->RecordEnvironment(std::vector<metrics::MetricsProvider*>(),
+ std::vector<variations::ActiveGroupId>(),
+ [install_date longLongValue],
+ [enabled_date longLongValue]);
+
+ return true;
+}
+
+TodayMetricsLogger::TodayMetricsLogger()
+ : pref_registry_(new PrefRegistrySimple()),
+ thread_pool_(
+ new base::SequencedWorkerPool(2,
+ "LoggerPool",
+ base::TaskPriority::BACKGROUND)),
+ metrics_service_client_(new TodayMetricsServiceClient()),
+ histogram_snapshot_manager_(this) {
+ metrics::MetricsLog::RegisterPrefs(pref_registry_.get());
+
+ NSString* url = [[NSSearchPathForDirectoriesInDomains(
+ NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]
+ stringByAppendingPathComponent:@"Application Support/localstate"];
+ base::FilePath path(base::SysNSStringToUTF8(url));
+ sequenced_task_runner_ =
+ JsonPrefStore::GetTaskRunnerForFile(path, thread_pool_.get());
+ PrefServiceFactory factory;
+ factory.set_extension_prefs(value_map_prefs_.get());
+ factory.SetUserPrefsFile(path, sequenced_task_runner_.get());
+ pref_service_ = factory.Create(pref_registry_.get());
+ base::StatisticsRecorder::Initialize();
+}
+
+TodayMetricsLogger::~TodayMetricsLogger() {}
+
+void TodayMetricsLogger::RecordDelta(const base::HistogramBase& histogram,
+ const base::HistogramSamples& snapshot) {
+ log_->RecordHistogramDelta(histogram.histogram_name(), snapshot);
+}
+
+void TodayMetricsLogger::InconsistencyDetected(
+ base::HistogramBase::Inconsistency problem) {
+ UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesBrowser", problem,
+ base::HistogramBase::NEVER_EXCEEDED_VALUE);
+}
+
+void TodayMetricsLogger::UniqueInconsistencyDetected(
+ base::HistogramBase::Inconsistency problem) {
+ UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesBrowserUnique", problem,
+ base::HistogramBase::NEVER_EXCEEDED_VALUE);
+}
+
+void TodayMetricsLogger::InconsistencyDetectedInLoggedCount(int amount) {
+ UMA_HISTOGRAM_COUNTS("Histogram.InconsistentSnapshotBrowser",
+ std::abs(amount));
+}
« no previous file with comments | « ios/chrome/today_extension/today_metrics_logger.h ('k') | ios/chrome/today_extension/today_view_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698