Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(396)

Side by Side Diff: chrome/browser/chromeos/system_logs/debug_log_writer.cc

Issue 329853010: Additional methods for chrome.logPrivate API (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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/browser/chromeos/system_logs/debug_log_writer.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/command_line.h"
11 #include "base/file_util.h"
12 #include "base/files/file.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/process/kill.h"
15 #include "base/process/launch.h"
16 #include "chrome/common/logging_chrome.h"
17 #include "chromeos/dbus/dbus_thread_manager.h"
18 #include "chromeos/dbus/debug_daemon_client.h"
19 #include "content/public/browser/browser_thread.h"
20
21 namespace chromeos {
22
23 namespace {
24
25 // Callback for returning status of executed external command.
26 typedef base::Callback<void(bool succeeded)> CommandCompletionCallback;
27
28 const char kGzipCommand[] = "/bin/gzip";
29 const char kTarCommand[] = "/bin/tar";
30
31 // Called upon completion of |WriteDebugLogToFile|. Closes file
32 // descriptor, deletes log file in the case of failure and calls
33 // |callback|.
34 void WriteDebugLogToFileCompleted(
35 const DebugLogWriter::StoreLogsCallback& callback,
36 const base::FilePath& file_path,
37 bool succeeded) {
38 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
39 if (!succeeded) {
40 bool posted = content::BrowserThread::PostBlockingPoolTaskAndReply(
41 FROM_HERE,
42 base::Bind(base::IgnoreResult(&base::DeleteFile), file_path, false),
43 base::Bind(callback, file_path, false));
44 DCHECK(posted);
45 return;
46 }
47 callback.Run(file_path, true);
48 }
49
50 // Stores into |file_path| debug logs in the .tgz format. Calls
51 // |callback| upon completion.
52 void WriteDebugLogToFile(
53 base::File* file,
54 const base::FilePath& file_path,
55 bool should_compress,
56 const DebugLogWriter::StoreLogsCallback& callback) {
57 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
58 if (!file->IsValid()) {
59 LOG(ERROR) <<
60 "Can't create debug log file: " << file_path.AsUTF8Unsafe() << ", " <<
61 "error: " << file->error_details();
62 return;
63 }
64 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->DumpDebugLogs(
65 should_compress,
66 file->Pass(),
67 base::Bind(&WriteDebugLogToFileCompleted, callback, file_path));
68 }
69
70 // Runs command with its parameters as defined in |argv|.
71 // Upon completion, it will report command run outcome via |callback| on the
72 // same thread from where it was initially called from.
73 void RunCommand(const std::vector<std::string>& argv,
74 const CommandCompletionCallback& callback) {
75 base::ProcessHandle handle = base::kNullProcessHandle;
76 if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) {
77 LOG(ERROR) << "Failed to execute command " << argv[0];
78 callback.Run(false);
79 return;
80 }
81
82 int exit_code = 0;
83 if (!base::WaitForExitCode(handle, &exit_code)) {
84 LOG(ERROR) << "Can't get exit code for pid " << handle;
85 callback.Run(false);
86 return;
87 }
88 callback.Run(exit_code == 0);
89 }
90
91 // Callback for handling the outcome of CompressArchive(). It reports
92 // the final outcome of log retreival process at via |callback|.
93 void OnCompressArchiveCompleted(
94 const base::FilePath& tar_file_path,
95 const base::FilePath& compressed_output_path,
96 const DebugLogWriter::StoreLogsCallback& callback,
97 bool compression_command_success) {
98 if (!compression_command_success) {
99 LOG(ERROR) << "Failed compressing " << compressed_output_path.value();
100 content::BrowserThread::PostTask(
101 content::BrowserThread::UI,
102 FROM_HERE,
103 base::Bind(callback, base::FilePath(), false));
104 base::DeleteFile(tar_file_path, true);
105 base::DeleteFile(compressed_output_path, true);
106 return;
107 }
108
109 content::BrowserThread::PostTask(
110 content::BrowserThread::UI,
111 FROM_HERE,
112 base::Bind(callback, compressed_output_path, true));
113 }
114
115 // Gzips |tar_file_path| and stores results in |compressed_output_path|.
116 void CompressArchive(const base::FilePath& tar_file_path,
117 const base::FilePath& compressed_output_path,
118 const DebugLogWriter::StoreLogsCallback& callback,
119 bool add_user_logs_command_success) {
120 if (!add_user_logs_command_success) {
121 LOG(ERROR) << "Failed adding user logs to " << tar_file_path.value();
122 content::BrowserThread::PostTask(
123 content::BrowserThread::UI,
124 FROM_HERE,
125 base::Bind(callback, base::FilePath(), false));
126 base::DeleteFile(tar_file_path, true);
127 return;
128 }
129
130 std::vector<std::string> argv;
131 argv.push_back(kGzipCommand);
132 argv.push_back(tar_file_path.value());
133 RunCommand(argv,
134 base::Bind(&OnCompressArchiveCompleted,
135 tar_file_path,
136 compressed_output_path,
137 callback));
138 }
139
140 // Adds user sessions specific logs from |user_log_dir| into tar archive file
141 // at |tar_file_path|. Upon completion, it will call CompressArchive() to
142 // produce |compressed_output_path|.
143 void AddUserLogsToArchive(const base::FilePath& user_log_dir,
144 const base::FilePath& tar_file_path,
145 const base::FilePath& compressed_output_path,
146 const DebugLogWriter::StoreLogsCallback& callback) {
147 std::vector<std::string> argv;
148 argv.push_back(kTarCommand);
149 argv.push_back("-rvf");
150 argv.push_back(tar_file_path.value());
151 argv.push_back(user_log_dir.value());
152 RunCommand(argv,
153 base::Bind(&CompressArchive,
154 tar_file_path,
155 compressed_output_path,
156 callback));
157 }
158
159 // Appends user logs after system logs are archived into |tar_file_path|.
160 void OnSystemLogsAdded(
161 const DebugLogWriter::StoreLogsCallback& callback,
162 const base::FilePath& tar_file_path,
163 bool succeeded) {
164 if (!succeeded) {
165 callback.Run(base::FilePath(), false);
166 return;
167 }
168
169 base::FilePath compressed_output_path =
170 tar_file_path.AddExtension(FILE_PATH_LITERAL(".gz"));
171 base::FilePath user_log_dir =
172 logging::GetSessionLogDir(*CommandLine::ForCurrentProcess());
173
174 content::BrowserThread::PostBlockingPoolTask(
175 FROM_HERE,
176 base::Bind(&AddUserLogsToArchive,
177 user_log_dir,
178 tar_file_path,
179 compressed_output_path,
180 callback));
181 }
182
183 // Starts logs retrieval process. The output will be stored in file with name
184 // derived from |file_name_template|.
185 void StartLogRetrieval(const base::FilePath& file_name_template,
186 bool should_compress,
187 const DebugLogWriter::StoreLogsCallback& callback) {
188 base::FilePath file_path =
189 logging::GenerateTimestampedName(file_name_template, base::Time::Now());
190
191 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE;
192 base::File* file = new base::File;
193 content::BrowserThread::PostBlockingPoolTaskAndReply(
194 FROM_HERE,
195 base::Bind(&base::File::Initialize,
196 base::Unretained(file), file_path, flags),
197 base::Bind(&WriteDebugLogToFile,
198 base::Owned(file),
199 file_path,
200 should_compress,
201 callback));
202 }
203
204 } // namespace
205
206 // static.
207 void DebugLogWriter::StoreLogs(
208 const base::FilePath& fileshelf,
209 bool should_compress,
210 const StoreLogsCallback& callback) {
211 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
212 DCHECK(!callback.is_null());
213
214 base::FilePath file_path = fileshelf.Append(
215 should_compress ? FILE_PATH_LITERAL("debug-logs.tgz") :
216 FILE_PATH_LITERAL("debug-logs.tar"));
217
218 StartLogRetrieval(file_path, should_compress, callback);
219 }
220
221 // static.
222 void DebugLogWriter::StoreCombinedLogs(
223 const base::FilePath& fileshelf,
224 const StoreLogsCallback& callback) {
225
226 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
227 DCHECK(!callback.is_null());
228
229 base::FilePath file_path =
230 fileshelf.Append(FILE_PATH_LITERAL("combined-logs.tar"));
231
232 // Get system logs from /var/log first, then add user-specific stuff.
233 StartLogRetrieval(file_path,
234 false,
235 base::Bind(&OnSystemLogsAdded, callback));
236 }
237
238 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698