| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/system/diagnostics/routine_log.h" |
| |
| #include <sstream> |
| #include <string> |
| |
| #include "base/i18n/time_formatting.h" |
| #include "base/logging.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/task/sequenced_task_runner.h" |
| #include "base/time/time.h" |
| |
| namespace ash { |
| namespace diagnostics { |
| namespace { |
| |
| const char kCancelledDescription[] = "Inflight Routine Cancelled"; |
| const char kNewline[] = "\n"; |
| const char kSeparator[] = " - "; |
| const char kStartedDescription[] = "Started"; |
| |
| std::string GetCurrentDateTimeAsString() { |
| return base::UTF16ToUTF8(base::TimeFormatShortDateAndTime(base::Time::Now())); |
| } |
| |
| std::string GetRoutineLogCategoryString(RoutineLog::RoutineCategory category) { |
| switch (category) { |
| case RoutineLog::RoutineCategory::kNetwork: |
| return "network"; |
| case RoutineLog::RoutineCategory::kSystem: |
| return "system"; |
| } |
| } |
| |
| std::string getRoutineResultString(mojom::StandardRoutineResult result) { |
| switch (result) { |
| case mojom::StandardRoutineResult::kTestPassed: |
| return "Passed"; |
| case mojom::StandardRoutineResult::kTestFailed: |
| return "Failed"; |
| case mojom::StandardRoutineResult::kExecutionError: |
| return "Execution error"; |
| case mojom::StandardRoutineResult::kUnableToRun: |
| return "Unable to run"; |
| } |
| } |
| |
| std::string getRoutineTypeString(mojom::RoutineType type) { |
| std::stringstream s; |
| s << type; |
| const std::string routineName = s.str(); |
| |
| // Remove leading "k" ex: "kCpuStress" -> "CpuStress". |
| DCHECK_GE(routineName.size(), 1U); |
| DCHECK_EQ(routineName[0], 'k'); |
| return routineName.substr(1, routineName.size() - 1); |
| } |
| |
| // Get the category for the routine `type`. |
| RoutineLog::RoutineCategory GetRoutineCategory(mojom::RoutineType type) { |
| switch (type) { |
| case mojom::RoutineType::kBatteryCharge: |
| case mojom::RoutineType::kBatteryDischarge: |
| case mojom::RoutineType::kCpuCache: |
| case mojom::RoutineType::kCpuStress: |
| case mojom::RoutineType::kCpuFloatingPoint: |
| case mojom::RoutineType::kCpuPrime: |
| case mojom::RoutineType::kMemory: |
| return RoutineLog::RoutineCategory::kSystem; |
| case mojom::RoutineType::kLanConnectivity: |
| case mojom::RoutineType::kSignalStrength: |
| case mojom::RoutineType::kGatewayCanBePinged: |
| case mojom::RoutineType::kHasSecureWiFiConnection: |
| case mojom::RoutineType::kDnsResolverPresent: |
| case mojom::RoutineType::kDnsLatency: |
| case mojom::RoutineType::kDnsResolution: |
| case mojom::RoutineType::kCaptivePortal: |
| case mojom::RoutineType::kHttpFirewall: |
| case mojom::RoutineType::kHttpsFirewall: |
| case mojom::RoutineType::kHttpsLatency: |
| case mojom::RoutineType::kArcHttp: |
| case mojom::RoutineType::kArcPing: |
| case mojom::RoutineType::kArcDnsResolution: |
| return RoutineLog::RoutineCategory::kNetwork; |
| }; |
| } |
| |
| } // namespace |
| |
| RoutineLog::RoutineLog(const base::FilePath& log_base_path) |
| : log_base_path_(log_base_path) {} |
| |
| RoutineLog::~RoutineLog() = default; |
| |
| void RoutineLog::LogRoutineStarted(mojom::RoutineType type) { |
| std::stringstream log_line; |
| log_line << GetCurrentDateTimeAsString() << kSeparator |
| << getRoutineTypeString(type) << kSeparator << kStartedDescription |
| << kNewline; |
| Append(type, log_line.str()); |
| } |
| |
| void RoutineLog::LogRoutineCompleted(mojom::RoutineType type, |
| mojom::StandardRoutineResult result) { |
| std::stringstream log_line; |
| log_line << GetCurrentDateTimeAsString() << kSeparator |
| << getRoutineTypeString(type) << kSeparator |
| << getRoutineResultString(result) << kNewline; |
| Append(type, log_line.str()); |
| } |
| |
| void RoutineLog::LogRoutineCancelled(mojom::RoutineType type) { |
| std::stringstream log_line; |
| log_line << GetCurrentDateTimeAsString() << kSeparator |
| << kCancelledDescription << kNewline; |
| Append(type, log_line.str()); |
| } |
| |
| std::string RoutineLog::GetContentsForCategory( |
| const RoutineCategory category) const { |
| const auto iter = logs_.find(category); |
| if (iter == logs_.end()) { |
| return ""; |
| } |
| |
| return iter->second->GetContents(); |
| } |
| |
| void RoutineLog::Append(mojom::RoutineType type, const std::string& text) { |
| RoutineCategory category = GetRoutineCategory(type); |
| |
| // Insert a new log if it doesn't exist then append to it. |
| base::FilePath log_path = GetCategoryLogFilePath(category); |
| auto iter = logs_.find(category); |
| if (iter == logs_.end()) { |
| iter = logs_.emplace(category, std::make_unique<AsyncLog>(log_path)).first; |
| } |
| |
| iter->second->Append(text); |
| } |
| |
| base::FilePath RoutineLog::GetCategoryLogFilePath( |
| const RoutineCategory category) { |
| std::string name = |
| "diagnostics_routines_" + GetRoutineLogCategoryString(category) + ".log"; |
| return log_base_path_.Append(name); |
| } |
| |
| } // namespace diagnostics |
| } // namespace ash |