1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/chrome_cleaner/logging/scoped_logging.h"
6
7 #include <memory>
8
9 #include "base/command_line.h"
10 #include "base/file_version_info.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/logging_win.h"
14 #include "base/strings/string_util.h"
15 #include "base/win/current_module.h"
16 #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h"
17 #include "chrome/chrome_cleaner/constants/version.h"
18 #include "chrome/chrome_cleaner/logging/logging_service_api.h"
19 #include "chrome/chrome_cleaner/os/disk_util.h"
20 #include "chrome/chrome_cleaner/os/pre_fetched_paths.h"
21 #include "chrome/chrome_cleaner/settings/settings.h"
22
23 namespace chrome_cleaner {
24
25 namespace {
26
27 // {985388DD-5F6A-40A9-A4D2-86D8547EFB52}
28 const GUID kChromeCleanerTraceProviderName = {
29 0x985388DD,
30 0x5F6A,
31 0x40A9,
32 {0xA4, 0xD2, 0x86, 0xD8, 0x54, 0x7E, 0xFB, 0x52}};
33
34 // The log file extension.
35 const wchar_t kLogFileExtension[] = L"log";
36
GetLoggingDirectory()37 base::FilePath GetLoggingDirectory() {
38 base::FilePath logging_directory =
39 base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
40 kTestLoggingPathSwitch);
41 if (logging_directory.empty()) {
42 if (!GetAppDataProductDirectory(&logging_directory))
43 return base::FilePath();
44 }
45 return logging_directory;
46 }
47
48 } // namespace
49
ScopedLogging(base::FilePath::StringPieceType suffix)50 ScopedLogging::ScopedLogging(base::FilePath::StringPieceType suffix) {
51 // Log to an ETW facility for convenience.
52 // This swallows all log lines it gets, so we need to initialize it before
53 // LoggingServiceAPI so LoggingServiceAPI can see the logs first, which it
54 // then passes on to LogEventProvider.
55 logging::LogEventProvider::Initialize(kChromeCleanerTraceProviderName);
56
57 // Initialize the logging global state.
58 LoggingServiceAPI* logging_service = LoggingServiceAPI::GetInstance();
59 logging_service->Initialize(nullptr);
60
61 const base::FilePath log_file_path = GetLogFilePath(suffix);
62
63 // Truncate log files to 40kB. This should be enough to cover logs of the
64 // previous run (99th percentile of uploaded raw log line size is 36kB).
65 TruncateLogFileToTail(log_file_path, 40 * 1000);
66
67 logging::LoggingSettings logging_settings;
68 logging_settings.logging_dest = logging::LOG_TO_FILE;
69 logging_settings.log_file_path = log_file_path.value().c_str();
70
71 bool success = logging::InitLogging(logging_settings);
72 DCHECK(success);
73 LOG(INFO) << "Starting logs for version: " << CHROME_CLEANER_VERSION_STRING;
74
75 logging_service->EnableUploads(
76 chrome_cleaner::Settings::GetInstance()->logs_upload_allowed(), nullptr);
77 }
78
~ScopedLogging()79 ScopedLogging::~ScopedLogging() {
80 // Terminate the service to avoid work being done in the destructor called by
81 // the AtExitManager.
82 LoggingServiceAPI::GetInstance()->Terminate();
83
84 // Kill our ETW provider.
85 logging::LogEventProvider::Uninitialize();
86 }
87
88 // static
GetLogFilePath(base::FilePath::StringPieceType suffix)89 base::FilePath ScopedLogging::GetLogFilePath(
90 base::FilePath::StringPieceType suffix) {
91 // Initialize the logging settings to set a specific log file name.
92 std::unique_ptr<FileVersionInfo> version(
93 FileVersionInfo::CreateFileVersionInfoForModule(CURRENT_MODULE()));
94
95 // Test executables don't have version resources.
96 base::FilePath original_filename;
97 if (version.get()) {
98 original_filename =
99 base::FilePath(base::AsWStringPiece(version->original_filename()));
100 } else {
101 original_filename =
102 PreFetchedPaths::GetInstance()->GetExecutablePath().BaseName();
103 }
104
105 if (!suffix.empty())
106 original_filename = original_filename.InsertBeforeExtension(suffix);
107
108 base::FilePath log_file_path =
109 original_filename.ReplaceExtension(kLogFileExtension);
110 base::FilePath logging_directory = GetLoggingDirectory();
111 if (!logging_directory.empty())
112 log_file_path = logging_directory.Append(log_file_path);
113 return log_file_path;
114 }
115
116 } // namespace chrome_cleaner
117