1 // Copyright 2014 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.
5 #include "components/metrics/metrics_log_manager.h"
9 #include "base/metrics/histogram.h"
10 #include "base/strings/string_util.h"
11 #include "base/timer/elapsed_timer.h"
12 #include "components/metrics/metrics_log.h"
13 #include "components/metrics/metrics_pref_names.h"
19 // The number of "initial" logs to save, and hope to send during a future Chrome
20 // session. Initial logs contain crash stats, and are pretty small.
21 const size_t kInitialLogsPersistLimit
= 20;
23 // The number of ongoing logs to save persistently, and hope to
24 // send during a this or future sessions. Note that each log may be pretty
25 // large, as presumably the related "initial" log wasn't sent (probably nothing
26 // was, as the user was probably off-line). As a result, the log probably kept
27 // accumulating while the "initial" log was stalled, and couldn't be sent. As a
28 // result, we don't want to save too many of these mega-logs.
29 // A "standard shutdown" will create a small log, including just the data that
30 // was not yet been transmitted, and that is normal (to have exactly one
31 // ongoing_log_ at startup).
32 const size_t kOngoingLogsPersistLimit
= 8;
34 // The number of bytes each of initial and ongoing logs that must be stored.
35 // This ensures that a reasonable amount of history will be stored even if there
36 // is a long series of very small logs.
37 const size_t kStorageByteLimitPerLogType
= 300000;
41 MetricsLogManager::MetricsLogManager(PrefService
* local_state
,
42 size_t max_ongoing_log_size
)
43 : unsent_logs_loaded_(false),
44 initial_log_queue_(local_state
,
45 prefs::kMetricsInitialLogs
,
46 kInitialLogsPersistLimit
,
47 kStorageByteLimitPerLogType
,
49 ongoing_log_queue_(local_state
,
50 prefs::kMetricsOngoingLogs
,
51 kOngoingLogsPersistLimit
,
52 kStorageByteLimitPerLogType
,
53 max_ongoing_log_size
) {}
55 MetricsLogManager::~MetricsLogManager() {}
57 void MetricsLogManager::BeginLoggingWithLog(scoped_ptr
<MetricsLog
> log
) {
58 DCHECK(!current_log_
);
59 current_log_
= log
.Pass();
62 void MetricsLogManager::FinishCurrentLog() {
63 DCHECK(current_log_
.get());
64 current_log_
->CloseLog();
66 current_log_
->GetEncodedLog(&log_data
);
67 if (!log_data
.empty())
68 StoreLog(log_data
, current_log_
->log_type());
72 void MetricsLogManager::StageNextLogForUpload() {
73 DCHECK(!has_staged_log());
74 if (!initial_log_queue_
.empty())
75 initial_log_queue_
.StageLog();
77 ongoing_log_queue_
.StageLog();
80 void MetricsLogManager::DiscardStagedLog() {
81 DCHECK(has_staged_log());
82 if (initial_log_queue_
.has_staged_log())
83 initial_log_queue_
.DiscardStagedLog();
85 ongoing_log_queue_
.DiscardStagedLog();
86 DCHECK(!has_staged_log());
89 void MetricsLogManager::DiscardCurrentLog() {
90 current_log_
->CloseLog();
94 void MetricsLogManager::PauseCurrentLog() {
95 DCHECK(!paused_log_
.get());
96 paused_log_
.reset(current_log_
.release());
99 void MetricsLogManager::ResumePausedLog() {
100 DCHECK(!current_log_
.get());
101 current_log_
.reset(paused_log_
.release());
104 void MetricsLogManager::StoreLog(const std::string
& log_data
,
105 MetricsLog::LogType log_type
) {
107 case MetricsLog::INITIAL_STABILITY_LOG
:
108 initial_log_queue_
.StoreLog(log_data
);
110 case MetricsLog::ONGOING_LOG
:
111 ongoing_log_queue_
.StoreLog(log_data
);
116 void MetricsLogManager::PersistUnsentLogs() {
117 DCHECK(unsent_logs_loaded_
);
118 if (!unsent_logs_loaded_
)
121 base::ElapsedTimer timer
;
122 initial_log_queue_
.SerializeLogs();
123 ongoing_log_queue_
.SerializeLogs();
124 UMA_HISTOGRAM_TIMES("UMA.StoreLogsTime", timer
.Elapsed());
127 void MetricsLogManager::LoadPersistedUnsentLogs() {
128 base::ElapsedTimer timer
;
129 initial_log_queue_
.DeserializeLogs();
130 ongoing_log_queue_
.DeserializeLogs();
131 UMA_HISTOGRAM_TIMES("UMA.LoadLogsTime", timer
.Elapsed());
133 unsent_logs_loaded_
= true;
136 } // namespace metrics