Commit 6eeb415c authored by Bailey Berro's avatar Bailey Berro Committed by Chromium LUCI CQ

Introduce Diagnostics RoutineLog

This change introduces a RoutineLog class to manage the logging of
routine status. Calls to `LogRoutineStarted` and `LogRoutineCompleted`
append lines to a log at a provided path.


Bug: 1128204
Change-Id: I379d9310371b703220788c674b21e641c184bbe7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2618841
Commit-Queue: Bailey Berro <baileyberro@chromium.org>
Reviewed-by: default avatarZentaro Kavanagh <zentaro@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842789}
parent 2a82e5eb
...@@ -16,6 +16,8 @@ static_library("backend") { ...@@ -16,6 +16,8 @@ static_library("backend") {
"histogram_util.h", "histogram_util.h",
"power_manager_client_conversions.cc", "power_manager_client_conversions.cc",
"power_manager_client_conversions.h", "power_manager_client_conversions.h",
"routine_log.cc",
"routine_log.h",
"system_data_provider.cc", "system_data_provider.cc",
"system_data_provider.h", "system_data_provider.h",
"system_routine_controller.cc", "system_routine_controller.cc",
...@@ -41,6 +43,7 @@ source_set("unit_tests") { ...@@ -41,6 +43,7 @@ source_set("unit_tests") {
sources = [ sources = [
"cpu_usage_data_unittest.cc", "cpu_usage_data_unittest.cc",
"power_manager_client_conversions_unittest.cc", "power_manager_client_conversions_unittest.cc",
"routine_log_unittest.cc",
"system_data_provider_unittest.cc", "system_data_provider_unittest.cc",
"system_routine_controller_unittest.cc", "system_routine_controller_unittest.cc",
] ]
......
// Copyright 2021 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.
#include "chromeos/components/diagnostics_ui/backend/routine_log.h"
#include <sstream>
#include <string>
#include "base/files/file_util.h"
#include "base/i18n/time_formatting.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
namespace chromeos {
namespace diagnostics {
namespace {
const char kNewline[] = "\n";
const char kSeparator[] = " - ";
const char kStartedDescription[] = "Started";
std::string GetCurrentTimeAsString() {
return base::UTF16ToUTF8(
base::TimeFormatTimeOfDayWithMilliseconds(base::Time::Now()));
}
} // namespace
RoutineLog::RoutineLog(const base::FilePath& routine_log_file_path)
: routine_log_file_path_(routine_log_file_path) {}
RoutineLog::~RoutineLog() = default;
void RoutineLog::LogRoutineStarted(mojom::RoutineType type) {
if (!base::PathExists(routine_log_file_path_)) {
base::WriteFile(routine_log_file_path_, "");
}
std::stringstream log_line;
log_line << GetCurrentTimeAsString() << kSeparator << type << kSeparator
<< kStartedDescription << kNewline;
AppendToLog(log_line.str());
}
void RoutineLog::LogRoutineCompleted(mojom::RoutineType type,
mojom::StandardRoutineResult result) {
DCHECK(base::PathExists(routine_log_file_path_));
std::stringstream log_line;
log_line << GetCurrentTimeAsString() << kSeparator << type << kSeparator
<< result << kNewline;
AppendToLog(log_line.str());
}
void RoutineLog::AppendToLog(const std::string& content) {
base::AppendToFile(routine_log_file_path_, content.data(), content.size());
}
} // namespace diagnostics
} // namespace chromeos
// Copyright 2021 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_COMPONENTS_DIAGNOSTICS_UI_BACKEND_ROUTINE_LOG_H_
#define CHROMEOS_COMPONENTS_DIAGNOSTICS_UI_BACKEND_ROUTINE_LOG_H_
#include "base/files/file_path.h"
#include "chromeos/components/diagnostics_ui/mojom/system_routine_controller.mojom.h"
namespace chromeos {
namespace diagnostics {
// RoutineLog is used to record the status and outcome of Diagnostics Routines.
// Each time `LogRoutineStarted()` or `LogRoutineCompleted()` is called, a new
// line is appended to `routine_log_file_path`. The file is created before the
// first write if it does not exist.
class RoutineLog {
public:
explicit RoutineLog(const base::FilePath& routine_log_file_path);
~RoutineLog();
RoutineLog(const RoutineLog&) = delete;
RoutineLog& operator=(const RoutineLog&) = delete;
// Adds an entry in the RoutineLog.
void LogRoutineStarted(mojom::RoutineType type);
void LogRoutineCompleted(mojom::RoutineType type,
mojom::StandardRoutineResult result);
private:
void AppendToLog(const std::string& content);
const base::FilePath routine_log_file_path_;
};
} // namespace diagnostics
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_DIAGNOSTICS_UI_BACKEND_ROUTINE_LOG_H_
// Copyright 2021 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.
#include "chromeos/components/diagnostics_ui/backend/routine_log.h"
#include <string>
#include <vector>
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/string_split.h"
#include "base/test/task_environment.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "chromeos/components/diagnostics_ui/mojom/system_routine_controller.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace diagnostics {
namespace {
const char kLogFileName[] = "diagnostic_routine_log";
const char kSeparator[] = " - ";
const char kNewline[] = "\n";
// Returns the lines of the log as a vector of strings.
std::vector<std::string> GetLogLines(const std::string& log) {
return base::SplitString(log, kNewline,
base::WhitespaceHandling::TRIM_WHITESPACE,
base::SplitResult::SPLIT_WANT_NONEMPTY);
}
// Splits a single line of the log at `kSeparator`. It is expected that each log
// line contains exactly 3 components: 1) timestamp, 2) routine name, 3) status.
std::vector<std::string> GetLogLineContents(const std::string& log_line) {
const std::vector<std::string> result = base::SplitString(
log_line, kSeparator, base::WhitespaceHandling::TRIM_WHITESPACE,
base::SplitResult::SPLIT_WANT_NONEMPTY);
DCHECK_EQ(3u, result.size());
return result;
}
} // namespace
class RoutineLogTest : public testing::Test {
public:
RoutineLogTest() {
EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
log_path_ = temp_dir_.GetPath().AppendASCII(kLogFileName);
}
~RoutineLogTest() override = default;
protected:
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
base::ScopedTempDir temp_dir_;
base::FilePath log_path_;
};
TEST_F(RoutineLogTest, Empty) {
RoutineLog log(log_path_);
EXPECT_FALSE(base::PathExists(log_path_));
}
TEST_F(RoutineLogTest, Basic) {
RoutineLog log(log_path_);
log.LogRoutineStarted(mojom::RoutineType::kCpuStress);
EXPECT_TRUE(base::PathExists(log_path_));
std::string contents;
base::ReadFileToString(log_path_, &contents);
const std::string first_line = GetLogLines(contents)[0];
const std::vector<std::string> first_line_contents =
GetLogLineContents(first_line);
ASSERT_EQ(3u, first_line_contents.size());
EXPECT_EQ("RoutineType::kCpuStress", first_line_contents[1]);
EXPECT_EQ("Started", first_line_contents[2]);
}
TEST_F(RoutineLogTest, TwoLine) {
RoutineLog log(log_path_);
log.LogRoutineStarted(mojom::RoutineType::kMemory);
log.LogRoutineCompleted(mojom::RoutineType::kMemory,
mojom::StandardRoutineResult::kTestPassed);
EXPECT_TRUE(base::PathExists(log_path_));
std::string contents;
base::ReadFileToString(log_path_, &contents);
const std::vector<std::string> log_lines = GetLogLines(contents);
const std::string first_line = log_lines[0];
const std::vector<std::string> first_line_contents =
GetLogLineContents(first_line);
ASSERT_EQ(3u, first_line_contents.size());
EXPECT_EQ("RoutineType::kMemory", first_line_contents[1]);
EXPECT_EQ("Started", first_line_contents[2]);
const std::string second_line = log_lines[1];
const std::vector<std::string> second_line_contents =
GetLogLineContents(second_line);
ASSERT_EQ(3u, second_line_contents.size());
EXPECT_EQ("RoutineType::kMemory", second_line_contents[1]);
EXPECT_EQ("StandardRoutineResult::kTestPassed", second_line_contents[2]);
}
} // namespace diagnostics
} // namespace chromeos
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment