blob: 2af68521928fc938e9e8959477f4ade48a3d13ca [file] [log] [blame]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <deque>
#include <limits>
#include <string>
#include <vector>
#include <base/command_line.h>
#include <base/logging.h>
#include "base/files/file_path.h"
#include <base/files/file_util.h>
#include <base/files/file_enumerator.h>
#include <brillo/syslog_logging.h>
#include <metrics/metrics_library.h>
#include "croslog/constants.h"
#include "croslog/log_parser_audit.h"
#include "croslog/log_parser_syslog.h"
#include "croslog/metrics_collector_util.h"
namespace {
///////////////////////////////////////////////////////////////////////////////
// Min, max, bucket size of metricses:
//
// NOTE: these value can't be changed. If we want, we need to delete the
// existing metrics and create new one (eg. SystemLogTotalFileSize2).
// We expect the log file size is between 1MB to 4GB.
// Note these values can't be changed
const int kFileSizeMegabyteMetricsMin = 1;
const int kFileSizeMegabyteMetricsMax = 4 * 1024;
// 24 = log2(kFileSizeMegabyteMetricsMax) * 2
const int kFileSizeMegabyteMetricsNumberOfBuckets = 24;
///////////////////////////////////////////////////////////////////////////////
// Log path constants:
// Patterns to match with the specific logs:
const char kChromeLogFileNamePattern[] = "chrome_\?\?\?\?\?\?\?\?-\?\?\?\?\?\?";
const char kChromeUiLogFileNamePattern[] = "ui.\?\?\?\?\?\?\?\?-\?\?\?\?\?\?";
// Log files:
const base::FilePath kSystemLogDirectoryPath("/var/log/");
const base::FilePath kSystemChromeLogDirectoryPath("/var/log/chrome/");
const base::FilePath kSystemChromeUiLogDirectoryPath("/var/log/ui/");
const base::FilePath kSystemMessagesLogPath("/var/log/messages");
const base::FilePath kSystemNetLogPath("/var/log/net.log");
const base::FilePath kSystemAuditLogPath("/var/log/audit/audit.log");
const base::FilePath kSystemArcLogPath("/var/log/arc.log");
const base::FilePath kUserLogDirectoryPath("/home/chronos/user/log/");
const base::FilePath kUserChromeLogDirectoryPath("/home/chronos/user/log/");
///////////////////////////////////////////////////////////////////////////////
// Utility methods
int ByteToMB(int64_t bytes) {
return bytes / 1024 / 1024;
}
void CalculateSysLogFileSizePerDayWithinDay(const base::FilePath& path,
int64_t* byte_count_out) {
base::Time count_after = base::Time::Now() - base::Days(1);
croslog::CalculateLogMetrics(path, count_after,
std::make_unique<croslog::LogParserSyslog>(),
byte_count_out, nullptr, nullptr);
}
void CalculateAuditLogFileSizePerDayWithinDay(const base::FilePath& path,
int64_t* byte_count_out) {
base::Time count_after = base::Time::Now() - base::Days(1);
croslog::CalculateLogMetrics(path, count_after,
std::make_unique<croslog::LogParserAudit>(),
byte_count_out, nullptr, nullptr);
}
void CalculateSystemChromeLogsByteCountWithinDay(int64_t* byte_count_out) {
base::Time count_after = base::Time::Now() - base::Days(1);
croslog::CalculateChromeLogMetrics(kSystemChromeLogDirectoryPath,
kChromeLogFileNamePattern, count_after,
byte_count_out, nullptr, nullptr);
croslog::CalculateChromeLogMetrics(kSystemChromeUiLogDirectoryPath,
kChromeUiLogFileNamePattern, count_after,
byte_count_out, nullptr, nullptr);
}
} // anonymous namespace
namespace metrics {
///////////////////////////////////////////////////////////////////////////////
// Metrics names:
const char kSystemNetLogFileSizePerDay[] = "Logging.SystemNetLogFileSizePerDay";
} // namespace metrics
class MetricsCollector {
public:
MetricsCollector() {}
void Run() {
// [Entire system log directory] Total file size.
{
int64_t system_log_total_size =
ComputeDirectorySize(kSystemLogDirectoryPath);
LOG(INFO) << "Total system log size: " << system_log_total_size
<< " bytes";
}
// [Major system log files] Number of entries per day and the maximum
// throughput per minute.
{
int64_t max_throughput;
int64_t entry_count;
croslog::Multiplexer multiplexer;
for (const auto& log_path_str : croslog::kLogSources) {
base::FilePath path(log_path_str.data());
if (!base::PathExists(path))
continue;
multiplexer.AddSource(
path, std::make_unique<croslog::LogParserSyslog>(), false);
}
for (const auto& log_path_str : croslog::kAuditLogSources) {
base::FilePath path(log_path_str.data());
if (!base::PathExists(path))
continue;
multiplexer.AddSource(path, std::make_unique<croslog::LogParserAudit>(),
false);
}
base::Time count_after = base::Time::Now() - base::Days(1);
croslog::CalculateMultipleLogMetrics(&multiplexer, count_after,
&entry_count, &max_throughput);
LOG(INFO) << "Total system log: " << entry_count << " entries per day.";
LOG(INFO) << "Maximum throughput of system logs: " << max_throughput
<< " entries per minute.";
}
// [System "message" log] Byte count of logs per day.
{
int64_t byte_count_message;
CalculateSysLogFileSizePerDayWithinDay(kSystemMessagesLogPath,
&byte_count_message);
if (byte_count_message != -1) {
LOG(INFO) << "Total message (system) log: " << byte_count_message
<< " bytes per day.";
}
}
// [System "net" log] Byte count of logs per day.
{
int64_t byte_count_net;
CalculateSysLogFileSizePerDayWithinDay(kSystemNetLogPath,
&byte_count_net);
if (byte_count_net != -1) {
SendLogFileSizeToUMA(metrics::kSystemNetLogFileSizePerDay,
byte_count_net);
LOG(INFO) << "Total net (system) log: " << byte_count_net
<< " bytes per day.";
}
}
// [System "audit" log] Byte count of logs per day.
{
int64_t byte_count_audit;
CalculateAuditLogFileSizePerDayWithinDay(kSystemAuditLogPath,
&byte_count_audit);
if (byte_count_audit != -1) {
LOG(INFO) << "Total audit (system) log: " << byte_count_audit
<< " bytes per day.";
}
}
// [System "ARC" log] Byte count of logs per day.
{
int64_t byte_count_arc;
CalculateSysLogFileSizePerDayWithinDay(kSystemArcLogPath,
&byte_count_arc);
if (byte_count_arc != -1) {
LOG(INFO) << "Total arc (system) log: " << byte_count_arc
<< " bytes per day.";
}
}
// [System chrome logs] Byte count of logs per day.
{
int64_t byte_count_chrome;
CalculateSystemChromeLogsByteCountWithinDay(&byte_count_chrome);
LOG(INFO) << "Total chrome (system) log: " << byte_count_chrome
<< " bytes per day.";
}
// [Entire user log directory] Total file size.
{
int64_t user_log_total_size = ComputeDirectorySize(kUserLogDirectoryPath);
LOG(INFO) << "Total user log size: " << user_log_total_size << " bytes";
}
// [User chrome logs] Byte count of logs per day, and the maximum throughput
// per minute.
{
int64_t max_throughput;
int64_t entry_count;
int64_t byte_count_chrome;
base::Time count_after = base::Time::Now() - base::Days(1);
croslog::CalculateChromeLogMetrics(
kUserChromeLogDirectoryPath, kChromeLogFileNamePattern, count_after,
&byte_count_chrome, &entry_count, &max_throughput);
if (byte_count_chrome > 0) {
LOG(INFO) << "Maximum throughput of user logs: " << max_throughput
<< " entries per minute.";
LOG(INFO) << "Total user log: " << entry_count << " entries per day.";
LOG(INFO) << "Total chrome (user) log: " << byte_count_chrome
<< " bytes per day.";
}
}
}
private:
void SendLogFileSizeToUMA(const std::string& name, int64_t value_in_bytes) {
metrics_library_.SendToUMA(
name, ByteToMB(value_in_bytes), kFileSizeMegabyteMetricsMin,
kFileSizeMegabyteMetricsMax, kFileSizeMegabyteMetricsNumberOfBuckets);
}
MetricsLibrary metrics_library_;
};
int main(int argc, char* argv[]) {
// Configure the log destination.
brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderrIfTty);
std::unique_ptr<MetricsCollector> collector =
std::make_unique<MetricsCollector>();
collector->Run();
}