1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef METRICS_UPLOADER_UPLOAD_SERVICE_H_ 18#define METRICS_UPLOADER_UPLOAD_SERVICE_H_ 19 20#include <memory> 21#include <string> 22 23#include <base/metrics/histogram_base.h> 24#include <base/metrics/histogram_flattener.h> 25#include <base/metrics/histogram_snapshot_manager.h> 26#include <brillo/daemons/daemon.h> 27 28#include "persistent_integer.h" 29#include "uploader/crash_counters.h" 30#include "uploader/metrics_log.h" 31#include "uploader/metricsd_service_runner.h" 32#include "uploader/proto/chrome_user_metrics_extension.pb.h" 33#include "uploader/sender.h" 34#include "uploader/system_profile_cache.h" 35 36class SystemProfileSetter; 37 38// Service responsible for backing up the currently aggregated metrics to disk 39// and uploading them periodically to the server. 40// 41// A given metrics sample can be in one of three locations. 42// * in-memory metrics: in memory aggregated metrics, waiting to be staged for 43// upload. 44// * saved log: protobuf message, written to disk periodically and on shutdown 45// to make a backup of metrics data for uploading later. 46// * staged log: protobuf message waiting to be uploaded. 47// 48// The service works as follows: 49// On startup, we create the in-memory metrics from the saved log if it exists. 50// 51// Periodically (every |disk_persistence_interval_| seconds), we take a snapshot 52// of the in-memory metrics and save them to disk. 53// 54// Periodically (every |upload_interval| seconds), we: 55// * take a snapshot of the in-memory metrics and create the staged log 56// * save the staged log to disk to avoid losing it if metricsd or the system 57// crashes between two uploads. 58// * delete the last saved log: all the metrics contained in it are also in the 59// newly created staged log. 60// 61// On shutdown (SIGINT or SIGTERM), we save the in-memory metrics to disk. 62// 63// Note: the in-memory metrics can be stored in |current_log_| or 64// base::StatisticsRecorder. 65class UploadService : public base::HistogramFlattener, public brillo::Daemon { 66 public: 67 UploadService(const std::string& server, 68 const base::TimeDelta& upload_interval, 69 const base::TimeDelta& disk_persistence_interval, 70 const base::FilePath& private_metrics_directory, 71 const base::FilePath& shared_metrics_directory); 72 73 // Initializes the upload service. 74 int OnInit() override; 75 76 // Cleans up the internal state before exiting. 77 void OnShutdown(int* exit_code) override; 78 79 // Starts a new log. The log needs to be regenerated after each successful 80 // launch as it is destroyed when staging the log. 81 void StartNewLog(); 82 83 // Saves the current metrics to a file. 84 void PersistToDisk(); 85 86 // Triggers an upload event. 87 void UploadEvent(); 88 89 // Sends the staged log. 90 void SendStagedLog(); 91 92 // Implements inconsistency detection to match HistogramFlattener's 93 // interface. 94 void InconsistencyDetected( 95 base::HistogramBase::Inconsistency problem) override {} 96 void UniqueInconsistencyDetected( 97 base::HistogramBase::Inconsistency problem) override {} 98 void InconsistencyDetectedInLoggedCount(int amount) override {} 99 100 private: 101 friend class UploadServiceTest; 102 103 FRIEND_TEST(UploadServiceTest, CanSendMultipleTimes); 104 FRIEND_TEST(UploadServiceTest, CorruptedSavedLog); 105 FRIEND_TEST(UploadServiceTest, CurrentLogSavedAndResumed); 106 FRIEND_TEST(UploadServiceTest, DiscardLogsAfterTooManyFailedUpload); 107 FRIEND_TEST(UploadServiceTest, EmptyLogsAreNotSent); 108 FRIEND_TEST(UploadServiceTest, FailedSendAreRetried); 109 FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues); 110 FRIEND_TEST(UploadServiceTest, LogContainsCrashCounts); 111 FRIEND_TEST(UploadServiceTest, LogEmptyAfterUpload); 112 FRIEND_TEST(UploadServiceTest, LogEmptyByDefault); 113 FRIEND_TEST(UploadServiceTest, LogFromTheMetricsLibrary); 114 FRIEND_TEST(UploadServiceTest, LogKernelCrash); 115 FRIEND_TEST(UploadServiceTest, LogUncleanShutdown); 116 FRIEND_TEST(UploadServiceTest, LogUserCrash); 117 FRIEND_TEST(UploadServiceTest, PersistEmptyLog); 118 FRIEND_TEST(UploadServiceTest, UnknownCrashIgnored); 119 FRIEND_TEST(UploadServiceTest, ValuesInConfigFileAreSent); 120 121 // Initializes the upload service for testing. 122 void InitForTest(SystemProfileSetter* setter); 123 124 // If a staged log fails to upload more than kMaxFailedUpload times, it 125 // will be discarded. 126 static const int kMaxFailedUpload; 127 128 // Loads the log saved to disk if it exists. 129 void LoadSavedLog(); 130 131 // Resets the internal state. 132 void Reset(); 133 134 // Returns true iff metrics reporting is enabled. 135 bool AreMetricsEnabled(); 136 137 // Event callback for handling Upload events. 138 void UploadEventCallback(); 139 140 // Event callback for handling Persist events. 141 void PersistEventCallback(); 142 143 // Aggregates all histogram available in memory and store them in the current 144 // log. 145 void GatherHistograms(); 146 147 // Callback for HistogramSnapshotManager to store the histograms. 148 void RecordDelta(const base::HistogramBase& histogram, 149 const base::HistogramSamples& snapshot) override; 150 151 // Compiles all the samples received into a single protobuf and adds all 152 // system information. 153 void StageCurrentLog(); 154 155 // Returns true iff a log is staged. 156 bool HasStagedLog(); 157 158 // Remove the staged log iff the upload failed more than |kMaxFailedUpload|. 159 void RemoveFailedLog(); 160 161 // Returns the current log. If there is no current log, creates it first. 162 MetricsLog* GetOrCreateCurrentLog(); 163 164 std::unique_ptr<SystemProfileSetter> system_profile_setter_; 165 base::HistogramSnapshotManager histogram_snapshot_manager_; 166 std::unique_ptr<Sender> sender_; 167 chromeos_metrics::PersistentInteger failed_upload_count_; 168 std::unique_ptr<MetricsLog> current_log_; 169 std::shared_ptr<CrashCounters> counters_; 170 171 base::TimeDelta upload_interval_; 172 base::TimeDelta disk_persistence_interval_; 173 174 MetricsdServiceRunner metricsd_service_runner_; 175 176 base::FilePath consent_file_; 177 base::FilePath staged_log_path_; 178 base::FilePath saved_log_path_; 179 180 bool testing_; 181}; 182 183#endif // METRICS_UPLOADER_UPLOAD_SERVICE_H_ 184