syslogs_provider.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/system/syslogs_provider.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shell.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/task_runner.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/feedback/feedback_util.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/memory_details.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/network/network_event_log.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "dbus/dbus_statistics.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace system { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kFeedbackMaxLength = 4 * 1024; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kFeedbackMaxLineCount = 40; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSysLogsScript[] = 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "/usr/share/userfeedback/scripts/sysinfo_script_runner"; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kBzip2Command[] = 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "/bin/bzip2"; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMultilineQuote[] = "\"\"\""; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNewLineChars[] = "\r\n"; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kInvalidLogEntry[] = "<invalid characters in log entry>"; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kEmptyLogEntry[] = "<no value>"; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kContextFeedback[] = "feedback"; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kContextSysInfo[] = "sysinfo"; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kContextNetwork[] = "network"; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads a key from the input string erasing the read values + delimiters read 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from the initial string 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReadKey(std::string* data) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t equal_sign = data->find("="); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (equal_sign == std::string::npos) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(""); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key = data->substr(0, equal_sign); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->erase(0, equal_sign); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data->size() > 0) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // erase the equal to sign also 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->erase(0,1); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return key; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads a value from the input string; erasing the read values from 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the initial string; detects if the value is multiline and reads 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accordingly 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReadValue(std::string* data) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Trim the leading spaces and tabs. In order to use a multi-line 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // value, you have to place the multi-line quote on the same line as 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the equal sign. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Why not use TrimWhitespace? Consider the following input: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // KEY1= 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // KEY2=VALUE 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we use TrimWhitespace, we will incorrectly trim the new line 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and assume that KEY1's value is "KEY2=VALUE" rather than empty. 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TrimString(*data, " \t", data); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If multiline value 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (StartsWithASCII(*data, std::string(kMultilineQuote), false)) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->erase(0, strlen(kMultilineQuote)); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t next_multi = data->find(kMultilineQuote); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_multi == std::string::npos) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Error condition, clear data to stop further processing 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->erase(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value = data->substr(0, next_multi); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->erase(0, next_multi + 3); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // single line value 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t endl_pos = data->find_first_of(kNewLineChars); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if we don't find a new line, we just return the rest of the data 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value = data->substr(0, endl_pos); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->erase(0, endl_pos); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return value; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a map of system log keys and values. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parameters: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// temp_filename: This is an out parameter that holds the name of a file in 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reads a value from the input string; erasing the read values from 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the initial string; detects if the value is multiline and reads 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accordingly 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// /tmp that contains the system logs in a KEY=VALUE format. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If this parameter is NULL, system logs are not retained on 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the filesystem after this call completes. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// context: This is an in parameter specifying what context should be 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// passed to the syslog collection script; currently valid 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// values are "sysinfo" or "feedback"; in case of an invalid 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// value, the script will currently default to "sysinfo" 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogDictionaryType* GetSystemLogs(base::FilePath* zip_file_name, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& context) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the temp file, logs will go here 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath temp_filename; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateTemporaryFile(&temp_filename)) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string cmd = std::string(kSysLogsScript) + " " + context + " >> " + 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) temp_filename.value(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore the return value - if the script execution didn't work 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stderr won't go into the output file anyway. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::system(cmd.c_str()) == -1) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Command " << cmd << " failed to run"; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compress the logs file if requested. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (zip_file_name) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd = std::string(kBzip2Command) + " -c " + temp_filename.value() + " > " + 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_file_name->value(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::system(cmd.c_str()) == -1) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Command " << cmd << " failed to run"; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read logs from the temp file 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string data; 14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool read_success = base::ReadFileToString(temp_filename, &data); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if we were using an internal temp file, the user does not need the 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // logs to stay past the ReadFile call - delete the file 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(temp_filename, false); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_success) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse the return data into a dictionary 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogDictionaryType* logs = new LogDictionaryType(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (data.length() > 0) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key = ReadKey(&data); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimWhitespaceASCII(key, TRIM_ALL, &key); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!key.empty()) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value = ReadValue(&data); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsStringUTF8(value)) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimWhitespaceASCII(value, TRIM_ALL, &value); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value.empty()) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*logs)[key] = kEmptyLogEntry; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*logs)[key] = value; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Invalid characters in system log entry: " << key; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*logs)[key] = kInvalidLogEntry; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no more keys, we're done 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return logs; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyslogsProviderImpl : public SyslogsProvider { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SyslogsProvider implementation: 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual CancelableTaskTracker::TaskId RequestSyslogs( 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool compress_logs, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyslogsContext context, 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ReadCompleteCallback& callback, 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelableTaskTracker* tracker) OVERRIDE; 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static SyslogsProviderImpl* GetInstance(); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) friend struct DefaultSingletonTraits<SyslogsProviderImpl>; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reads system logs, compresses content if requested. 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Called from blocking pool thread. 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReadSyslogs( 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CancelableTaskTracker::IsCanceledCallback& is_canceled, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool compress_logs, 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyslogsContext context, 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ReadCompleteCallback& callback); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Loads compressed logs and writes into |zip_content|. 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void LoadCompressedLogs(const base::FilePath& zip_file, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* zip_content); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyslogsProviderImpl(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Gets syslogs context string from the enum value. 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* GetSyslogsContextString(SyslogsContext context); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If not canceled, run callback on originating thread (the thread on which 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // ReadSyslogs was run). 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static void RunCallbackIfNotCanceled( 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CancelableTaskTracker::IsCanceledCallback& is_canceled, 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TaskRunner* origin_runner, 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ReadCompleteCallback& callback, 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LogDictionaryType* logs, 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* zip_content); 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SyslogsProviderImpl); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyslogsProviderImpl::SyslogsProviderImpl() { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CancelableTaskTracker::TaskId SyslogsProviderImpl::RequestSyslogs( 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool compress_logs, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyslogsContext context, 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ReadCompleteCallback& callback, 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelableTaskTracker* tracker) { 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelableTaskTracker::IsCanceledCallback is_canceled; 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CancelableTaskTracker::TaskId id = tracker->NewTrackedTaskId(&is_canceled); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReadCompleteCallback callback_runner = 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&SyslogsProviderImpl::RunCallbackIfNotCanceled, 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_canceled, base::MessageLoopProxy::current(), callback); 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Schedule a task which will run the callback later when complete. 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostBlockingPoolTask( 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SyslogsProviderImpl::ReadSyslogs, base::Unretained(this), 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_canceled, compress_logs, context, callback_runner)); 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return id; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Derived class from memoryDetails converts the results into a single string 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and adds a "mem_usage" entry to the logs, then forwards the result. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Format of entry is (one process per line, reverse-sorted by size): 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tab [Title1|Title2]: 50 MB 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Browser: 30 MB 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tab [Title]: 20 MB 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Extension [Title]: 10 MB 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ... 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SyslogsMemoryHandler : public MemoryDetails { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef SyslogsProvider::ReadCompleteCallback ReadCompleteCallback; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |logs| is modified (see comment above) and passed to |request|. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |zip_content| is passed to |request|. 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyslogsMemoryHandler(const ReadCompleteCallback& callback, 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LogDictionaryType* logs, 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* zip_content); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnDetailsAvailable() OVERRIDE; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~SyslogsMemoryHandler(); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReadCompleteCallback callback_; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogDictionaryType* logs_; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* zip_content_; 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SyslogsMemoryHandler); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyslogsMemoryHandler::SyslogsMemoryHandler( 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ReadCompleteCallback& callback, 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LogDictionaryType* logs, 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* zip_content) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : callback_(callback), 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) logs_(logs), 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) zip_content_(zip_content) { 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!callback_.is_null()); 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyslogsMemoryHandler::OnDetailsAvailable() { 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*logs_)["mem_usage"] = ToLogString(); 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback_.Run(logs_, zip_content_); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SyslogsMemoryHandler::~SyslogsMemoryHandler() {} 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called from blocking pool thread. 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyslogsProviderImpl::ReadSyslogs( 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CancelableTaskTracker::IsCanceledCallback& is_canceled, 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool compress_logs, 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SyslogsContext context, 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ReadCompleteCallback& callback) { 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_canceled.Run()) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create temp file. 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath zip_file; 308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (compress_logs && !base::CreateTemporaryFile(&zip_file)) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Cannot create temp file"; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compress_logs = false; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LogDictionaryType* logs = NULL; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logs = GetSystemLogs( 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compress_logs ? &zip_file : NULL, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSyslogsContextString(context)); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* zip_content = NULL; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (compress_logs) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Load compressed logs. 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_content = new std::string(); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadCompressedLogs(zip_file, zip_content); 3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(zip_file, false); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Include dbus statistics summary 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*logs)["dbus"] = dbus::statistics::GetAsString( 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dbus::statistics::SHOW_INTERFACE, 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dbus::statistics::FORMAT_ALL); 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Include recent network log events 33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) (*logs)["network_event_log"] = network_event_log::GetAsString( 33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) network_event_log::OLDEST_FIRST, 33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "time,file,desc", 33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) network_event_log::kDefaultLogLevel, 33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) system::kFeedbackMaxLineCount); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SyslogsMemoryHandler will clean itself up. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SyslogsMemoryHandler::OnDetailsAvailable() will modify |logs| and call 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // request->ForwardResult(logs, zip_content). 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<SyslogsMemoryHandler> 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handler(new SyslogsMemoryHandler(callback, logs, zip_content)); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jamescook): Maybe we don't need to update histograms here? 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handler->StartFetch(MemoryDetails::UPDATE_USER_METRICS); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyslogsProviderImpl::LoadCompressedLogs(const base::FilePath& zip_file, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* zip_content) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(zip_content); 35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!base::ReadFileToString(zip_file, zip_content)) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Cannot read compressed logs file from " << 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) zip_file.value().c_str(); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SyslogsProviderImpl::GetSyslogsContextString( 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyslogsContext context) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (context) { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case(SYSLOGS_FEEDBACK): 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kContextFeedback; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case(SYSLOGS_SYSINFO): 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kContextSysInfo; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case(SYSLOGS_NETWORK): 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kContextNetwork; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case(SYSLOGS_DEFAULT): 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kContextSysInfo; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ""; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SyslogsProviderImpl::RunCallbackIfNotCanceled( 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CancelableTaskTracker::IsCanceledCallback& is_canceled, 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TaskRunner* origin_runner, 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ReadCompleteCallback& callback, 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LogDictionaryType* logs, 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* zip_content) { 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!is_canceled.is_null() && !callback.is_null()); 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_canceled.Run()) { 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete logs; 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete zip_content; 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(achuith@chromium.org): Maybe always run callback asynchronously? 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (origin_runner->RunsTasksOnCurrentThread()) { 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(logs, zip_content); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) origin_runner->PostTask(FROM_HERE, base::Bind(callback, logs, zip_content)); 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyslogsProviderImpl* SyslogsProviderImpl::GetInstance() { 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<SyslogsProviderImpl, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DefaultSingletonTraits<SyslogsProviderImpl> >::get(); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyslogsProvider* SyslogsProvider::GetInstance() { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SyslogsProviderImpl::GetInstance(); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace system 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chromeos 407