Merge "metricsd: Collect generic stats about the system."
This commit is contained in:
commit
eeedcc4150
5 changed files with 105 additions and 7 deletions
|
|
@ -84,6 +84,7 @@ include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := libmetrics
|
LOCAL_MODULE := libmetrics
|
||||||
LOCAL_C_INCLUDES := $(metrics_includes)
|
LOCAL_C_INCLUDES := $(metrics_includes)
|
||||||
LOCAL_CFLAGS := $(metrics_CFLAGS)
|
LOCAL_CFLAGS := $(metrics_CFLAGS)
|
||||||
|
LOCAL_CLANG := true
|
||||||
LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
|
LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
|
||||||
LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
|
LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
|
||||||
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
|
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
|
||||||
|
|
@ -97,6 +98,7 @@ include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := metrics_client
|
LOCAL_MODULE := metrics_client
|
||||||
LOCAL_C_INCLUDES := $(metrics_includes)
|
LOCAL_C_INCLUDES := $(metrics_includes)
|
||||||
LOCAL_CFLAGS := $(metrics_CFLAGS)
|
LOCAL_CFLAGS := $(metrics_CFLAGS)
|
||||||
|
LOCAL_CLANG := true
|
||||||
LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
|
LOCAL_CPP_EXTENSION := $(metrics_cpp_extension)
|
||||||
LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
|
LOCAL_CPPFLAGS := $(metrics_CPPFLAGS)
|
||||||
LOCAL_SHARED_LIBRARIES := $(metrics_shared_libraries) \
|
LOCAL_SHARED_LIBRARIES := $(metrics_shared_libraries) \
|
||||||
|
|
@ -132,7 +134,10 @@ LOCAL_SHARED_LIBRARIES := $(metrics_shared_libraries) \
|
||||||
libchromeos-http \
|
libchromeos-http \
|
||||||
libchromeos-dbus \
|
libchromeos-dbus \
|
||||||
libcutils \
|
libcutils \
|
||||||
libdbus
|
libdbus \
|
||||||
|
librootdev
|
||||||
|
|
||||||
|
LOCAL_CLANG := true
|
||||||
LOCAL_SRC_FILES := $(metrics_daemon_sources)
|
LOCAL_SRC_FILES := $(metrics_daemon_sources)
|
||||||
LOCAL_STATIC_LIBRARIES := metrics_daemon_protos
|
LOCAL_STATIC_LIBRARIES := metrics_daemon_protos
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,8 @@ const char kMetricWriteSectorsShortName[] = "Platform.WriteSectorsShort";
|
||||||
const int kMetricStatsShortInterval = 1; // seconds
|
const int kMetricStatsShortInterval = 1; // seconds
|
||||||
const int kMetricStatsLongInterval = 30; // seconds
|
const int kMetricStatsLongInterval = 30; // seconds
|
||||||
|
|
||||||
|
const int kMetricMeminfoInterval = 30; // seconds
|
||||||
|
|
||||||
// Assume a max rate of 250Mb/s for reads (worse for writes) and 512 byte
|
// Assume a max rate of 250Mb/s for reads (worse for writes) and 512 byte
|
||||||
// sectors.
|
// sectors.
|
||||||
const int kMetricSectorsIOMax = 500000; // sectors/second
|
const int kMetricSectorsIOMax = 500000; // sectors/second
|
||||||
|
|
@ -110,6 +112,7 @@ const char kMetricsProcStatFileName[] = "/proc/stat";
|
||||||
const char kVmStatFileName[] = "/proc/vmstat";
|
const char kVmStatFileName[] = "/proc/vmstat";
|
||||||
const char kMeminfoFileName[] = "/proc/meminfo";
|
const char kMeminfoFileName[] = "/proc/meminfo";
|
||||||
const int kMetricsProcStatFirstLineItemsCount = 11;
|
const int kMetricsProcStatFirstLineItemsCount = 11;
|
||||||
|
const int kDiskMetricsStatItemCount = 11;
|
||||||
|
|
||||||
// Thermal CPU throttling.
|
// Thermal CPU throttling.
|
||||||
|
|
||||||
|
|
@ -215,6 +218,7 @@ void MetricsDaemon::Init(bool testing,
|
||||||
bool uploader_active,
|
bool uploader_active,
|
||||||
bool dbus_enabled,
|
bool dbus_enabled,
|
||||||
MetricsLibraryInterface* metrics_lib,
|
MetricsLibraryInterface* metrics_lib,
|
||||||
|
const string& diskstats_path,
|
||||||
const string& scaling_max_freq_path,
|
const string& scaling_max_freq_path,
|
||||||
const string& cpuinfo_max_freq_path,
|
const string& cpuinfo_max_freq_path,
|
||||||
const base::TimeDelta& upload_interval,
|
const base::TimeDelta& upload_interval,
|
||||||
|
|
@ -273,8 +277,13 @@ void MetricsDaemon::Init(bool testing,
|
||||||
weekly_cycle_.reset(new PersistentInteger("weekly.cycle"));
|
weekly_cycle_.reset(new PersistentInteger("weekly.cycle"));
|
||||||
version_cycle_.reset(new PersistentInteger("version.cycle"));
|
version_cycle_.reset(new PersistentInteger("version.cycle"));
|
||||||
|
|
||||||
|
diskstats_path_ = diskstats_path;
|
||||||
scaling_max_freq_path_ = scaling_max_freq_path;
|
scaling_max_freq_path_ = scaling_max_freq_path;
|
||||||
cpuinfo_max_freq_path_ = cpuinfo_max_freq_path;
|
cpuinfo_max_freq_path_ = cpuinfo_max_freq_path;
|
||||||
|
|
||||||
|
// If testing, initialize Stats Reporter without connecting DBus
|
||||||
|
if (testing_)
|
||||||
|
StatsReporterInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
int MetricsDaemon::OnInit() {
|
int MetricsDaemon::OnInit() {
|
||||||
|
|
@ -283,6 +292,13 @@ int MetricsDaemon::OnInit() {
|
||||||
if (return_code != EX_OK)
|
if (return_code != EX_OK)
|
||||||
return return_code;
|
return return_code;
|
||||||
|
|
||||||
|
StatsReporterInit();
|
||||||
|
|
||||||
|
// Start collecting meminfo stats.
|
||||||
|
ScheduleMeminfoCallback(kMetricMeminfoInterval);
|
||||||
|
memuse_final_time_ = GetActiveTime() + kMemuseIntervals[0];
|
||||||
|
ScheduleMemuseCallback(kMemuseIntervals[0]);
|
||||||
|
|
||||||
if (testing_)
|
if (testing_)
|
||||||
return EX_OK;
|
return EX_OK;
|
||||||
|
|
||||||
|
|
@ -313,6 +329,11 @@ int MetricsDaemon::OnInit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||||
|
base::Bind(&MetricsDaemon::HandleUpdateStatsTimeout,
|
||||||
|
base::Unretained(this)),
|
||||||
|
base::TimeDelta::FromMilliseconds(kUpdateStatsIntervalMs));
|
||||||
|
|
||||||
if (uploader_active_) {
|
if (uploader_active_) {
|
||||||
upload_service_.reset(
|
upload_service_.reset(
|
||||||
new UploadService(new SystemProfileCache(), metrics_lib_, server_));
|
new UploadService(new SystemProfileCache(), metrics_lib_, server_));
|
||||||
|
|
@ -494,6 +515,40 @@ void MetricsDaemon::ScheduleStatsCallback(int wait) {
|
||||||
base::TimeDelta::FromSeconds(wait));
|
base::TimeDelta::FromSeconds(wait));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MetricsDaemon::DiskStatsReadStats(uint64_t* read_sectors,
|
||||||
|
uint64_t* write_sectors) {
|
||||||
|
CHECK(read_sectors);
|
||||||
|
CHECK(write_sectors);
|
||||||
|
std::string line;
|
||||||
|
if (diskstats_path_.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!base::ReadFileToString(base::FilePath(diskstats_path_), &line)) {
|
||||||
|
PLOG(WARNING) << "Could not read disk stats from " << diskstats_path_;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> parts = base::SplitString(
|
||||||
|
line, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||||
|
if (parts.size() != kDiskMetricsStatItemCount) {
|
||||||
|
LOG(ERROR) << "Could not parse disk stat correctly. Expected "
|
||||||
|
<< kDiskMetricsStatItemCount << " elements but got "
|
||||||
|
<< parts.size();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!base::StringToUint64(parts[2], read_sectors)) {
|
||||||
|
LOG(ERROR) << "Couldn't convert read sectors " << parts[2] << " to uint64";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!base::StringToUint64(parts[6], write_sectors)) {
|
||||||
|
LOG(ERROR) << "Couldn't convert write sectors " << parts[6] << " to uint64";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool MetricsDaemon::VmStatsParseStats(const char* stats,
|
bool MetricsDaemon::VmStatsParseStats(const char* stats,
|
||||||
struct VmstatRecord* record) {
|
struct VmstatRecord* record) {
|
||||||
CHECK(stats);
|
CHECK(stats);
|
||||||
|
|
@ -712,11 +767,7 @@ void MetricsDaemon::MeminfoCallback(base::TimeDelta wait) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Make both calls even if the first one fails.
|
// Make both calls even if the first one fails.
|
||||||
bool success = ProcessMeminfo(meminfo_raw);
|
if (ProcessMeminfo(meminfo_raw)) {
|
||||||
bool reschedule =
|
|
||||||
ReportZram(base::FilePath(FILE_PATH_LITERAL("/sys/block/zram0"))) &&
|
|
||||||
success;
|
|
||||||
if (reschedule) {
|
|
||||||
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||||
base::Bind(&MetricsDaemon::MeminfoCallback, base::Unretained(this),
|
base::Bind(&MetricsDaemon::MeminfoCallback, base::Unretained(this),
|
||||||
wait),
|
wait),
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ class MetricsDaemon : public chromeos::DBusDaemon {
|
||||||
bool uploader_active,
|
bool uploader_active,
|
||||||
bool dbus_enabled,
|
bool dbus_enabled,
|
||||||
MetricsLibraryInterface* metrics_lib,
|
MetricsLibraryInterface* metrics_lib,
|
||||||
|
const std::string& diskstats_path,
|
||||||
const std::string& cpuinfo_max_freq_path,
|
const std::string& cpuinfo_max_freq_path,
|
||||||
const std::string& scaling_max_freq_path,
|
const std::string& scaling_max_freq_path,
|
||||||
const base::TimeDelta& upload_interval,
|
const base::TimeDelta& upload_interval,
|
||||||
|
|
@ -78,6 +79,7 @@ class MetricsDaemon : public chromeos::DBusDaemon {
|
||||||
FRIEND_TEST(MetricsDaemonTest, GetHistogramPath);
|
FRIEND_TEST(MetricsDaemonTest, GetHistogramPath);
|
||||||
FRIEND_TEST(MetricsDaemonTest, IsNewEpoch);
|
FRIEND_TEST(MetricsDaemonTest, IsNewEpoch);
|
||||||
FRIEND_TEST(MetricsDaemonTest, MessageFilter);
|
FRIEND_TEST(MetricsDaemonTest, MessageFilter);
|
||||||
|
FRIEND_TEST(MetricsDaemonTest, ParseDiskStats);
|
||||||
FRIEND_TEST(MetricsDaemonTest, ParseVmStats);
|
FRIEND_TEST(MetricsDaemonTest, ParseVmStats);
|
||||||
FRIEND_TEST(MetricsDaemonTest, ProcessKernelCrash);
|
FRIEND_TEST(MetricsDaemonTest, ProcessKernelCrash);
|
||||||
FRIEND_TEST(MetricsDaemonTest, ProcessMeminfo);
|
FRIEND_TEST(MetricsDaemonTest, ProcessMeminfo);
|
||||||
|
|
@ -86,7 +88,6 @@ class MetricsDaemon : public chromeos::DBusDaemon {
|
||||||
FRIEND_TEST(MetricsDaemonTest, ProcessUserCrash);
|
FRIEND_TEST(MetricsDaemonTest, ProcessUserCrash);
|
||||||
FRIEND_TEST(MetricsDaemonTest, ReportCrashesDailyFrequency);
|
FRIEND_TEST(MetricsDaemonTest, ReportCrashesDailyFrequency);
|
||||||
FRIEND_TEST(MetricsDaemonTest, ReadFreqToInt);
|
FRIEND_TEST(MetricsDaemonTest, ReadFreqToInt);
|
||||||
FRIEND_TEST(MetricsDaemonTest, ReportDiskStats);
|
|
||||||
FRIEND_TEST(MetricsDaemonTest, ReportKernelCrashInterval);
|
FRIEND_TEST(MetricsDaemonTest, ReportKernelCrashInterval);
|
||||||
FRIEND_TEST(MetricsDaemonTest, ReportUncleanShutdownInterval);
|
FRIEND_TEST(MetricsDaemonTest, ReportUncleanShutdownInterval);
|
||||||
FRIEND_TEST(MetricsDaemonTest, ReportUserCrashInterval);
|
FRIEND_TEST(MetricsDaemonTest, ReportUserCrashInterval);
|
||||||
|
|
@ -324,6 +325,7 @@ class MetricsDaemon : public chromeos::DBusDaemon {
|
||||||
scoped_ptr<PersistentInteger> unclean_shutdowns_daily_count_;
|
scoped_ptr<PersistentInteger> unclean_shutdowns_daily_count_;
|
||||||
scoped_ptr<PersistentInteger> unclean_shutdowns_weekly_count_;
|
scoped_ptr<PersistentInteger> unclean_shutdowns_weekly_count_;
|
||||||
|
|
||||||
|
std::string diskstats_path_;
|
||||||
std::string scaling_max_freq_path_;
|
std::string scaling_max_freq_path_;
|
||||||
std::string cpuinfo_max_freq_path_;
|
std::string cpuinfo_max_freq_path_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include <base/strings/string_util.h>
|
#include <base/strings/string_util.h>
|
||||||
#include <chromeos/flag_helper.h>
|
#include <chromeos/flag_helper.h>
|
||||||
#include <chromeos/syslog_logging.h>
|
#include <chromeos/syslog_logging.h>
|
||||||
|
#include <rootdev.h>
|
||||||
|
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "metrics_daemon.h"
|
#include "metrics_daemon.h"
|
||||||
|
|
@ -29,6 +30,28 @@ const char kScalingMaxFreqPath[] =
|
||||||
const char kCpuinfoMaxFreqPath[] =
|
const char kCpuinfoMaxFreqPath[] =
|
||||||
"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
|
"/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
|
||||||
|
|
||||||
|
// Returns the path to the disk stats in the sysfs. Returns the null string if
|
||||||
|
// it cannot find the disk stats file.
|
||||||
|
static
|
||||||
|
const std::string MetricsMainDiskStatsPath() {
|
||||||
|
char dev_path_cstr[PATH_MAX];
|
||||||
|
std::string dev_prefix = "/dev/block/";
|
||||||
|
std::string dev_path;
|
||||||
|
|
||||||
|
int ret = rootdev(dev_path_cstr, sizeof(dev_path_cstr), true, true);
|
||||||
|
if (ret != 0) {
|
||||||
|
LOG(WARNING) << "error " << ret << " determining root device";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
dev_path = dev_path_cstr;
|
||||||
|
// Check that rootdev begins with "/dev/block/".
|
||||||
|
if (!base::StartsWithASCII(dev_path, dev_prefix, false)) {
|
||||||
|
LOG(WARNING) << "unexpected root device " << dev_path;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return "/sys/class/block/" + dev_path.substr(dev_prefix.length()) + "/stat";
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
DEFINE_bool(daemon, true, "run as daemon (use -nodaemon for debugging)");
|
DEFINE_bool(daemon, true, "run as daemon (use -nodaemon for debugging)");
|
||||||
|
|
||||||
|
|
@ -75,6 +98,7 @@ int main(int argc, char** argv) {
|
||||||
FLAGS_uploader | FLAGS_uploader_test,
|
FLAGS_uploader | FLAGS_uploader_test,
|
||||||
FLAGS_withdbus,
|
FLAGS_withdbus,
|
||||||
&metrics_lib,
|
&metrics_lib,
|
||||||
|
MetricsMainDiskStatsPath(),
|
||||||
kScalingMaxFreqPath,
|
kScalingMaxFreqPath,
|
||||||
kCpuinfoMaxFreqPath,
|
kCpuinfoMaxFreqPath,
|
||||||
base::TimeDelta::FromSeconds(FLAGS_upload_interval_secs),
|
base::TimeDelta::FromSeconds(FLAGS_upload_interval_secs),
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ class MetricsDaemonTest : public testing::Test {
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
&metrics_lib_,
|
&metrics_lib_,
|
||||||
|
disk_stats_path_.value(),
|
||||||
scaling_max_freq_path_.value(),
|
scaling_max_freq_path_.value(),
|
||||||
cpu_max_freq_path_.value(),
|
cpu_max_freq_path_.value(),
|
||||||
base::TimeDelta::FromMinutes(30),
|
base::TimeDelta::FromMinutes(30),
|
||||||
|
|
@ -198,6 +199,21 @@ TEST_F(MetricsDaemonTest, SendSample) {
|
||||||
/* min */ 1, /* max */ 100, /* buckets */ 50);
|
/* min */ 1, /* max */ 100, /* buckets */ 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(MetricsDaemonTest, ParseDiskStats) {
|
||||||
|
uint64_t read_sectors_now, write_sectors_now;
|
||||||
|
CreateFakeDiskStatsFile(kFakeDiskStats0);
|
||||||
|
ASSERT_TRUE(daemon_.DiskStatsReadStats(&read_sectors_now,
|
||||||
|
&write_sectors_now));
|
||||||
|
EXPECT_EQ(read_sectors_now, kFakeReadSectors[0]);
|
||||||
|
EXPECT_EQ(write_sectors_now, kFakeWriteSectors[0]);
|
||||||
|
|
||||||
|
CreateFakeDiskStatsFile(kFakeDiskStats1);
|
||||||
|
ASSERT_TRUE(daemon_.DiskStatsReadStats(&read_sectors_now,
|
||||||
|
&write_sectors_now));
|
||||||
|
EXPECT_EQ(read_sectors_now, kFakeReadSectors[1]);
|
||||||
|
EXPECT_EQ(write_sectors_now, kFakeWriteSectors[1]);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(MetricsDaemonTest, ProcessMeminfo) {
|
TEST_F(MetricsDaemonTest, ProcessMeminfo) {
|
||||||
string meminfo =
|
string meminfo =
|
||||||
"MemTotal: 2000000 kB\nMemFree: 500000 kB\n"
|
"MemTotal: 2000000 kB\nMemFree: 500000 kB\n"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue