blob: e3bc8fc2443c6b134473c0ce00c0458d840faf75 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_METRICS_LOGIN_EVENT_RECORDER_H_
#define CHROMEOS_METRICS_LOGIN_EVENT_RECORDER_H_
#include <vector>
#include "base/callback.h"
#include "base/component_export.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class SequencedTaskRunner;
}
namespace chromeos {
// LoginEventRecorder is a utility class used to save the bootimes of Chrome OS.
class COMPONENT_EXPORT(CHROMEOS_METRICS) LoginEventRecorder {
public:
class TimeMarker {
public:
TimeMarker(const char* name,
absl::optional<std::string> url,
bool send_to_uma,
bool write_to_file);
TimeMarker(const TimeMarker& other);
~TimeMarker();
const char* name() const { return name_; }
base::Time time() const { return time_; }
const absl::optional<std::string>& url() const { return url_; }
bool send_to_uma() const { return send_to_uma_; }
bool write_to_file() const { return write_to_file_; }
// comparator for sorting
bool operator<(const TimeMarker& other) const {
return time_ < other.time_;
}
private:
friend class std::vector<TimeMarker>;
const char* name_;
base::Time time_ = base::Time::NowFromSystemTime();
absl::optional<std::string> url_;
bool send_to_uma_;
bool write_to_file_;
};
class Stats {
public:
// Initializes stats with current /proc values.
static Stats GetCurrentStats();
// Returns JSON representation.
std::string SerializeToString() const;
// Creates new object from JSON representation.
static Stats DeserializeFromString(const std::string& value);
const std::string& uptime() const { return uptime_; }
const std::string& disk() const { return disk_; }
// Writes "uptime in seconds" to result. (This is first field in uptime_.)
// Returns true on successful conversion.
bool UptimeDouble(double* result) const;
// Stores stats to 'type-name' file with the given |name|.
// I.e. '/tmp/uptime-logout-started' and '/tmp/disk-logout-started' for
// name='logout-started'.
//
// When |write_flag_file| is true, also creates 'stats-name.written' flag
// file to signal that stats were appended.
// I.e. '/tmp/stats-logout-started.written' for name='logout-started'.
void RecordStats(const std::string& name, bool write_flag_file) const;
void RecordStatsWithCallback(const std::string& name,
bool write_flag_file,
base::OnceClosure callback) const;
private:
// Runs asynchronously when RecordStats(WithCallback) is called.
void RecordStatsAsync(const std::string& name, bool write_flag_file) const;
std::string uptime_;
std::string disk_;
};
LoginEventRecorder();
LoginEventRecorder(const LoginEventRecorder&) = delete;
LoginEventRecorder& operator=(const LoginEventRecorder&) = delete;
virtual ~LoginEventRecorder();
static LoginEventRecorder* Get();
// Add a time marker for login. A timeline will be dumped to
// /tmp/login-times-sent after login is done. If |send_to_uma| is true
// the time between this marker and the last will be sent to UMA with
// the identifier BootTime.|marker_name|.
void AddLoginTimeMarker(const char* marker_name,
bool send_to_uma,
bool write_to_file = true);
void AddLoginTimeMarkerWithURL(const char* marker_name,
absl::optional<std::string> url,
bool send_to_uma,
bool write_to_file = true);
// Add a time marker for logout. A timeline will be dumped to
// /tmp/logout-times-sent after logout is done. If |send_to_uma| is true
// the time between this marker and the last will be sent to UMA with
// the identifier ShutdownTime.|marker_name|.
void AddLogoutTimeMarker(const char* marker_name, bool send_to_uma);
// Record events for successful authentication.
void RecordAuthenticationSuccess();
// Record events for authentication failure.
void RecordAuthenticationFailure();
void ClearLoginTimeMarkers();
// Records current uptime and disk usage for metrics use.
// Posts task to file thread.
// name will be used as part of file names in /tmp.
// Existing stats files will not be overwritten.
void RecordCurrentStats(const std::string& name);
// Schedule writing login times to logs.
void ScheduleWriteLoginTimes(const std::string base_name,
const std::string uma_name,
const std::string uma_prefix);
// Immediately execute the task to write login times.
void RunScheduledWriteLoginTimes();
// Write logout times to logs.
void WriteLogoutTimes(const std::string base_name,
const std::string uma_name,
const std::string uma_prefix);
// Stores a copy of the events to be retrieved by tests.
// Also all future events will have stored copies for testing.
void PrepareEventCollectionForTesting();
// Returns list of all events collected.
const std::vector<TimeMarker>& GetCollectedLoginEventsForTesting();
private:
void AddMarker(std::vector<TimeMarker>* vector, TimeMarker&& marker);
void WriteLoginTimesDelayed();
std::vector<TimeMarker> login_time_markers_;
std::vector<TimeMarker> logout_time_markers_;
base::OnceCallback<void(std::vector<TimeMarker>)> callback_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
// This list is never cleared. It has copy of all the login events that
// login_time_markers_ had when PrepareEventCollectionForTesting() was
// called and all login avents since that moment.
absl::optional<std::vector<TimeMarker>> login_time_markers_for_testing_;
base::WeakPtrFactory<LoginEventRecorder> weak_ptr_factory_{this};
};
} // namespace chromeos
// TODO(https://crbug.com/1164001): remove after the migration is finished.
namespace ash {
using ::chromeos::LoginEventRecorder;
}
#endif // CHROMEOS_METRICS_LOGIN_EVENT_RECORDER_H_