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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #import <UIKit/UIKit.h>
6
7 #import "ios/chrome/today_extension/today_metrics_logger.h"
8
9 #include "base/base64.h"
10 #include "base/cpu.h"
11 #include "base/mac/bind_objc_block.h"
12 #import "base/mac/scoped_nsobject.h"
13 #include "base/metrics/histogram_base.h"
14 #include "base/metrics/statistics_recorder.h"
15 #include "base/strings/sys_string_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/sys_info.h"
18 #include "components/metrics/metrics_log.h"
19 #include "components/metrics/metrics_log_uploader.h"
20 #include "components/metrics/metrics_pref_names.h"
21 #include "components/metrics/metrics_service_client.h"
22 #include "components/metrics/net/version_utils.h"
23 #include "components/prefs/json_pref_store.h"
24 #include "components/prefs/pref_registry_simple.h"
25 #include "components/prefs/pref_service.h"
26 #include "components/prefs/pref_service_factory.h"
27 #include "components/prefs/value_map_pref_store.h"
28 #include "components/variations/active_field_trials.h"
29 #include "components/version_info/version_info.h"
30 #import "ios/chrome/common/app_group/app_group_constants.h"
31 #import "ios/chrome/common/app_group/app_group_metrics.h"
32 #import "ios/chrome/common/app_group/app_group_metrics_client.h"
33 #include "ios/chrome/common/channel_info.h"
34
35 namespace {
36
37 // User default key to keep track of the current log session ID. Increased every
38 // time a log is created. This ID must be offset using
39 // app_group::AppGroupSessionID.
40 NSString* const kTodayExtensionMetricsSessionID = @"MetricsSessionID";
41
42 // User default key to the current log serialized. In case of an extension
43 // restart, this log can be written to disk for upload.
44 NSString* const kTodayExtensionMetricsCurrentLog = @"MetricsCurrentLog";
45
46 // Maximum number of event in a log.
47 const int kMaxEventsPerLog = 1000;
48
49 // Maximum age of a log.
50 const int kMaxLogLifeTimeInSeconds = 86400;
51
52 // A simple implementation of metrics::MetricsServiceClient.
53 // As logs are uploaded by Chrome application, not all methods are needed.
54 // Only the method needed to initialize the metrics logs are implementsd.
55 class TodayMetricsServiceClient : public metrics::MetricsServiceClient {
56 public:
57 TodayMetricsServiceClient() {}
58 metrics::MetricsService* GetMetricsService() override;
59 void SetMetricsClientId(const std::string& client_id) override;
60 int32_t GetProduct() override;
61 std::string GetApplicationLocale() override;
62 bool GetBrand(std::string* brand_code) override;
63 metrics::SystemProfileProto::Channel GetChannel() override;
64 std::string GetVersionString() override;
65 void OnLogUploadComplete() override;
66 void InitializeSystemProfileMetrics(
67 const base::Closure& done_callback) override;
68 void CollectFinalMetricsForLog(const base::Closure& done_callback) override;
69 std::unique_ptr<metrics::MetricsLogUploader> CreateUploader(
70 const base::Callback<void(int)>& on_upload_complete) override;
71 base::TimeDelta GetStandardUploadInterval() override;
72
73 private:
74 DISALLOW_COPY_AND_ASSIGN(TodayMetricsServiceClient);
75 };
76
77 class TodayMetricsLog : public metrics::MetricsLog {
78 public:
79 // Creates a new today metrics log of the specified type.
80 // TodayMetricsLog is similar to metrics::MetricsLog but allow serialization
81 // of open logs.
82 TodayMetricsLog(const std::string& client_id,
83 int session_id,
84 LogType log_type,
85 TodayMetricsServiceClient* client,
86 PrefService* local_state);
87
88 // Fills |encoded_log| with the serialized protobuf representation of the
89 // record. Can be called even on open log.
90 void GetOpenEncodedLog(std::string* encoded_log) const;
91
92 private:
93 DISALLOW_COPY_AND_ASSIGN(TodayMetricsLog);
94 };
95
96 metrics::MetricsService* TodayMetricsServiceClient::GetMetricsService() {
97 NOTREACHED();
98 return nullptr;
99 }
100
101 void TodayMetricsServiceClient::SetMetricsClientId(
102 const std::string& client_id) {
103 NOTREACHED();
104 }
105
106 int32_t TodayMetricsServiceClient::GetProduct() {
107 return metrics::ChromeUserMetricsExtension::CHROME;
108 }
109
110 bool TodayMetricsServiceClient::GetBrand(std::string* brand_code) {
111 base::scoped_nsobject<NSUserDefaults> shared_defaults(
112 [[NSUserDefaults alloc] initWithSuiteName:app_group::ApplicationGroup()]);
113
114 NSString* ns_brand_code = [shared_defaults
115 stringForKey:base::SysUTF8ToNSString(app_group::kBrandCode)];
116 if (!ns_brand_code)
117 return false;
118
119 *brand_code = base::SysNSStringToUTF8(ns_brand_code);
120 return true;
121 }
122
123 metrics::SystemProfileProto::Channel TodayMetricsServiceClient::GetChannel() {
124 return metrics::AsProtobufChannel(::GetChannel());
125 }
126
127 std::string TodayMetricsServiceClient::GetApplicationLocale() {
128 return base::SysNSStringToUTF8(
129 [[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]);
130 }
131
132 std::string TodayMetricsServiceClient::GetVersionString() {
133 return metrics::GetVersionString();
134 }
135
136 void TodayMetricsServiceClient::OnLogUploadComplete() {
137 NOTREACHED();
138 }
139
140 void TodayMetricsServiceClient::InitializeSystemProfileMetrics(
141 const base::Closure& done_callback) {
142 NOTREACHED();
143 }
144
145 void TodayMetricsServiceClient::CollectFinalMetricsForLog(
146 const base::Closure& done_callback) {
147 NOTREACHED();
148 }
149
150 std::unique_ptr<metrics::MetricsLogUploader>
151 TodayMetricsServiceClient::CreateUploader(
152 const base::Callback<void(int)>& on_upload_complete) {
153 NOTREACHED();
154 return nullptr;
155 }
156
157 base::TimeDelta TodayMetricsServiceClient::GetStandardUploadInterval() {
158 NOTREACHED();
159 return base::TimeDelta::FromSeconds(0);
160 }
161
162 TodayMetricsLog::TodayMetricsLog(const std::string& client_id,
163 int session_id,
164 LogType log_type,
165 TodayMetricsServiceClient* client,
166 PrefService* local_state)
167 : metrics::MetricsLog(client_id,
168 session_id,
169 log_type,
170 client,
171 local_state) {}
172
173 void TodayMetricsLog::GetOpenEncodedLog(std::string* encoded_log) const {
174 uma_proto()->SerializeToString(encoded_log);
175 }
176
177 } // namespace
178
179 TodayMetricsLogger* TodayMetricsLogger::GetInstance() {
180 // |logger| is a singleton that should live as long as the application.
181 // We do not delete it and it will be deleted when the application dies.
182 static TodayMetricsLogger* logger = new TodayMetricsLogger();
183 return logger;
184 }
185
186 void TodayMetricsLogger::RecordUserAction(base::UserMetricsAction action) {
187 if (!log_ && !CreateNewLog()) {
188 return;
189 }
190 log_->RecordUserAction(action.str_);
191 PersistLogs();
192 }
193
194 void TodayMetricsLogger::PersistLogs() {
195 histogram_snapshot_manager_.PrepareDeltas(
196 base::StatisticsRecorder::begin(false), base::StatisticsRecorder::end(),
197 base::Histogram::kNoFlags, base::Histogram::kNoFlags);
198 std::string encoded_log;
199 log_->GetOpenEncodedLog(&encoded_log);
200 NSData* ns_encoded_log =
201 [NSData dataWithBytes:encoded_log.c_str() length:encoded_log.length()];
202 [[NSUserDefaults standardUserDefaults]
203 setObject:ns_encoded_log
204 forKey:kTodayExtensionMetricsCurrentLog];
205 if (log_->num_events() >= kMaxEventsPerLog ||
206 (base::TimeTicks::Now() - log_->creation_time()).InSeconds() >=
207 kMaxLogLifeTimeInSeconds) {
208 CreateNewLog();
209 }
210 }
211
212 bool TodayMetricsLogger::CreateNewLog() {
213 id previous_log = [[NSUserDefaults standardUserDefaults]
214 dataForKey:kTodayExtensionMetricsCurrentLog];
215 if (previous_log) {
216 app_group::client_app::AddPendingLog(previous_log,
217 app_group::APP_GROUP_TODAY_EXTENSION);
218 thread_pool_->PostTask(
219 FROM_HERE, base::Bind(&app_group::client_app::CleanOldPendingLogs));
220 }
221
222 base::scoped_nsobject<NSUserDefaults> shared_defaults(
223 [[NSUserDefaults alloc] initWithSuiteName:app_group::ApplicationGroup()]);
224
225 NSString* client_id = [shared_defaults
226 stringForKey:base::SysUTF8ToNSString(app_group::kChromeAppClientID)];
227 NSString* enabled_date = [shared_defaults
228 stringForKey:base::SysUTF8ToNSString(app_group::kUserMetricsEnabledDate)];
229
230 NSString* install_date = [shared_defaults
231 stringForKey:base::SysUTF8ToNSString(app_group::kInstallDate)];
232
233 if (!client_id || !enabled_date || !install_date) {
234 return false;
235 }
236
237 int session_id = [[NSUserDefaults standardUserDefaults]
238 integerForKey:kTodayExtensionMetricsSessionID];
239 [[NSUserDefaults standardUserDefaults]
240 setInteger:session_id + 1
241 forKey:kTodayExtensionMetricsSessionID];
242 session_id = app_group::AppGroupSessionID(
243 session_id, app_group::APP_GROUP_TODAY_EXTENSION);
244 log_.reset(new TodayMetricsLog(base::SysNSStringToUTF8(client_id), session_id,
245 metrics::MetricsLog::ONGOING_LOG,
246 metrics_service_client_.get(),
247 pref_service_.get()));
248
249 log_->RecordEnvironment(std::vector<metrics::MetricsProvider*>(),
250 std::vector<variations::ActiveGroupId>(),
251 [install_date longLongValue],
252 [enabled_date longLongValue]);
253
254 return true;
255 }
256
257 TodayMetricsLogger::TodayMetricsLogger()
258 : pref_registry_(new PrefRegistrySimple()),
259 thread_pool_(
260 new base::SequencedWorkerPool(2,
261 "LoggerPool",
262 base::TaskPriority::BACKGROUND)),
263 metrics_service_client_(new TodayMetricsServiceClient()),
264 histogram_snapshot_manager_(this) {
265 metrics::MetricsLog::RegisterPrefs(pref_registry_.get());
266
267 NSString* url = [[NSSearchPathForDirectoriesInDomains(
268 NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]
269 stringByAppendingPathComponent:@"Application Support/localstate"];
270 base::FilePath path(base::SysNSStringToUTF8(url));
271 sequenced_task_runner_ =
272 JsonPrefStore::GetTaskRunnerForFile(path, thread_pool_.get());
273 PrefServiceFactory factory;
274 factory.set_extension_prefs(value_map_prefs_.get());
275 factory.SetUserPrefsFile(path, sequenced_task_runner_.get());
276 pref_service_ = factory.Create(pref_registry_.get());
277 base::StatisticsRecorder::Initialize();
278 }
279
280 TodayMetricsLogger::~TodayMetricsLogger() {}
281
282 void TodayMetricsLogger::RecordDelta(const base::HistogramBase& histogram,
283 const base::HistogramSamples& snapshot) {
284 log_->RecordHistogramDelta(histogram.histogram_name(), snapshot);
285 }
286
287 void TodayMetricsLogger::InconsistencyDetected(
288 base::HistogramBase::Inconsistency problem) {
289 UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesBrowser", problem,
290 base::HistogramBase::NEVER_EXCEEDED_VALUE);
291 }
292
293 void TodayMetricsLogger::UniqueInconsistencyDetected(
294 base::HistogramBase::Inconsistency problem) {
295 UMA_HISTOGRAM_ENUMERATION("Histogram.InconsistenciesBrowserUnique", problem,
296 base::HistogramBase::NEVER_EXCEEDED_VALUE);
297 }
298
299 void TodayMetricsLogger::InconsistencyDetectedInLoggedCount(int amount) {
300 UMA_HISTOGRAM_COUNTS("Histogram.InconsistentSnapshotBrowser",
301 std::abs(amount));
302 }
OLDNEW
« 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