Home | History | Annotate | Download | only in uploader
      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.
     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