Home | History | Annotate | Download | only in webdriver
      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 file_util::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
    255