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

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: rebase 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 scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner(
32 const std::string sequence_name) {
33 base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
34 return pool->GetSequencedTaskRunnerWithShutdownBehavior(
35 pool->GetNamedSequenceToken(sequence_name),
36 base::SequencedWorkerPool::BLOCK_SHUTDOWN);
37 }
38
39 // Called upon completion of |WriteDebugLogToFile|. Closes file
40 // descriptor, deletes log file in the case of failure and calls
41 // |callback|.
42 void WriteDebugLogToFileCompleted(
43 const base::FilePath& file_path,
44 const std::string& sequence_token_name,
45 const DebugLogWriter::StoreLogsCallback& callback,
46 bool succeeded) {
47 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
48 if (!succeeded) {
49 bool posted = GetSequencedTaskRunner(sequence_token_name)->PostTaskAndReply(
50 FROM_HERE,
51 base::Bind(base::IgnoreResult(&base::DeleteFile), file_path, false),
52 base::Bind(callback, file_path, false));
53 DCHECK(posted);
54 return;
55 }
56 if (!callback.is_null())
57 callback.Run(file_path, true);
58 }
59
60 // Stores into |file_path| debug logs in the .tgz format. Calls
61 // |callback| upon completion.
62 void WriteDebugLogToFile(base::File* file,
63 const std::string& sequence_token_name,
64 const base::FilePath& file_path,
65 bool should_compress,
66 const DebugLogWriter::StoreLogsCallback& callback) {
67 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
68 if (!file->IsValid()) {
69 LOG(ERROR) << "Can't create debug log file: " << file_path.AsUTF8Unsafe()
70 << ", "
71 << "error: " << file->error_details();
72 return;
73 }
74 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->DumpDebugLogs(
75 should_compress,
76 file->Pass(),
77 base::Bind(&WriteDebugLogToFileCompleted,
78 file_path,
79 sequence_token_name,
80 callback));
81 }
82
83 // Runs command with its parameters as defined in |argv|.
84 // Upon completion, it will report command run outcome via |callback| on the
85 // same thread from where it was initially called from.
86 void RunCommand(const std::vector<std::string>& argv,
87 const CommandCompletionCallback& callback) {
88 base::ProcessHandle handle = base::kNullProcessHandle;
89 if (!base::LaunchProcess(argv, base::LaunchOptions(), &handle)) {
90 LOG(ERROR) << "Failed to execute command " << argv[0];
91 if (!callback.is_null())
92 callback.Run(false);
93
94 return;
95 }
96
97 int exit_code = 0;
98 if (!base::WaitForExitCode(handle, &exit_code)) {
99 LOG(ERROR) << "Can't get exit code for pid " << handle;
100 if (!callback.is_null())
101 callback.Run(false);
102
103 return;
104 }
105 if (!callback.is_null())
106 callback.Run(exit_code == 0);
107 }
108
109 // Callback for handling the outcome of CompressArchive(). It reports
110 // the final outcome of log retreival process at via |callback|.
111 void OnCompressArchiveCompleted(
112 const base::FilePath& tar_file_path,
113 const base::FilePath& compressed_output_path,
114 const DebugLogWriter::StoreLogsCallback& callback,
115 bool compression_command_success) {
116 if (!compression_command_success) {
117 LOG(ERROR) << "Failed compressing " << compressed_output_path.value();
118 content::BrowserThread::PostTask(
119 content::BrowserThread::UI,
120 FROM_HERE,
121 base::Bind(callback, base::FilePath(), false));
122 base::DeleteFile(tar_file_path, true);
123 base::DeleteFile(compressed_output_path, true);
124 return;
125 }
126
127 content::BrowserThread::PostTask(
128 content::BrowserThread::UI,
129 FROM_HERE,
130 base::Bind(callback, compressed_output_path, true));
131 }
132
133 // Gzips |tar_file_path| and stores results in |compressed_output_path|.
134 void CompressArchive(const base::FilePath& tar_file_path,
135 const base::FilePath& compressed_output_path,
136 const DebugLogWriter::StoreLogsCallback& callback,
137 bool add_user_logs_command_success) {
138 if (!add_user_logs_command_success) {
139 LOG(ERROR) << "Failed adding user logs to " << tar_file_path.value();
140 content::BrowserThread::PostTask(
141 content::BrowserThread::UI,
142 FROM_HERE,
143 base::Bind(callback, base::FilePath(), false));
144 base::DeleteFile(tar_file_path, true);
145 return;
146 }
147
148 std::vector<std::string> argv;
149 argv.push_back(kGzipCommand);
150 argv.push_back(tar_file_path.value());
151 RunCommand(argv,
152 base::Bind(&OnCompressArchiveCompleted,
153 tar_file_path,
154 compressed_output_path,
155 callback));
156 }
157
158 // Adds user sessions specific logs from |user_log_dir| into tar archive file
159 // at |tar_file_path|. Upon completion, it will call CompressArchive() to
160 // produce |compressed_output_path|.
161 void AddUserLogsToArchive(const base::FilePath& user_log_dir,
162 const base::FilePath& tar_file_path,
163 const base::FilePath& compressed_output_path,
164 const DebugLogWriter::StoreLogsCallback& callback) {
165 std::vector<std::string> argv;
166 argv.push_back(kTarCommand);
167 argv.push_back("-rvf");
168 argv.push_back(tar_file_path.value());
169 argv.push_back(user_log_dir.value());
170 RunCommand(
171 argv,
172 base::Bind(
173 &CompressArchive, tar_file_path, compressed_output_path, callback));
174 }
175
176 // Appends user logs after system logs are archived into |tar_file_path|.
177 void OnSystemLogsAdded(const DebugLogWriter::StoreLogsCallback& callback,
178 const base::FilePath& tar_file_path,
179 bool succeeded) {
180 if (!succeeded) {
181 if (!callback.is_null())
182 callback.Run(base::FilePath(), false);
183
184 return;
185 }
186
187 base::FilePath compressed_output_path =
188 tar_file_path.AddExtension(FILE_PATH_LITERAL(".gz"));
189 base::FilePath user_log_dir =
190 logging::GetSessionLogDir(*CommandLine::ForCurrentProcess());
191
192 content::BrowserThread::PostBlockingPoolTask(
193 FROM_HERE,
194 base::Bind(&AddUserLogsToArchive,
195 user_log_dir,
196 tar_file_path,
197 compressed_output_path,
198 callback));
199 }
200
201 void IntializeLogFile(base::File* file,
202 const base::FilePath& file_path,
203 uint32 flags) {
204 base::FilePath dir = file_path.DirName();
205 if (!base::DirectoryExists(dir)) {
206 if (!base::CreateDirectory(dir)) {
207 LOG(ERROR) << "Can not create " << dir.value();
208 return;
209 }
210 }
211
212 file->Initialize(file_path, flags);
213 }
214
215 // Starts logs retrieval process. The output will be stored in file with name
216 // derived from |file_name_template|.
217 void StartLogRetrieval(const base::FilePath& file_name_template,
218 bool should_compress,
219 const std::string& sequence_token_name,
220 const DebugLogWriter::StoreLogsCallback& callback) {
221 base::FilePath file_path =
222 logging::GenerateTimestampedName(file_name_template, base::Time::Now());
223
224 int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE;
225 base::File* file = new base::File;
226 GetSequencedTaskRunner(sequence_token_name)->PostTaskAndReply(
227 FROM_HERE,
228 base::Bind(&IntializeLogFile, base::Unretained(file), file_path, flags),
229 base::Bind(&WriteDebugLogToFile,
230 base::Owned(file),
231 sequence_token_name,
232 file_path,
233 should_compress,
234 callback));
235 }
236
237 const char kDefaultSequenceName[] = "DebugLogWriter";
238
239 } // namespace
240
241 // static.
242 void DebugLogWriter::StoreLogs(const base::FilePath& fileshelf,
243 bool should_compress,
244 const StoreLogsCallback& callback) {
245 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
246 DCHECK(!callback.is_null());
247
248 base::FilePath file_path =
249 fileshelf.Append(should_compress ? FILE_PATH_LITERAL("debug-logs.tgz")
250 : FILE_PATH_LITERAL("debug-logs.tar"));
251
252 StartLogRetrieval(file_path, should_compress, kDefaultSequenceName, callback);
253 }
254
255 // static.
256 void DebugLogWriter::StoreCombinedLogs(const base::FilePath& fileshelf,
257 const std::string& sequence_token_name,
258 const StoreLogsCallback& callback) {
259 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
260 DCHECK(!callback.is_null());
261
262 base::FilePath file_path =
263 fileshelf.Append(FILE_PATH_LITERAL("combined-logs.tar"));
264
265 // Get system logs from /var/log first, then add user-specific stuff.
266 StartLogRetrieval(file_path,
267 false,
268 sequence_token_name,
269 base::Bind(&OnSystemLogsAdded, callback));
270 }
271
272 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/system_logs/debug_log_writer.h ('k') | chrome/browser/extensions/api/hid/hid_connection_resource.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698