|  | /* | 
|  | * Copyright (C) 2015 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #ifndef METRICS_UPLOADER_UPLOAD_SERVICE_H_ | 
|  | #define METRICS_UPLOADER_UPLOAD_SERVICE_H_ | 
|  |  | 
|  | #include <memory> | 
|  | #include <string> | 
|  |  | 
|  | #include <base/metrics/histogram_base.h> | 
|  | #include <base/metrics/histogram_flattener.h> | 
|  | #include <base/metrics/histogram_snapshot_manager.h> | 
|  | #include <brillo/daemons/daemon.h> | 
|  |  | 
|  | #include "persistent_integer.h" | 
|  | #include "uploader/crash_counters.h" | 
|  | #include "uploader/metrics_log.h" | 
|  | #include "uploader/metricsd_service_runner.h" | 
|  | #include "uploader/proto/chrome_user_metrics_extension.pb.h" | 
|  | #include "uploader/sender.h" | 
|  | #include "uploader/system_profile_cache.h" | 
|  |  | 
|  | class SystemProfileSetter; | 
|  |  | 
|  | // Service responsible for backing up the currently aggregated metrics to disk | 
|  | // and uploading them periodically to the server. | 
|  | // | 
|  | // A given metrics sample can be in one of three locations. | 
|  | // * in-memory metrics: in memory aggregated metrics, waiting to be staged for | 
|  | //   upload. | 
|  | // * saved log: protobuf message, written to disk periodically and on shutdown | 
|  | //   to make a backup of metrics data for uploading later. | 
|  | // * staged log: protobuf message waiting to be uploaded. | 
|  | // | 
|  | // The service works as follows: | 
|  | // On startup, we create the in-memory metrics from the saved log if it exists. | 
|  | // | 
|  | // Periodically (every |disk_persistence_interval_| seconds), we take a snapshot | 
|  | // of the in-memory metrics and save them to disk. | 
|  | // | 
|  | // Periodically (every |upload_interval| seconds), we: | 
|  | // * take a snapshot of the in-memory metrics and create the staged log | 
|  | // * save the staged log to disk to avoid losing it if metricsd or the system | 
|  | //   crashes between two uploads. | 
|  | // * delete the last saved log: all the metrics contained in it are also in the | 
|  | //   newly created staged log. | 
|  | // | 
|  | // On shutdown (SIGINT or SIGTERM), we save the in-memory metrics to disk. | 
|  | // | 
|  | // Note: the in-memory metrics can be stored in |current_log_| or | 
|  | // base::StatisticsRecorder. | 
|  | class UploadService : public base::HistogramFlattener, public brillo::Daemon { | 
|  | public: | 
|  | UploadService(const std::string& server, | 
|  | const base::TimeDelta& upload_interval, | 
|  | const base::TimeDelta& disk_persistence_interval, | 
|  | const base::FilePath& private_metrics_directory, | 
|  | const base::FilePath& shared_metrics_directory); | 
|  |  | 
|  | // Initializes the upload service. | 
|  | int OnInit() override; | 
|  |  | 
|  | // Cleans up the internal state before exiting. | 
|  | void OnShutdown(int* exit_code) override; | 
|  |  | 
|  | // Starts a new log. The log needs to be regenerated after each successful | 
|  | // launch as it is destroyed when staging the log. | 
|  | void StartNewLog(); | 
|  |  | 
|  | // Saves the current metrics to a file. | 
|  | void PersistToDisk(); | 
|  |  | 
|  | // Triggers an upload event. | 
|  | void UploadEvent(); | 
|  |  | 
|  | // Sends the staged log. | 
|  | void SendStagedLog(); | 
|  |  | 
|  | // Implements inconsistency detection to match HistogramFlattener's | 
|  | // interface. | 
|  | void InconsistencyDetected( | 
|  | base::HistogramBase::Inconsistency problem) override {} | 
|  | void UniqueInconsistencyDetected( | 
|  | base::HistogramBase::Inconsistency problem) override {} | 
|  | void InconsistencyDetectedInLoggedCount(int amount) override {} | 
|  |  | 
|  | private: | 
|  | friend class UploadServiceTest; | 
|  |  | 
|  | FRIEND_TEST(UploadServiceTest, CanSendMultipleTimes); | 
|  | FRIEND_TEST(UploadServiceTest, CorruptedSavedLog); | 
|  | FRIEND_TEST(UploadServiceTest, CurrentLogSavedAndResumed); | 
|  | FRIEND_TEST(UploadServiceTest, DiscardLogsAfterTooManyFailedUpload); | 
|  | FRIEND_TEST(UploadServiceTest, EmptyLogsAreNotSent); | 
|  | FRIEND_TEST(UploadServiceTest, FailedSendAreRetried); | 
|  | FRIEND_TEST(UploadServiceTest, LogContainsAggregatedValues); | 
|  | FRIEND_TEST(UploadServiceTest, LogContainsCrashCounts); | 
|  | FRIEND_TEST(UploadServiceTest, LogEmptyAfterUpload); | 
|  | FRIEND_TEST(UploadServiceTest, LogEmptyByDefault); | 
|  | FRIEND_TEST(UploadServiceTest, LogFromTheMetricsLibrary); | 
|  | FRIEND_TEST(UploadServiceTest, LogKernelCrash); | 
|  | FRIEND_TEST(UploadServiceTest, LogUncleanShutdown); | 
|  | FRIEND_TEST(UploadServiceTest, LogUserCrash); | 
|  | FRIEND_TEST(UploadServiceTest, PersistEmptyLog); | 
|  | FRIEND_TEST(UploadServiceTest, UnknownCrashIgnored); | 
|  | FRIEND_TEST(UploadServiceTest, ValuesInConfigFileAreSent); | 
|  |  | 
|  | // Initializes the upload service for testing. | 
|  | void InitForTest(SystemProfileSetter* setter); | 
|  |  | 
|  | // If a staged log fails to upload more than kMaxFailedUpload times, it | 
|  | // will be discarded. | 
|  | static const int kMaxFailedUpload; | 
|  |  | 
|  | // Loads the log saved to disk if it exists. | 
|  | void LoadSavedLog(); | 
|  |  | 
|  | // Resets the internal state. | 
|  | void Reset(); | 
|  |  | 
|  | // Returns true iff metrics reporting is enabled. | 
|  | bool AreMetricsEnabled(); | 
|  |  | 
|  | // Event callback for handling Upload events. | 
|  | void UploadEventCallback(); | 
|  |  | 
|  | // Event callback for handling Persist events. | 
|  | void PersistEventCallback(); | 
|  |  | 
|  | // Aggregates all histogram available in memory and store them in the current | 
|  | // log. | 
|  | void GatherHistograms(); | 
|  |  | 
|  | // Callback for HistogramSnapshotManager to store the histograms. | 
|  | void RecordDelta(const base::HistogramBase& histogram, | 
|  | const base::HistogramSamples& snapshot) override; | 
|  |  | 
|  | // Compiles all the samples received into a single protobuf and adds all | 
|  | // system information. | 
|  | void StageCurrentLog(); | 
|  |  | 
|  | // Returns true iff a log is staged. | 
|  | bool HasStagedLog(); | 
|  |  | 
|  | // Remove the staged log iff the upload failed more than |kMaxFailedUpload|. | 
|  | void RemoveFailedLog(); | 
|  |  | 
|  | // Returns the current log. If there is no current log, creates it first. | 
|  | MetricsLog* GetOrCreateCurrentLog(); | 
|  |  | 
|  | std::unique_ptr<SystemProfileSetter> system_profile_setter_; | 
|  | base::HistogramSnapshotManager histogram_snapshot_manager_; | 
|  | std::unique_ptr<Sender> sender_; | 
|  | chromeos_metrics::PersistentInteger failed_upload_count_; | 
|  | std::unique_ptr<MetricsLog> current_log_; | 
|  | std::shared_ptr<CrashCounters> counters_; | 
|  |  | 
|  | base::TimeDelta upload_interval_; | 
|  | base::TimeDelta disk_persistence_interval_; | 
|  |  | 
|  | MetricsdServiceRunner metricsd_service_runner_; | 
|  |  | 
|  | base::FilePath consent_file_; | 
|  | base::FilePath staged_log_path_; | 
|  | base::FilePath saved_log_path_; | 
|  |  | 
|  | bool testing_; | 
|  | }; | 
|  |  | 
|  | #endif  // METRICS_UPLOADER_UPLOAD_SERVICE_H_ |