chromium/chrome/browser/metrics/perf/metric_collector.h

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_METRICS_PERF_METRIC_COLLECTOR_H_
#define CHROME_BROWSER_METRICS_PERF_METRIC_COLLECTOR_H_

#include <stdint.h>

#include <memory>
#include <string>

#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/metrics/perf/collection_params.h"

namespace metrics {

class SampledProfile;

namespace internal {

// MetricCollector implements the basic collector functionality, including the
// scheduling and synchronization logic between the various trigger events, and
// the profile post-processing logic. Except for the constructor that can be
// invoked from a different thread, all its methods run on the same sequence,
// which is enforced by a sequence checker. A collector is managed by a
// MetricProvider, including the sequence on which it runs.
class MetricCollector {
 public:
  using ProfileDoneCallback =
      base::RepeatingCallback<void(std::unique_ptr<SampledProfile>)>;

  // It may be invoked on a difference sequence than the member functions.
  MetricCollector(const std::string& name,
                  const CollectionParams& collection_params);

  MetricCollector(const MetricCollector&) = delete;
  MetricCollector& operator=(const MetricCollector&) = delete;

  virtual ~MetricCollector();

  virtual const char* ToolName() const = 0;

  void Init();

  // These methods are used to update the cached_data_size_ field via PostTask
  // from the provider.
  void AddCachedDataDelta(size_t delta);
  void ResetCachedDataSize();

  // Turns on profile collection. Resets the timer that's used to schedule
  // collections.
  void RecordUserLogin(base::TimeTicks login_time);

  // Deactivates the timer and turns off profile collection. Does not delete any
  // profile data that was already collected.
  void StopTimer();

  // Schedules a collection after a resume from suspend event. A collection is
  // scheduled with the probablity given by the sampling factor stored in
  // |collection_params_|.
  void ScheduleSuspendDoneCollection(base::TimeDelta sleep_duration);

  // Schedules a collection after a session restore event. A collection is
  // scheduled with the probablity given by the sampling factor stored in
  // |collection_params_|.
  void ScheduleSessionRestoreCollection(int num_tabs_restored);

  // Called when a jank started/stopped.
  void OnJankStarted();
  void OnJankStopped();

  void set_profile_done_callback(ProfileDoneCallback cb) {
    profile_done_callback_ = std::move(cb);
  }

 protected:
  // Enumeration representing success and various failure modes for collecting
  // profile data. These values are persisted to logs. Entries should not be
  // renumbered and numeric values should never be reused.
  enum class CollectionAttemptStatus {
    SUCCESS,
    NOT_READY_TO_COLLECT,
    INCOGNITO_ACTIVE,
    INCOGNITO_LAUNCHED,
    PROTOBUF_NOT_PARSED,
    ILLEGAL_DATA_RETURNED,
    ALREADY_COLLECTING,
    UNABLE_TO_COLLECT,
    DATA_COLLECTION_FAILED,
    SESSION_HAS_ZERO_SAMPLES,
    NUM_OUTCOMES
  };

  // Returns a WeakPtr to this instance.
  virtual base::WeakPtr<MetricCollector> GetWeakPtr() = 0;

  // Collector specific initialization.
  virtual void SetUp() {}

  // Saves the given outcome to the uma histogram associated with the collector.
  void AddToUmaHistogram(CollectionAttemptStatus outcome) const;

  // Returns whether the underlying timer is running or not.
  bool IsRunning() { return timer_.IsRunning(); }
  // Returns the current timer delay. Useful for debugging.
  base::TimeDelta CurrentTimerDelay() { return timer_.GetCurrentDelay(); }

  base::TimeTicks login_time() const { return login_time_; }

  // Collects perf data after a resume. |sleep_duration| is the duration the
  // system was suspended before resuming. |time_after_resume_ms| is how long
  // ago the system resumed.
  void CollectPerfDataAfterResume(base::TimeDelta sleep_duration,
                                  base::TimeDelta time_after_resume);

  // Collects perf data after a session restore. |time_after_restore| is how
  // long ago the session restore started. |num_tabs_restored| is the total
  // number of tabs being restored.
  void CollectPerfDataAfterSessionRestore(base::TimeDelta time_after_restore,
                                          int num_tabs_restored);

  // Selects a random time in the upcoming profiling interval that begins at
  // |next_profiling_interval_start|. Schedules |timer| to invoke
  // DoPeriodicCollection() when that time comes.
  void ScheduleIntervalCollection();

  // Collects profiles on a repeating basis by calling CollectIfNecessary() and
  // reschedules it to be collected again.
  void DoPeriodicCollection();

  // Collects a profile for a given |trigger_event| if necessary.
  void CollectIfNecessary(std::unique_ptr<SampledProfile> sampled_profile);

  // Returns if it's valid and safe for a collector to gather a profile.
  // A collector implementation can override this logic.
  virtual bool ShouldCollect() const;

  // Collector specific logic for collecting a profile.
  virtual void CollectProfile(
      std::unique_ptr<SampledProfile> sampled_profile) = 0;

  // Collector specific logic for stopping the current collection.
  virtual void StopCollection() {}

  // Parses the given serialized perf data proto. If valid, it adds it to the
  // given sampled_profile and stores it in the local profile data cache.
  void SaveSerializedPerfProto(std::unique_ptr<SampledProfile> sampled_profile,
                               std::string serialized_proto);

  // Returns a const reference to the collection_params.
  const CollectionParams& collection_params() const {
    return collection_params_;
  }

  // Returns a mutable reference to the collection_params, so that collectors
  // and tests can update the params.
  CollectionParams& collection_params() { return collection_params_; }

  // The size of cached profile data.
  size_t cached_data_size_ = 0;

  // Checks that some methods are called on the collector sequence.
  SEQUENCE_CHECKER(sequence_checker_);

 private:
  // Parameters controlling how profiles are collected. Initialized at
  // collector creation time. Then accessed only on the collector sequence.
  CollectionParams collection_params_;

  // For scheduling collection of profile data.
  base::OneShotTimer timer_;

  // Record of the last login time.
  base::TimeTicks login_time_;

  // Record of the start of the upcoming profiling interval.
  base::TimeTicks next_profiling_interval_start_;

  // Tracks the last time a session restore was collected.
  base::TimeTicks last_session_restore_collection_time_;

  // Name of the histogram that represents the success and various failure
  // modes of collection attempts.
  const std::string collect_uma_histogram_;

  // A callback to be Run on each successfully collected profile.
  ProfileDoneCallback profile_done_callback_;
};

}  // namespace internal

}  // namespace metrics

#endif  // CHROME_BROWSER_METRICS_PERF_METRIC_COLLECTOR_H_