reporting_service.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // Copyright 2017 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. // ReportingService handles uploading serialized logs to a server.
  5. #include "components/metrics/reporting_service.h"
  6. #include <cstdio>
  7. #include <memory>
  8. #include "base/base64.h"
  9. #include "base/bind.h"
  10. #include "base/callback.h"
  11. #include "base/command_line.h"
  12. #include "base/logging.h"
  13. #include "base/strings/string_number_conversions.h"
  14. #include "components/metrics/data_use_tracker.h"
  15. #include "components/metrics/log_store.h"
  16. #include "components/metrics/metrics_log_uploader.h"
  17. #include "components/metrics/metrics_service_client.h"
  18. #include "components/metrics/metrics_upload_scheduler.h"
  19. namespace metrics {
  20. // static
  21. void ReportingService::RegisterPrefs(PrefRegistrySimple* registry) {
  22. DataUseTracker::RegisterPrefs(registry);
  23. }
  24. ReportingService::ReportingService(MetricsServiceClient* client,
  25. PrefService* local_state,
  26. size_t max_retransmit_size)
  27. : client_(client),
  28. max_retransmit_size_(max_retransmit_size),
  29. reporting_active_(false),
  30. log_upload_in_progress_(false),
  31. data_use_tracker_(DataUseTracker::Create(local_state)) {
  32. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  33. DCHECK(client_);
  34. DCHECK(local_state);
  35. }
  36. ReportingService::~ReportingService() {
  37. DisableReporting();
  38. }
  39. void ReportingService::Initialize() {
  40. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  41. DCHECK(!upload_scheduler_);
  42. log_store()->LoadPersistedUnsentLogs();
  43. base::RepeatingClosure send_next_log_callback = base::BindRepeating(
  44. &ReportingService::SendNextLog, self_ptr_factory_.GetWeakPtr());
  45. bool fast_startup_for_testing = client_->ShouldStartUpFastForTesting();
  46. upload_scheduler_ = std::make_unique<MetricsUploadScheduler>(
  47. send_next_log_callback, fast_startup_for_testing);
  48. }
  49. void ReportingService::Start() {
  50. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  51. if (reporting_active_)
  52. upload_scheduler_->Start();
  53. }
  54. void ReportingService::Stop() {
  55. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  56. if (upload_scheduler_)
  57. upload_scheduler_->Stop();
  58. }
  59. void ReportingService::EnableReporting() {
  60. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  61. if (reporting_active_)
  62. return;
  63. reporting_active_ = true;
  64. Start();
  65. }
  66. void ReportingService::DisableReporting() {
  67. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  68. reporting_active_ = false;
  69. Stop();
  70. }
  71. bool ReportingService::reporting_active() const {
  72. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  73. return reporting_active_;
  74. }
  75. //------------------------------------------------------------------------------
  76. // private methods
  77. //------------------------------------------------------------------------------
  78. void ReportingService::SendNextLog() {
  79. DVLOG(1) << "SendNextLog";
  80. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  81. const base::TimeTicks now = base::TimeTicks::Now();
  82. LogActualUploadInterval(last_upload_finish_time_.is_null()
  83. ? base::TimeDelta()
  84. : now - last_upload_finish_time_);
  85. last_upload_finish_time_ = now;
  86. if (!reporting_active()) {
  87. upload_scheduler_->StopAndUploadCancelled();
  88. return;
  89. }
  90. if (!log_store()->has_unsent_logs()) {
  91. // Should only get here if serializing the log failed somehow.
  92. upload_scheduler_->Stop();
  93. // Reset backoff interval
  94. upload_scheduler_->UploadFinished(true);
  95. return;
  96. }
  97. if (!log_store()->has_staged_log()) {
  98. reporting_info_.set_attempt_count(0);
  99. log_store()->StageNextLog();
  100. }
  101. // Check whether the log should be uploaded based on user id. If it should not
  102. // be sent, then discard the log from the store and notify the scheduler.
  103. auto staged_user_id = log_store()->staged_log_user_id();
  104. if (staged_user_id.has_value() &&
  105. !client_->ShouldUploadMetricsForUserId(staged_user_id.value())) {
  106. // Remove the log and update list to disk.
  107. log_store()->DiscardStagedLog();
  108. log_store()->TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
  109. // Notify the scheduler that the next log should be uploaded. If there are
  110. // no more logs, then stop the scheduler.
  111. if (!log_store()->has_unsent_logs()) {
  112. DVLOG(1) << "Stopping upload_scheduler_.";
  113. upload_scheduler_->Stop();
  114. }
  115. upload_scheduler_->UploadFinished(true);
  116. return;
  117. }
  118. // Proceed to stage the log for upload if log size satisfies cellular log
  119. // upload constrains.
  120. bool upload_canceled = false;
  121. bool is_cellular_logic = client_->IsUMACellularUploadLogicEnabled();
  122. if (is_cellular_logic && data_use_tracker_ &&
  123. !data_use_tracker_->ShouldUploadLogOnCellular(
  124. log_store()->staged_log().size())) {
  125. upload_scheduler_->UploadOverDataUsageCap();
  126. upload_canceled = true;
  127. } else {
  128. SendStagedLog();
  129. }
  130. if (is_cellular_logic) {
  131. LogCellularConstraint(upload_canceled);
  132. }
  133. }
  134. void ReportingService::SendStagedLog() {
  135. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  136. DCHECK(log_store()->has_staged_log());
  137. if (!log_store()->has_staged_log())
  138. return;
  139. DCHECK(!log_upload_in_progress_);
  140. log_upload_in_progress_ = true;
  141. if (!log_uploader_) {
  142. log_uploader_ = client_->CreateUploader(
  143. GetUploadUrl(), GetInsecureUploadUrl(), upload_mime_type(),
  144. service_type(),
  145. base::BindRepeating(&ReportingService::OnLogUploadComplete,
  146. self_ptr_factory_.GetWeakPtr()));
  147. }
  148. reporting_info_.set_attempt_count(reporting_info_.attempt_count() + 1);
  149. const std::string hash =
  150. base::HexEncode(log_store()->staged_log_hash().data(),
  151. log_store()->staged_log_hash().size());
  152. std::string signature;
  153. base::Base64Encode(log_store()->staged_log_signature(), &signature);
  154. log_uploader_->UploadLog(log_store()->staged_log(), hash, signature,
  155. reporting_info_);
  156. }
  157. void ReportingService::OnLogUploadComplete(int response_code,
  158. int error_code,
  159. bool was_https) {
  160. DVLOG(1) << "OnLogUploadComplete:" << response_code;
  161. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  162. DCHECK(log_upload_in_progress_);
  163. log_upload_in_progress_ = false;
  164. reporting_info_.set_last_response_code(response_code);
  165. reporting_info_.set_last_error_code(error_code);
  166. reporting_info_.set_last_attempt_was_https(was_https);
  167. // Log a histogram to track response success vs. failure rates.
  168. LogResponseOrErrorCode(response_code, error_code, was_https);
  169. bool upload_succeeded = response_code == 200;
  170. // Staged log could have been removed already (such as by Purge() in some
  171. // implementations), otherwise we may remove it here.
  172. if (log_store()->has_staged_log()) {
  173. // Provide boolean for error recovery (allow us to ignore response_code).
  174. bool discard_log = false;
  175. const std::string& staged_log = log_store()->staged_log();
  176. const size_t log_size = staged_log.length();
  177. if (upload_succeeded) {
  178. LogSuccessLogSize(log_size);
  179. LogSuccessMetadata(staged_log);
  180. } else if (log_size > max_retransmit_size_) {
  181. LogLargeRejection(log_size);
  182. discard_log = true;
  183. } else if (response_code == 400) {
  184. // Bad syntax. Retransmission won't work.
  185. discard_log = true;
  186. }
  187. if (upload_succeeded || discard_log) {
  188. if (upload_succeeded)
  189. log_store()->MarkStagedLogAsSent();
  190. log_store()->DiscardStagedLog();
  191. // Store the updated list to disk now that the removed log is uploaded.
  192. log_store()->TrimAndPersistUnsentLogs(/*overwrite_in_memory_store=*/true);
  193. }
  194. }
  195. // Error 400 indicates a problem with the log, not with the server, so
  196. // don't consider that a sign that the server is in trouble.
  197. bool server_is_healthy = upload_succeeded || response_code == 400;
  198. if (!log_store()->has_unsent_logs()) {
  199. DVLOG(1) << "Stopping upload_scheduler_.";
  200. upload_scheduler_->Stop();
  201. }
  202. upload_scheduler_->UploadFinished(server_is_healthy);
  203. }
  204. } // namespace metrics