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 36 class 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. 65 class 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. InconsistencyDetected(base::HistogramBase::Inconsistency problem)94 void InconsistencyDetected( 95 base::HistogramBase::Inconsistency problem) override {} UniqueInconsistencyDetected(base::HistogramBase::Inconsistency problem)96 void UniqueInconsistencyDetected( 97 base::HistogramBase::Inconsistency problem) override {} InconsistencyDetectedInLoggedCount(int amount)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