xref: /aosp_15_r20/external/cronet/components/metrics/reporting_service.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker // ReportingService handles uploading serialized logs to a server.
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include "components/metrics/reporting_service.h"
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <cstdio>
10*6777b538SAndroid Build Coastguard Worker #include <memory>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/base64.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
19*6777b538SAndroid Build Coastguard Worker #include "components/metrics/data_use_tracker.h"
20*6777b538SAndroid Build Coastguard Worker #include "components/metrics/log_store.h"
21*6777b538SAndroid Build Coastguard Worker #include "components/metrics/metrics_features.h"
22*6777b538SAndroid Build Coastguard Worker #include "components/metrics/metrics_log_uploader.h"
23*6777b538SAndroid Build Coastguard Worker #include "components/metrics/metrics_service_client.h"
24*6777b538SAndroid Build Coastguard Worker #include "components/metrics/metrics_upload_scheduler.h"
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker namespace metrics {
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker // static
RegisterPrefs(PrefRegistrySimple * registry)29*6777b538SAndroid Build Coastguard Worker void ReportingService::RegisterPrefs(PrefRegistrySimple* registry) {
30*6777b538SAndroid Build Coastguard Worker   DataUseTracker::RegisterPrefs(registry);
31*6777b538SAndroid Build Coastguard Worker }
32*6777b538SAndroid Build Coastguard Worker 
ReportingService(MetricsServiceClient * client,PrefService * local_state,size_t max_retransmit_size,MetricsLogsEventManager * logs_event_manager)33*6777b538SAndroid Build Coastguard Worker ReportingService::ReportingService(MetricsServiceClient* client,
34*6777b538SAndroid Build Coastguard Worker                                    PrefService* local_state,
35*6777b538SAndroid Build Coastguard Worker                                    size_t max_retransmit_size,
36*6777b538SAndroid Build Coastguard Worker                                    MetricsLogsEventManager* logs_event_manager)
37*6777b538SAndroid Build Coastguard Worker     : client_(client),
38*6777b538SAndroid Build Coastguard Worker       local_state_(local_state),
39*6777b538SAndroid Build Coastguard Worker       max_retransmit_size_(max_retransmit_size),
40*6777b538SAndroid Build Coastguard Worker       logs_event_manager_(logs_event_manager),
41*6777b538SAndroid Build Coastguard Worker       reporting_active_(false),
42*6777b538SAndroid Build Coastguard Worker       log_upload_in_progress_(false),
43*6777b538SAndroid Build Coastguard Worker       data_use_tracker_(DataUseTracker::Create(local_state)) {
44*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
45*6777b538SAndroid Build Coastguard Worker   DCHECK(client_);
46*6777b538SAndroid Build Coastguard Worker   DCHECK(local_state);
47*6777b538SAndroid Build Coastguard Worker }
48*6777b538SAndroid Build Coastguard Worker 
~ReportingService()49*6777b538SAndroid Build Coastguard Worker ReportingService::~ReportingService() {
50*6777b538SAndroid Build Coastguard Worker   DisableReporting();
51*6777b538SAndroid Build Coastguard Worker }
52*6777b538SAndroid Build Coastguard Worker 
Initialize()53*6777b538SAndroid Build Coastguard Worker void ReportingService::Initialize() {
54*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
55*6777b538SAndroid Build Coastguard Worker   DCHECK(!upload_scheduler_);
56*6777b538SAndroid Build Coastguard Worker   log_store()->LoadPersistedUnsentLogs();
57*6777b538SAndroid Build Coastguard Worker   base::RepeatingClosure send_next_log_callback = base::BindRepeating(
58*6777b538SAndroid Build Coastguard Worker       &ReportingService::SendNextLog, self_ptr_factory_.GetWeakPtr());
59*6777b538SAndroid Build Coastguard Worker   bool fast_startup_for_testing = client_->ShouldStartUpFastForTesting();
60*6777b538SAndroid Build Coastguard Worker   upload_scheduler_ = std::make_unique<MetricsUploadScheduler>(
61*6777b538SAndroid Build Coastguard Worker       send_next_log_callback, fast_startup_for_testing);
62*6777b538SAndroid Build Coastguard Worker }
63*6777b538SAndroid Build Coastguard Worker 
Start()64*6777b538SAndroid Build Coastguard Worker void ReportingService::Start() {
65*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
66*6777b538SAndroid Build Coastguard Worker   if (reporting_active_)
67*6777b538SAndroid Build Coastguard Worker     upload_scheduler_->Start();
68*6777b538SAndroid Build Coastguard Worker }
69*6777b538SAndroid Build Coastguard Worker 
Stop()70*6777b538SAndroid Build Coastguard Worker void ReportingService::Stop() {
71*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
72*6777b538SAndroid Build Coastguard Worker   if (upload_scheduler_)
73*6777b538SAndroid Build Coastguard Worker     upload_scheduler_->Stop();
74*6777b538SAndroid Build Coastguard Worker }
75*6777b538SAndroid Build Coastguard Worker 
EnableReporting()76*6777b538SAndroid Build Coastguard Worker void ReportingService::EnableReporting() {
77*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
78*6777b538SAndroid Build Coastguard Worker   if (reporting_active_)
79*6777b538SAndroid Build Coastguard Worker     return;
80*6777b538SAndroid Build Coastguard Worker   reporting_active_ = true;
81*6777b538SAndroid Build Coastguard Worker   Start();
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker 
DisableReporting()84*6777b538SAndroid Build Coastguard Worker void ReportingService::DisableReporting() {
85*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
86*6777b538SAndroid Build Coastguard Worker   reporting_active_ = false;
87*6777b538SAndroid Build Coastguard Worker   Stop();
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker 
reporting_active() const90*6777b538SAndroid Build Coastguard Worker bool ReportingService::reporting_active() const {
91*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
92*6777b538SAndroid Build Coastguard Worker   return reporting_active_;
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
96*6777b538SAndroid Build Coastguard Worker // private methods
97*6777b538SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
98*6777b538SAndroid Build Coastguard Worker 
SendNextLog()99*6777b538SAndroid Build Coastguard Worker void ReportingService::SendNextLog() {
100*6777b538SAndroid Build Coastguard Worker   DVLOG(1) << "SendNextLog";
101*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
102*6777b538SAndroid Build Coastguard Worker 
103*6777b538SAndroid Build Coastguard Worker   const base::TimeTicks now = base::TimeTicks::Now();
104*6777b538SAndroid Build Coastguard Worker   LogActualUploadInterval(last_upload_finish_time_.is_null()
105*6777b538SAndroid Build Coastguard Worker                               ? base::TimeDelta()
106*6777b538SAndroid Build Coastguard Worker                               : now - last_upload_finish_time_);
107*6777b538SAndroid Build Coastguard Worker   last_upload_finish_time_ = now;
108*6777b538SAndroid Build Coastguard Worker 
109*6777b538SAndroid Build Coastguard Worker   if (!reporting_active()) {
110*6777b538SAndroid Build Coastguard Worker     upload_scheduler_->StopAndUploadCancelled();
111*6777b538SAndroid Build Coastguard Worker     return;
112*6777b538SAndroid Build Coastguard Worker   }
113*6777b538SAndroid Build Coastguard Worker   if (!log_store()->has_unsent_logs()) {
114*6777b538SAndroid Build Coastguard Worker     // Should only get here if serializing the log failed somehow.
115*6777b538SAndroid Build Coastguard Worker     upload_scheduler_->Stop();
116*6777b538SAndroid Build Coastguard Worker     // Reset backoff interval
117*6777b538SAndroid Build Coastguard Worker     upload_scheduler_->UploadFinished(true);
118*6777b538SAndroid Build Coastguard Worker     return;
119*6777b538SAndroid Build Coastguard Worker   }
120*6777b538SAndroid Build Coastguard Worker   if (!log_store()->has_staged_log()) {
121*6777b538SAndroid Build Coastguard Worker     reporting_info_.set_attempt_count(0);
122*6777b538SAndroid Build Coastguard Worker     log_store()->StageNextLog();
123*6777b538SAndroid Build Coastguard Worker   }
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   // Check whether the log should be uploaded based on user id. If it should not
126*6777b538SAndroid Build Coastguard Worker   // be sent, then discard the log from the store and notify the scheduler.
127*6777b538SAndroid Build Coastguard Worker   auto staged_user_id = log_store()->staged_log_user_id();
128*6777b538SAndroid Build Coastguard Worker   if (staged_user_id.has_value() &&
129*6777b538SAndroid Build Coastguard Worker       !client_->ShouldUploadMetricsForUserId(staged_user_id.value())) {
130*6777b538SAndroid Build Coastguard Worker     // Remove the log and update list to disk.
131*6777b538SAndroid Build Coastguard Worker     log_store()->DiscardStagedLog();
132*6777b538SAndroid Build Coastguard Worker     log_store()->TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
133*6777b538SAndroid Build Coastguard Worker 
134*6777b538SAndroid Build Coastguard Worker     // Notify the scheduler that the next log should be uploaded. If there are
135*6777b538SAndroid Build Coastguard Worker     // no more logs, then stop the scheduler.
136*6777b538SAndroid Build Coastguard Worker     if (!log_store()->has_unsent_logs()) {
137*6777b538SAndroid Build Coastguard Worker       DVLOG(1) << "Stopping upload_scheduler_.";
138*6777b538SAndroid Build Coastguard Worker       upload_scheduler_->Stop();
139*6777b538SAndroid Build Coastguard Worker     }
140*6777b538SAndroid Build Coastguard Worker     upload_scheduler_->UploadFinished(true);
141*6777b538SAndroid Build Coastguard Worker     return;
142*6777b538SAndroid Build Coastguard Worker   }
143*6777b538SAndroid Build Coastguard Worker 
144*6777b538SAndroid Build Coastguard Worker   // Proceed to stage the log for upload if log size satisfies cellular log
145*6777b538SAndroid Build Coastguard Worker   // upload constrains.
146*6777b538SAndroid Build Coastguard Worker   bool upload_canceled = false;
147*6777b538SAndroid Build Coastguard Worker   bool is_cellular_logic = client_->IsOnCellularConnection();
148*6777b538SAndroid Build Coastguard Worker   if (is_cellular_logic && data_use_tracker_ &&
149*6777b538SAndroid Build Coastguard Worker       !data_use_tracker_->ShouldUploadLogOnCellular(
150*6777b538SAndroid Build Coastguard Worker           log_store()->staged_log().size())) {
151*6777b538SAndroid Build Coastguard Worker     upload_scheduler_->UploadOverDataUsageCap();
152*6777b538SAndroid Build Coastguard Worker     upload_canceled = true;
153*6777b538SAndroid Build Coastguard Worker   } else {
154*6777b538SAndroid Build Coastguard Worker     SendStagedLog();
155*6777b538SAndroid Build Coastguard Worker   }
156*6777b538SAndroid Build Coastguard Worker   if (is_cellular_logic) {
157*6777b538SAndroid Build Coastguard Worker     LogCellularConstraint(upload_canceled);
158*6777b538SAndroid Build Coastguard Worker   }
159*6777b538SAndroid Build Coastguard Worker }
160*6777b538SAndroid Build Coastguard Worker 
SendStagedLog()161*6777b538SAndroid Build Coastguard Worker void ReportingService::SendStagedLog() {
162*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
163*6777b538SAndroid Build Coastguard Worker   DCHECK(log_store()->has_staged_log());
164*6777b538SAndroid Build Coastguard Worker   if (!log_store()->has_staged_log())
165*6777b538SAndroid Build Coastguard Worker     return;
166*6777b538SAndroid Build Coastguard Worker 
167*6777b538SAndroid Build Coastguard Worker   DCHECK(!log_upload_in_progress_);
168*6777b538SAndroid Build Coastguard Worker   log_upload_in_progress_ = true;
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker   if (!log_uploader_) {
171*6777b538SAndroid Build Coastguard Worker     log_uploader_ = client_->CreateUploader(
172*6777b538SAndroid Build Coastguard Worker         GetUploadUrl(), GetInsecureUploadUrl(), upload_mime_type(),
173*6777b538SAndroid Build Coastguard Worker         service_type(),
174*6777b538SAndroid Build Coastguard Worker         base::BindRepeating(&ReportingService::OnLogUploadComplete,
175*6777b538SAndroid Build Coastguard Worker                             self_ptr_factory_.GetWeakPtr()));
176*6777b538SAndroid Build Coastguard Worker   }
177*6777b538SAndroid Build Coastguard Worker 
178*6777b538SAndroid Build Coastguard Worker   reporting_info_.set_attempt_count(reporting_info_.attempt_count() + 1);
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker   const std::string hash = base::HexEncode(log_store()->staged_log_hash());
181*6777b538SAndroid Build Coastguard Worker 
182*6777b538SAndroid Build Coastguard Worker   std::string signature =
183*6777b538SAndroid Build Coastguard Worker       base::Base64Encode(log_store()->staged_log_signature());
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker   if (logs_event_manager_) {
186*6777b538SAndroid Build Coastguard Worker     logs_event_manager_->NotifyLogEvent(
187*6777b538SAndroid Build Coastguard Worker         MetricsLogsEventManager::LogEvent::kLogUploading,
188*6777b538SAndroid Build Coastguard Worker         log_store()->staged_log_hash());
189*6777b538SAndroid Build Coastguard Worker   }
190*6777b538SAndroid Build Coastguard Worker   log_uploader_->UploadLog(log_store()->staged_log(),
191*6777b538SAndroid Build Coastguard Worker                            log_store()->staged_log_metadata(), hash, signature,
192*6777b538SAndroid Build Coastguard Worker                            reporting_info_);
193*6777b538SAndroid Build Coastguard Worker }
194*6777b538SAndroid Build Coastguard Worker 
OnLogUploadComplete(int response_code,int error_code,bool was_https,bool force_discard,base::StringPiece force_discard_reason)195*6777b538SAndroid Build Coastguard Worker void ReportingService::OnLogUploadComplete(
196*6777b538SAndroid Build Coastguard Worker     int response_code,
197*6777b538SAndroid Build Coastguard Worker     int error_code,
198*6777b538SAndroid Build Coastguard Worker     bool was_https,
199*6777b538SAndroid Build Coastguard Worker     bool force_discard,
200*6777b538SAndroid Build Coastguard Worker     base::StringPiece force_discard_reason) {
201*6777b538SAndroid Build Coastguard Worker   DVLOG(1) << "OnLogUploadComplete:" << response_code;
202*6777b538SAndroid Build Coastguard Worker   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
203*6777b538SAndroid Build Coastguard Worker   DCHECK(log_upload_in_progress_);
204*6777b538SAndroid Build Coastguard Worker   log_upload_in_progress_ = false;
205*6777b538SAndroid Build Coastguard Worker 
206*6777b538SAndroid Build Coastguard Worker   reporting_info_.set_last_response_code(response_code);
207*6777b538SAndroid Build Coastguard Worker   reporting_info_.set_last_error_code(error_code);
208*6777b538SAndroid Build Coastguard Worker   reporting_info_.set_last_attempt_was_https(was_https);
209*6777b538SAndroid Build Coastguard Worker 
210*6777b538SAndroid Build Coastguard Worker   // Log a histogram to track response success vs. failure rates.
211*6777b538SAndroid Build Coastguard Worker   LogResponseOrErrorCode(response_code, error_code, was_https);
212*6777b538SAndroid Build Coastguard Worker 
213*6777b538SAndroid Build Coastguard Worker   bool upload_succeeded = response_code == 200;
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker   // Staged log could have been removed already (such as by Purge() in some
216*6777b538SAndroid Build Coastguard Worker   // implementations), otherwise we may remove it here.
217*6777b538SAndroid Build Coastguard Worker   if (log_store()->has_staged_log()) {
218*6777b538SAndroid Build Coastguard Worker     // Provide boolean for error recovery (allow us to ignore response_code).
219*6777b538SAndroid Build Coastguard Worker     bool discard_log = false;
220*6777b538SAndroid Build Coastguard Worker     base::StringPiece discard_reason;
221*6777b538SAndroid Build Coastguard Worker 
222*6777b538SAndroid Build Coastguard Worker     const std::string& staged_log = log_store()->staged_log();
223*6777b538SAndroid Build Coastguard Worker     const size_t log_size = staged_log.length();
224*6777b538SAndroid Build Coastguard Worker     if (upload_succeeded) {
225*6777b538SAndroid Build Coastguard Worker       LogSuccessLogSize(log_size);
226*6777b538SAndroid Build Coastguard Worker       LogSuccessMetadata(staged_log);
227*6777b538SAndroid Build Coastguard Worker       discard_log = true;
228*6777b538SAndroid Build Coastguard Worker       discard_reason = "Log upload successful.";
229*6777b538SAndroid Build Coastguard Worker     } else if (force_discard) {
230*6777b538SAndroid Build Coastguard Worker       discard_log = true;
231*6777b538SAndroid Build Coastguard Worker       discard_reason = force_discard_reason;
232*6777b538SAndroid Build Coastguard Worker     } else if (log_size > max_retransmit_size_) {
233*6777b538SAndroid Build Coastguard Worker       LogLargeRejection(log_size);
234*6777b538SAndroid Build Coastguard Worker       discard_log = true;
235*6777b538SAndroid Build Coastguard Worker       discard_reason =
236*6777b538SAndroid Build Coastguard Worker           "Failed to upload, and log is too large. Will not attempt to "
237*6777b538SAndroid Build Coastguard Worker           "retransmit.";
238*6777b538SAndroid Build Coastguard Worker     } else if (response_code == 400) {
239*6777b538SAndroid Build Coastguard Worker       // Bad syntax.  Retransmission won't work.
240*6777b538SAndroid Build Coastguard Worker       discard_log = true;
241*6777b538SAndroid Build Coastguard Worker       discard_reason =
242*6777b538SAndroid Build Coastguard Worker           "Failed to upload because log has bad syntax. Will not attempt to "
243*6777b538SAndroid Build Coastguard Worker           "retransmit.";
244*6777b538SAndroid Build Coastguard Worker     }
245*6777b538SAndroid Build Coastguard Worker 
246*6777b538SAndroid Build Coastguard Worker     if (!discard_log && logs_event_manager_) {
247*6777b538SAndroid Build Coastguard Worker       // The log is not discarded, meaning that it has failed to upload. We will
248*6777b538SAndroid Build Coastguard Worker       // try to retransmit it.
249*6777b538SAndroid Build Coastguard Worker       logs_event_manager_->NotifyLogEvent(
250*6777b538SAndroid Build Coastguard Worker           MetricsLogsEventManager::LogEvent::kLogStaged,
251*6777b538SAndroid Build Coastguard Worker           log_store()->staged_log_hash(),
252*6777b538SAndroid Build Coastguard Worker           base::StringPrintf("Failed to upload (status code: %d, net error "
253*6777b538SAndroid Build Coastguard Worker                              "code: %d). Staged again for retransmission.",
254*6777b538SAndroid Build Coastguard Worker                              response_code, error_code));
255*6777b538SAndroid Build Coastguard Worker     }
256*6777b538SAndroid Build Coastguard Worker 
257*6777b538SAndroid Build Coastguard Worker     if (discard_log) {
258*6777b538SAndroid Build Coastguard Worker       if (upload_succeeded)
259*6777b538SAndroid Build Coastguard Worker         log_store()->MarkStagedLogAsSent();
260*6777b538SAndroid Build Coastguard Worker 
261*6777b538SAndroid Build Coastguard Worker       log_store()->DiscardStagedLog(discard_reason);
262*6777b538SAndroid Build Coastguard Worker       // Store the updated list to disk now that the removed log is uploaded.
263*6777b538SAndroid Build Coastguard Worker       log_store()->TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
264*6777b538SAndroid Build Coastguard Worker 
265*6777b538SAndroid Build Coastguard Worker       bool flush_local_state =
266*6777b538SAndroid Build Coastguard Worker           base::FeatureList::IsEnabled(features::kReportingServiceAlwaysFlush);
267*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
268*6777b538SAndroid Build Coastguard Worker       // If Chrome is in the background, flush the discarded and trimmed logs
269*6777b538SAndroid Build Coastguard Worker       // from |local_state_| immediately because the process may be killed at
270*6777b538SAndroid Build Coastguard Worker       // any time from now without persisting the changes. Otherwise, we may end
271*6777b538SAndroid Build Coastguard Worker       // up re-uploading the same log in a future session. We do not do this if
272*6777b538SAndroid Build Coastguard Worker       // Chrome is in the foreground because of the assumption that
273*6777b538SAndroid Build Coastguard Worker       // |local_state_| will be flushed when convenient, and we do not want to
274*6777b538SAndroid Build Coastguard Worker       // do more work than necessary on the main thread while Chrome is visible.
275*6777b538SAndroid Build Coastguard Worker       flush_local_state = flush_local_state || !is_in_foreground_;
276*6777b538SAndroid Build Coastguard Worker #endif  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
277*6777b538SAndroid Build Coastguard Worker       if (flush_local_state) {
278*6777b538SAndroid Build Coastguard Worker         local_state_->CommitPendingWrite();
279*6777b538SAndroid Build Coastguard Worker       }
280*6777b538SAndroid Build Coastguard Worker     }
281*6777b538SAndroid Build Coastguard Worker   }
282*6777b538SAndroid Build Coastguard Worker 
283*6777b538SAndroid Build Coastguard Worker   // Error 400 indicates a problem with the log, not with the server, so
284*6777b538SAndroid Build Coastguard Worker   // don't consider that a sign that the server is in trouble. Similarly, if
285*6777b538SAndroid Build Coastguard Worker   // |force_discard| is true, do not delay the sending of other logs. For
286*6777b538SAndroid Build Coastguard Worker   // example, if |force_discard| is true because there are no metrics server
287*6777b538SAndroid Build Coastguard Worker   // URLs included in this build, do not indicate that the "non-existent server"
288*6777b538SAndroid Build Coastguard Worker   // is in trouble, which would delay the sending of other logs and causing the
289*6777b538SAndroid Build Coastguard Worker   // accumulation of logs on disk.
290*6777b538SAndroid Build Coastguard Worker   bool server_is_healthy =
291*6777b538SAndroid Build Coastguard Worker       upload_succeeded || response_code == 400 || force_discard;
292*6777b538SAndroid Build Coastguard Worker 
293*6777b538SAndroid Build Coastguard Worker   if (!log_store()->has_unsent_logs()) {
294*6777b538SAndroid Build Coastguard Worker     DVLOG(1) << "Stopping upload_scheduler_.";
295*6777b538SAndroid Build Coastguard Worker     upload_scheduler_->Stop();
296*6777b538SAndroid Build Coastguard Worker   }
297*6777b538SAndroid Build Coastguard Worker   upload_scheduler_->UploadFinished(server_is_healthy);
298*6777b538SAndroid Build Coastguard Worker }
299*6777b538SAndroid Build Coastguard Worker 
300*6777b538SAndroid Build Coastguard Worker }  // namespace metrics
301