OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/test/webdriver/webdriver_logging.h" | |
6 | |
7 #include <cmath> | |
8 | |
9 #include "base/file_util.h" | |
10 #include "base/files/file_path.h" | |
11 #include "base/logging.h" | |
12 #include "base/strings/string_number_conversions.h" | |
13 #include "base/strings/string_util.h" | |
14 #include "base/strings/stringprintf.h" | |
15 #include "base/time/time.h" | |
16 #include "build/build_config.h" | |
17 | |
18 using base::DictionaryValue; | |
19 using base::ListValue; | |
20 using base::Value; | |
21 | |
22 namespace webdriver { | |
23 | |
24 FileLog* FileLog::singleton_ = NULL; | |
25 | |
26 double start_time = 0; | |
27 | |
28 LogLevel LogLevelFromString(const std::string& name) { | |
29 // Default logging level is INFO. | |
30 LogLevel level = kInfoLogLevel; | |
31 const std::string upper_case_name = StringToUpperASCII(name); | |
32 if (upper_case_name == "OFF") { | |
33 level = kOffLogLevel; | |
34 } else if (upper_case_name == "SEVERE") { | |
35 level = kSevereLogLevel; | |
36 } else if (upper_case_name == "WARNING") { | |
37 level = kWarningLogLevel; | |
38 } else if (upper_case_name == "INFO" || upper_case_name == "CONFIG") { | |
39 | |
40 } else if (upper_case_name == "FINE") { | |
41 level = kFineLogLevel; | |
42 } else if (upper_case_name == "FINER") { | |
43 level = kFinerLogLevel; | |
44 } else if (upper_case_name == "ALL" || upper_case_name == "FINEST") { | |
45 level = kAllLogLevel; | |
46 } | |
47 return level; | |
48 } | |
49 | |
50 // static | |
51 bool LogType::FromString(const std::string& name, LogType* log_type) { | |
52 if (name == "driver") { | |
53 *log_type = LogType(kDriver); | |
54 } else { | |
55 return false; | |
56 } | |
57 return true; | |
58 } | |
59 | |
60 LogType::LogType() : type_(kInvalid) { } | |
61 | |
62 LogType::LogType(Type type) : type_(type) { } | |
63 | |
64 LogType::~LogType() { } | |
65 | |
66 std::string LogType::ToString() const { | |
67 switch (type_) { | |
68 case kDriver: | |
69 return "driver"; | |
70 default: | |
71 return "unknown"; | |
72 }; | |
73 } | |
74 | |
75 LogType::Type LogType::type() const { | |
76 return type_; | |
77 } | |
78 | |
79 LogHandler::LogHandler() { } | |
80 | |
81 LogHandler::~LogHandler() { } | |
82 | |
83 // static | |
84 void FileLog::SetGlobalLog(FileLog* log) { | |
85 singleton_ = log; | |
86 } | |
87 | |
88 // static | |
89 FileLog* FileLog::Get() { | |
90 return singleton_; | |
91 } | |
92 | |
93 // static | |
94 FileLog* FileLog::CreateFileLog(const base::FilePath::StringType& log_name, | |
95 LogLevel level) { | |
96 base::FilePath log_path(log_name); | |
97 file_util::ScopedFILE file(file_util::OpenFile(log_path, "w")); | |
98 base::FilePath temp_dir; | |
99 if (!file.get() && file_util::GetTempDir(&temp_dir)) | |
100 log_path = temp_dir.Append(log_name); | |
101 file.reset(); | |
102 return new FileLog(log_path, level); | |
103 } | |
104 | |
105 FileLog::FileLog(const base::FilePath& path, LogLevel level) | |
106 : path_(path), | |
107 min_log_level_(level) { | |
108 if (!path_.IsAbsolute()) { | |
109 base::FilePath cwd; | |
110 if (file_util::GetCurrentDirectory(&cwd)) | |
111 path_ = cwd.Append(path_); | |
112 } | |
113 file_.reset(file_util::OpenFile(path_, "w")); | |
114 } | |
115 | |
116 FileLog::~FileLog() { } | |
117 | |
118 void FileLog::Log(LogLevel level, const base::Time& time, | |
119 const std::string& message) { | |
120 if (!file_.get() || level < min_log_level_) | |
121 return; | |
122 | |
123 const char* level_name = "UNKNOWN"; | |
124 switch (level) { | |
125 case kOffLogLevel: | |
126 level_name = "OFF"; | |
127 break; | |
128 case kSevereLogLevel: | |
129 level_name = "SEVERE"; | |
130 break; | |
131 case kWarningLogLevel: | |
132 level_name = "WARNING"; | |
133 break; | |
134 case kInfoLogLevel: | |
135 level_name = "INFO"; | |
136 break; | |
137 case kFineLogLevel: | |
138 level_name = "FINE"; | |
139 break; | |
140 case kFinerLogLevel: | |
141 level_name = "FINER"; | |
142 break; | |
143 default: | |
144 break; | |
145 } | |
146 base::TimeDelta delta(time - base::Time::FromDoubleT(start_time)); | |
147 std::string entry = base::StringPrintf( | |
148 "[%.3lf][%s]:", delta.InSecondsF(), level_name); | |
149 | |
150 int pad_length = 20 - entry.length(); | |
151 if (pad_length < 1) | |
152 pad_length = 1; | |
153 std::string padding(pad_length, ' '); | |
154 entry += padding + message; | |
155 #if defined(OS_WIN) | |
156 entry += "\r\n"; | |
157 #else | |
158 entry += "\n"; | |
159 #endif | |
160 | |
161 base::AutoLock auto_lock(lock_); | |
162 fprintf(file_.get(), "%s", entry.c_str()); | |
163 fflush(file_.get()); | |
164 } | |
165 | |
166 bool FileLog::GetLogContents(std::string* contents) const { | |
167 if (!file_.get()) | |
168 return false; | |
169 return base::ReadFileToString(path_, contents); | |
170 } | |
171 | |
172 bool FileLog::IsOpen() const { | |
173 return !!file_.get(); | |
174 } | |
175 | |
176 void FileLog::set_min_log_level(LogLevel level) { | |
177 min_log_level_ = level; | |
178 } | |
179 | |
180 const base::FilePath& FileLog::path() const { | |
181 return path_; | |
182 } | |
183 | |
184 InMemoryLog::InMemoryLog() { } | |
185 | |
186 InMemoryLog::~InMemoryLog() { } | |
187 | |
188 void InMemoryLog::Log(LogLevel level, const base::Time& time, | |
189 const std::string& message) { | |
190 base::TimeDelta delta = time - base::Time::UnixEpoch(); | |
191 DictionaryValue* entry = new DictionaryValue(); | |
192 entry->SetInteger("level", level); | |
193 entry->SetDouble("timestamp", std::floor(delta.InMillisecondsF())); | |
194 entry->SetString("message", message); | |
195 base::AutoLock auto_lock(entries_lock_); | |
196 entries_list_.Append(entry); | |
197 } | |
198 | |
199 const ListValue* InMemoryLog::entries_list() const { | |
200 return &entries_list_; | |
201 } | |
202 | |
203 Logger::Logger() : min_log_level_(kAllLogLevel) { } | |
204 | |
205 Logger::Logger(LogLevel level) : min_log_level_(level) { } | |
206 | |
207 Logger::~Logger() { } | |
208 | |
209 void Logger::Log(LogLevel level, const std::string& message) const { | |
210 if (level < min_log_level_) | |
211 return; | |
212 | |
213 base::Time time = base::Time::Now(); | |
214 for (size_t i = 0; i < handlers_.size(); ++i) { | |
215 handlers_[i]->Log(level, time, message); | |
216 } | |
217 } | |
218 | |
219 void Logger::AddHandler(LogHandler* log_handler) { | |
220 handlers_.push_back(log_handler); | |
221 } | |
222 | |
223 void Logger::set_min_log_level(LogLevel level) { | |
224 min_log_level_ = level; | |
225 } | |
226 | |
227 bool InitWebDriverLogging(const base::FilePath& log_path, | |
228 LogLevel min_log_level) { | |
229 start_time = base::Time::Now().ToDoubleT(); | |
230 // Turn off base/logging. | |
231 logging::LoggingSettings settings; | |
232 settings.logging_dest = logging::LOG_NONE; | |
233 bool success = logging::InitLogging(settings); | |
234 if (!success) { | |
235 PLOG(ERROR) << "Unable to initialize logging"; | |
236 } | |
237 logging::SetLogItems(false, // enable_process_id | |
238 false, // enable_thread_id | |
239 true, // enable_timestamp | |
240 false); // enable_tickcount | |
241 | |
242 // Init global file log. | |
243 FileLog* log; | |
244 if (log_path.empty()) { | |
245 log = FileLog::CreateFileLog(FILE_PATH_LITERAL("chromedriver.log"), | |
246 min_log_level); | |
247 } else { | |
248 log = new FileLog(log_path, min_log_level); | |
249 } | |
250 FileLog::SetGlobalLog(log); | |
251 return log->IsOpen(); | |
252 } | |
253 | |
254 } // namespace webdriver | |
OLD | NEW |