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

Side by Side Diff: src/platform/metrics/metrics_daemon.cc

Issue 1863002: Add basic daily active use logging. (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: Address review comments. Created 10 years, 7 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
« no previous file with comments | « src/platform/metrics/metrics_daemon.h ('k') | src/platform/metrics/power_states.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS 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 #include "metrics_daemon.h" 5 #include "metrics_daemon.h"
6 #include "metrics_library.h" 6 #include "metrics_library.h"
7 7
8 #include <dbus/dbus-glib-lowlevel.h> 8 #include <dbus/dbus-glib-lowlevel.h>
9 #include <sys/file.h>
9 10
11 #include <base/eintr_wrapper.h>
10 #include <base/logging.h> 12 #include <base/logging.h>
11 13
12 #define SAFE_MESSAGE(e) (e.message ? e.message : "unknown error") 14 #define SAFE_MESSAGE(e) (e.message ? e.message : "unknown error")
13 #define DBUS_IFACE_CONNMAN_MANAGER "org.moblin.connman.Manager" 15 #define DBUS_IFACE_CONNMAN_MANAGER "org.moblin.connman.Manager"
14 #define DBUS_IFACE_POWER_MANAGER "org.chromium.Power.Manager" 16 #define DBUS_IFACE_POWER_MANAGER "org.chromium.Power.Manager"
17 #define DBUS_IFACE_SCREENSAVER_MANAGER "org.chromium.ScreenSaver.Manager"
18 #define DBUS_IFACE_SESSION_MANAGER "org.chromium.SessionManagerInterface"
19
20 // File to aggregate daily usage before sending to UMA.
21 // TODO(petkov): This file should probably live in a user-specific stateful
22 // location, e.g., /home/chronos/user.
23 static const char kDailyUseRecordFile[] = "/var/log/metrics/daily-usage";
24
25 static const int kSecondsPerMinute = 60;
26 static const int kMinutesPerHour = 60;
27 static const int kHoursPerDay = 24;
28 static const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour;
29 static const int kSecondsPerDay = kMinutesPerDay * kSecondsPerMinute;
30
31 // The daily use monitor is scheduled to a 1-minute interval after
32 // initial user activity and then it's exponentially backed off to
33 // 10-minute intervals. Although not required, the back off is
34 // implemented because the histogram buckets are spaced exponentially
35 // anyway and to avoid too frequent metrics daemon process wake-ups
36 // and file I/O.
37 static const int kUseMonitorIntervalInit = 1 * kSecondsPerMinute;
38 static const int kUseMonitorIntervalMax = 10 * kSecondsPerMinute;
15 39
16 // static 40 // static
17 const char* 41 const char* MetricsDaemon::kDBusMatches_[] = {
18 MetricsDaemon::dbus_matches_[] = {
19 "type='signal'," 42 "type='signal',"
20 "sender='org.moblin.connman'," 43 "sender='org.moblin.connman',"
21 "interface='" DBUS_IFACE_CONNMAN_MANAGER "'," 44 "interface='" DBUS_IFACE_CONNMAN_MANAGER "',"
22 "path='/'," 45 "path='/',"
23 "member='StateChanged'", 46 "member='StateChanged'",
24 47
25 "type='signal'," 48 "type='signal',"
26 "interface='" DBUS_IFACE_POWER_MANAGER "'," 49 "interface='" DBUS_IFACE_POWER_MANAGER "',"
27 "path='/'," 50 "path='/',"
28 "member='PowerStateChanged'", 51 "member='PowerStateChanged'",
52
53 "type='signal',"
54 "interface='" DBUS_IFACE_SCREENSAVER_MANAGER "',"
55 "path='/',"
56 "member='LockStateChanged'",
57
58 "type='signal',"
59 "sender='org.chromium.SessionManager',"
60 "interface='" DBUS_IFACE_SESSION_MANAGER "',"
61 "path='/org/chromium/SessionManager',"
62 "member='SessionStateChanged'",
29 }; 63 };
30 64
31 // static 65 // static
32 const char * 66 const char* MetricsDaemon::kNetworkStates_[] = {
33 MetricsDaemon::network_states_[MetricsDaemon::kNumberNetworkStates] = {
34 #define STATE(name, capname) #name, 67 #define STATE(name, capname) #name,
35 #include "network_states.h" 68 #include "network_states.h"
36 }; 69 };
37 70
38 // static 71 // static
39 const char * 72 const char* MetricsDaemon::kPowerStates_[] = {
40 MetricsDaemon::power_states_[MetricsDaemon::kNumberPowerStates] = {
41 #define STATE(name, capname) #name, 73 #define STATE(name, capname) #name,
42 #include "power_states.h" 74 #include "power_states.h"
43 }; 75 };
44 76
77 // static
78 const char* MetricsDaemon::kScreenSaverStates_[] = {
79 #define STATE(name, capname) #name,
80 #include "screensaver_states.h"
81 };
82
83 // static
84 const char* MetricsDaemon::kSessionStates_[] = {
85 #define STATE(name, capname) #name,
86 #include "session_states.h"
87 };
88
45 void MetricsDaemon::Run(bool run_as_daemon, bool testing) { 89 void MetricsDaemon::Run(bool run_as_daemon, bool testing) {
46 Init(testing); 90 Init(testing);
47 if (!run_as_daemon || daemon(0, 0) == 0) { 91 if (!run_as_daemon || daemon(0, 0) == 0) {
48 Loop(); 92 Loop();
49 } 93 }
50 } 94 }
51 95
52 void MetricsDaemon::Init(bool testing) { 96 void MetricsDaemon::Init(bool testing) {
53 testing_ = testing; 97 testing_ = testing;
54 network_state_ = kUnknownNetworkState;
55 network_state_changed_ = 0;
56 power_state_ = kUnknownPowerState;
57 98
58 g_thread_init(NULL); 99 g_thread_init(NULL);
59 g_type_init(); 100 g_type_init();
60 dbus_g_thread_init(); 101 dbus_g_thread_init();
61 102
62 DBusError error; 103 DBusError error;
63 dbus_error_init(&error); 104 dbus_error_init(&error);
64 105
65 DBusConnection *connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); 106 DBusConnection *connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
66 LOG_IF(FATAL, dbus_error_is_set(&error)) << 107 LOG_IF(FATAL, dbus_error_is_set(&error)) <<
67 "No D-Bus connection: " << SAFE_MESSAGE(error); 108 "No D-Bus connection: " << SAFE_MESSAGE(error);
68 109
69 dbus_connection_setup_with_g_main(connection, NULL); 110 dbus_connection_setup_with_g_main(connection, NULL);
70 111
71 // Registers D-Bus matches for the signals we would like to catch. 112 // Registers D-Bus matches for the signals we would like to catch.
72 for (unsigned int m = 0; m < sizeof(dbus_matches_) / sizeof(char *); m++) { 113 for (unsigned int m = 0; m < sizeof(kDBusMatches_) / sizeof(char *); m++) {
73 const char* match = dbus_matches_[m]; 114 const char* match = kDBusMatches_[m];
74 LOG(INFO) << "adding dbus match: " << match; 115 DLOG(INFO) << "adding dbus match: " << match;
75 dbus_bus_add_match(connection, match, &error); 116 dbus_bus_add_match(connection, match, &error);
76 LOG_IF(FATAL, dbus_error_is_set(&error)) << 117 LOG_IF(FATAL, dbus_error_is_set(&error)) <<
77 "unable to add a match: " << SAFE_MESSAGE(error); 118 "unable to add a match: " << SAFE_MESSAGE(error);
78 } 119 }
79 120
80 // Adds the D-Bus filter routine to be called back whenever one of 121 // Adds the D-Bus filter routine to be called back whenever one of
81 // the registered D-Bus matches is successful. The daemon is not 122 // the registered D-Bus matches is successful. The daemon is not
82 // activated for D-Bus messages that don't match. 123 // activated for D-Bus messages that don't match.
83 CHECK(dbus_connection_add_filter(connection, MessageFilter, this, NULL)); 124 CHECK(dbus_connection_add_filter(connection, MessageFilter, this, NULL));
84 } 125 }
85 126
86 void MetricsDaemon::Loop() { 127 void MetricsDaemon::Loop() {
87 GMainLoop* loop = g_main_loop_new(NULL, false); 128 GMainLoop* loop = g_main_loop_new(NULL, false);
88 g_main_loop_run(loop); 129 g_main_loop_run(loop);
89 } 130 }
90 131
91 // static 132 // static
92 DBusHandlerResult MetricsDaemon::MessageFilter(DBusConnection* connection, 133 DBusHandlerResult MetricsDaemon::MessageFilter(DBusConnection* connection,
93 DBusMessage* message, 134 DBusMessage* message,
94 void* user_data) { 135 void* user_data) {
95 LOG(INFO) << "message filter"; 136 time_t now = time(NULL);
137 DLOG(INFO) << "message intercepted @ " << now;
96 138
97 int message_type = dbus_message_get_type(message); 139 int message_type = dbus_message_get_type(message);
98 if (message_type != DBUS_MESSAGE_TYPE_SIGNAL) { 140 if (message_type != DBUS_MESSAGE_TYPE_SIGNAL) {
99 LOG(WARNING) << "unexpected message type " << message_type; 141 DLOG(WARNING) << "unexpected message type " << message_type;
100 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 142 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
101 } 143 }
102 144
103 // Signal messages always have interfaces. 145 // Signal messages always have interfaces.
104 const char* interface = dbus_message_get_interface(message); 146 const char* interface = dbus_message_get_interface(message);
105 CHECK(interface != NULL); 147 CHECK(interface != NULL);
106 148
107 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(user_data); 149 MetricsDaemon* daemon = static_cast<MetricsDaemon*>(user_data);
108 150
109 DBusMessageIter iter; 151 DBusMessageIter iter;
110 dbus_message_iter_init(message, &iter); 152 dbus_message_iter_init(message, &iter);
111 if (strcmp(interface, DBUS_IFACE_CONNMAN_MANAGER) == 0) { 153 if (strcmp(interface, DBUS_IFACE_CONNMAN_MANAGER) == 0) {
112 CHECK(strcmp(dbus_message_get_member(message), "StateChanged") == 0); 154 CHECK(strcmp(dbus_message_get_member(message),
155 "StateChanged") == 0);
113 156
114 char *state_name; 157 char *state_name;
115 dbus_message_iter_get_basic(&iter, &state_name); 158 dbus_message_iter_get_basic(&iter, &state_name);
116 daemon->NetStateChanged(state_name); 159 daemon->NetStateChanged(state_name, now);
117 } else if (strcmp(interface, DBUS_IFACE_POWER_MANAGER) == 0) { 160 } else if (strcmp(interface, DBUS_IFACE_POWER_MANAGER) == 0) {
118 CHECK(strcmp(dbus_message_get_member(message), "PowerStateChanged") == 0); 161 CHECK(strcmp(dbus_message_get_member(message),
162 "PowerStateChanged") == 0);
119 163
120 char *state_name; 164 char *state_name;
121 dbus_message_iter_get_basic(&iter, &state_name); 165 dbus_message_iter_get_basic(&iter, &state_name);
122 daemon->PowerStateChanged(state_name); 166 daemon->PowerStateChanged(state_name, now);
167 } else if (strcmp(interface, DBUS_IFACE_SCREENSAVER_MANAGER) == 0) {
168 CHECK(strcmp(dbus_message_get_member(message),
169 "LockStateChanged") == 0);
170
171 char *state_name;
172 dbus_message_iter_get_basic(&iter, &state_name);
173 daemon->ScreenSaverStateChanged(state_name, now);
174 } else if (strcmp(interface, DBUS_IFACE_SESSION_MANAGER) == 0) {
175 CHECK(strcmp(dbus_message_get_member(message),
176 "SessionStateChanged") == 0);
177
178 char *state_name;
179 dbus_message_iter_get_basic(&iter, &state_name);
180 daemon->SessionStateChanged(state_name, now);
123 } else { 181 } else {
124 LOG(WARNING) << "unexpected interface: " << interface; 182 DLOG(WARNING) << "unexpected interface: " << interface;
125 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 183 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
126 } 184 }
127 185
128 return DBUS_HANDLER_RESULT_HANDLED; 186 return DBUS_HANDLER_RESULT_HANDLED;
129 } 187 }
130 188
131 void MetricsDaemon::NetStateChanged(const char* state_name) { 189 void MetricsDaemon::NetStateChanged(const char* state_name, time_t now) {
132 LOG(INFO) << "network state: " << state_name; 190 DLOG(INFO) << "network state: " << state_name;
133 191
134 time_t now = time(NULL);
135 NetworkState state = LookupNetworkState(state_name); 192 NetworkState state = LookupNetworkState(state_name);
136 193
137 // Logs the time in seconds between the network going online to 194 // Logs the time in seconds between the network going online to
138 // going offline in order to measure the mean time to network 195 // going offline in order to measure the mean time to network
139 // dropping. Going offline as part of suspend-to-RAM is not logged 196 // dropping. Going offline as part of suspend-to-RAM is not logged
140 // as network drop -- the assumption is that the message for 197 // as network drop -- the assumption is that the message for
141 // suspend-to-RAM comes before the network offline message which 198 // suspend-to-RAM comes before the network offline message which
142 // seems to and should be the case. 199 // seems to and should be the case.
143 if (state == kNetworkStateOffline && 200 if (state == kNetworkStateOffline &&
144 network_state_ == kNetworkStateOnline && 201 network_state_ == kNetworkStateOnline &&
145 power_state_ != kPowerStateMem) { 202 power_state_ != kPowerStateMem) {
146 int online_time = static_cast<int>(now - network_state_changed_); 203 int online_time = static_cast<int>(now - network_state_last_);
147 PublishMetric("Network.TimeToDrop", online_time, 204 PublishMetric("Network.TimeToDrop", online_time,
148 1, 8 /* hours */ * 60 * 60, 50); 205 1, 8 /* hours */ * 60 * 60, 50);
149 } 206 }
150 207
151 network_state_ = state; 208 network_state_ = state;
152 network_state_changed_ = now; 209 network_state_last_ = now;
153 } 210 }
154 211
155 MetricsDaemon::NetworkState 212 MetricsDaemon::NetworkState
156 MetricsDaemon::LookupNetworkState(const char* state_name) { 213 MetricsDaemon::LookupNetworkState(const char* state_name) {
157 for (int i = 0; i < kNumberNetworkStates; i++) { 214 for (int i = 0; i < kNumberNetworkStates; i++) {
158 if (strcmp(state_name, network_states_[i]) == 0) { 215 if (strcmp(state_name, kNetworkStates_[i]) == 0) {
159 return static_cast<NetworkState>(i); 216 return static_cast<NetworkState>(i);
160 } 217 }
161 } 218 }
162 LOG(WARNING) << "unknown network connection state: " << state_name; 219 DLOG(WARNING) << "unknown network connection state: " << state_name;
163 return kUnknownNetworkState; 220 return kUnknownNetworkState;
164 } 221 }
165 222
166 void MetricsDaemon::PowerStateChanged(const char* state_name) { 223 void MetricsDaemon::PowerStateChanged(const char* state_name, time_t now) {
167 LOG(INFO) << "power state: " << state_name; 224 DLOG(INFO) << "power state: " << state_name;
168 power_state_ = LookupPowerState(state_name); 225 power_state_ = LookupPowerState(state_name);
226
227 if (power_state_ != kPowerStateOn)
228 SetUserActiveState(false, now);
169 } 229 }
170 230
171 MetricsDaemon::PowerState 231 MetricsDaemon::PowerState
172 MetricsDaemon::LookupPowerState(const char* state_name) { 232 MetricsDaemon::LookupPowerState(const char* state_name) {
173 for (int i = 0; i < kNumberPowerStates; i++) { 233 for (int i = 0; i < kNumberPowerStates; i++) {
174 if (strcmp(state_name, power_states_[i]) == 0) { 234 if (strcmp(state_name, kPowerStates_[i]) == 0) {
175 return static_cast<PowerState>(i); 235 return static_cast<PowerState>(i);
176 } 236 }
177 } 237 }
178 LOG(WARNING) << "unknown power state: " << state_name; 238 DLOG(WARNING) << "unknown power state: " << state_name;
179 return kUnknownPowerState; 239 return kUnknownPowerState;
180 } 240 }
181 241
242 void MetricsDaemon::ScreenSaverStateChanged(const char* state_name,
243 time_t now) {
244 DLOG(INFO) << "screen-saver state: " << state_name;
245 screensaver_state_ = LookupScreenSaverState(state_name);
246 SetUserActiveState(screensaver_state_ == kScreenSaverStateUnlocked, now);
247 }
248
249 MetricsDaemon::ScreenSaverState
250 MetricsDaemon::LookupScreenSaverState(const char* state_name) {
251 for (int i = 0; i < kNumberScreenSaverStates; i++) {
252 if (strcmp(state_name, kScreenSaverStates_[i]) == 0) {
253 return static_cast<ScreenSaverState>(i);
254 }
255 }
256 DLOG(WARNING) << "unknown screen-saver state: " << state_name;
257 return kUnknownScreenSaverState;
258 }
259
260 void MetricsDaemon::SessionStateChanged(const char* state_name,
261 time_t now) {
262 DLOG(INFO) << "user session state: " << state_name;
263 session_state_ = LookupSessionState(state_name);
264 SetUserActiveState(session_state_ == kSessionStateStarted, now);
265 }
266
267 MetricsDaemon::SessionState
268 MetricsDaemon::LookupSessionState(const char* state_name) {
269 for (int i = 0; i < kNumberSessionStates; i++) {
270 if (strcmp(state_name, kSessionStates_[i]) == 0) {
271 return static_cast<SessionState>(i);
272 }
273 }
274 DLOG(WARNING) << "unknown user session state: " << state_name;
275 return kUnknownSessionState;
276 }
277
278 void MetricsDaemon::SetUserActiveState(bool active, time_t now) {
279 DLOG(INFO) << "user: " << (active ? "active" : "inactive");
280
281 // Calculates the seconds of active use since the last update and
282 // the day since Epoch, and logs the usage data.
283 int seconds = user_active_ ? (now - user_active_last_) : 0;
284 int day = now / kSecondsPerDay;
285 LogDailyUseRecord(day, seconds);
286
287 // Schedules a use monitor on inactive->active transitions and
288 // unschedules it on active->inactive transitions.
289 if (!user_active_ && active)
290 ScheduleUseMonitor(kUseMonitorIntervalInit, /* backoff */ false);
291 else if (user_active_ && !active)
292 UnscheduleUseMonitor();
293
294 // Remembers the current active state and the time of the last
295 // activity update.
296 user_active_ = active;
297 user_active_last_ = now;
298 }
299
300 void MetricsDaemon::LogDailyUseRecord(int day, int seconds) {
301 // If there's no new active use today and the last record in the
302 // usage aggregation file is today, there's nothing to do.
303 if (seconds == 0 && day == daily_use_day_last_)
304 return;
305
306 DLOG(INFO) << "day: " << day << " usage: " << seconds << " seconds";
307 int fd = HANDLE_EINTR(open(kDailyUseRecordFile,
308 O_RDWR | O_CREAT,
309 S_IRUSR | S_IWUSR));
310 if (fd < 0) {
311 DLOG(WARNING) << "Unable to open the daily use file.";
312 return;
313 }
314
315 bool same_day = false;
316 UseRecord record;
317 if (HANDLE_EINTR(read(fd, &record, sizeof(record))) == sizeof(record)) {
318 if (record.day_ == day) {
319 // If there's an existing record for today, aggregates the usage
320 // time.
321 same_day = true;
322 record.seconds_ += seconds;
323 } else {
324 // If there's an existing record for a day in the past, rounds
325 // the usage to the nearest minute and sends it to UMA.
326 int minutes =
327 (record.seconds_ + kSecondsPerMinute / 2) / kSecondsPerMinute;
328 PublishMetric("Logging.DailyUseTime",
329 minutes, 1, kMinutesPerDay, 50);
330
331 // Truncates the usage file to ensure that no duplicate usage is
332 // sent to UMA.
333 LOG_IF(WARNING, HANDLE_EINTR(ftruncate(fd, 0)) != 0);
334 }
335 }
336
337 // Updates the use record in the daily usage file if there's new
338 // usage today.
339 if (seconds > 0) {
340 if (!same_day) {
341 record.day_ = day;
342 record.seconds_ = seconds;
343 }
344 // else an already existing record for the same day will be
345 // overwritten with updated usage below.
346
347 LOG_IF(WARNING, HANDLE_EINTR(lseek(fd, 0, SEEK_SET)) != 0);
348 LOG_IF(WARNING,
349 HANDLE_EINTR(write(fd, &record, sizeof(record))) != sizeof(record));
350 }
351
352 HANDLE_EINTR(close(fd));
353
354 // Remembers the day of the use record in the usage aggregation file
355 // to reduce file I/O. This is not really useful now but potentially
356 // allows frequent LogDailyUseRecord calls with no unnecessary I/O
357 // overhead.
358 daily_use_day_last_ = day;
359 }
360
361 // static
362 gboolean MetricsDaemon::UseMonitorStatic(gpointer data) {
363 return static_cast<MetricsDaemon*>(data)->UseMonitor() ? TRUE : FALSE;
364 }
365
366 bool MetricsDaemon::UseMonitor() {
367 SetUserActiveState(user_active_, time(NULL));
368
369 // If a new monitor source/instance is scheduled, returns false to
370 // tell GLib to destroy this monitor source/instance. Returns true
371 // otherwise to keep calling back this monitor.
372 return !ScheduleUseMonitor(usemon_interval_ * 2, /* backoff */ true);
373 }
374
375 bool MetricsDaemon::ScheduleUseMonitor(int interval, bool backoff)
376 {
377 // Caps the interval -- the bigger the interval, the more active use
378 // time will be potentially dropped on system shutdown.
379 if (interval > kUseMonitorIntervalMax)
380 interval = kUseMonitorIntervalMax;
381
382 if (backoff) {
383 // Back-off mode is used by the use monitor to reschedule itself
384 // with exponential back-off in time. This mode doesn't create a
385 // new timeout source if the new interval is the same as the old
386 // one. Also, if a new timeout source is created, the old one is
387 // not destroyed explicitly here -- it will be destroyed by GLib
388 // when the monitor returns FALSE (see UseMonitor and
389 // UseMonitorStatic).
390 if (interval == usemon_interval_)
391 return false;
392 } else {
393 UnscheduleUseMonitor();
394 }
395
396 // Schedules a new use monitor for |interval| seconds from now.
397 DLOG(INFO) << "scheduling use monitor in " << interval << " seconds";
398 usemon_source_ = g_timeout_source_new_seconds(interval);
399 g_source_set_callback(usemon_source_, UseMonitorStatic, this,
400 NULL); // No destroy notification.
401 g_source_attach(usemon_source_,
402 NULL); // Default context.
403 usemon_interval_ = interval;
404 return true;
405 }
406
407 void MetricsDaemon::UnscheduleUseMonitor() {
408 // If there's a use monitor scheduled already, destroys it.
409 if (usemon_source_ == NULL)
410 return;
411
412 DLOG(INFO) << "destroying use monitor";
413 g_source_destroy(usemon_source_);
414 usemon_source_ = NULL;
415 usemon_interval_ = 0;
416 }
417
182 void MetricsDaemon::PublishMetric(const char* name, int sample, 418 void MetricsDaemon::PublishMetric(const char* name, int sample,
183 int min, int max, int nbuckets) { 419 int min, int max, int nbuckets) {
184 LOG(INFO) << "received metric: " << name << " " << sample << 420 DLOG(INFO) << "received metric: " << name << " " << sample << " "
185 " " << min << " " << max << " " << nbuckets; 421 << min << " " << max << " " << nbuckets;
186 if (!testing_) { 422 if (!testing_) {
187 MetricsLibrary::SendToChrome(name, sample, min, max, nbuckets); 423 MetricsLibrary::SendToChrome(name, sample, min, max, nbuckets);
188 } 424 }
189 } 425 }
OLDNEW
« no previous file with comments | « src/platform/metrics/metrics_daemon.h ('k') | src/platform/metrics/power_states.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698