log.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// found in the LICENSE file.
4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <stdio.h>
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/json/json_reader.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/json/json_writer.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/stringprintf.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/values.h"
11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/test/chromedriver/logging.h"
12b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Truncates the given string to 200 characters, adding an ellipsis if
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// truncation was necessary.
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TruncateString(std::string* data) {
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const size_t kMaxLength = 200;
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (data->length() > kMaxLength) {
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    data->resize(kMaxLength);
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    data->replace(kMaxLength - 3, 3, "...");
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Truncates all strings contained in the given value.
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TruncateContainedStrings(base::Value* value) {
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::ListValue* list = NULL;
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::DictionaryValue* dict = NULL;
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value->GetAsDictionary(&dict)) {
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         it.Advance()) {
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::string data;
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (it.value().GetAsString(&data)) {
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        TruncateString(&data);
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        dict->SetWithoutPathExpansion(it.key(), new base::StringValue(data));
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      } else {
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::Value* child = NULL;
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        dict->GetWithoutPathExpansion(it.key(), &child);
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        TruncateContainedStrings(child);
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else if (value->GetAsList(&list)) {
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (size_t i = 0; i < list->GetSize(); ++i) {
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Value* child = NULL;
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!list->Get(i, &child))
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        continue;
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::string data;
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (child->GetAsString(&data)) {
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        TruncateString(&data);
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        list->Set(i, new base::StringValue(data));
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      } else {
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        TruncateContainedStrings(child);
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Pretty prints encapsulated JSON and truncates long strings for display.
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string ConvertForDisplay(const std::string& input) {
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t left = input.find("{");
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t right = input.rfind("}");
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (left == std::string::npos || right == std::string::npos)
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return input.substr(0, 10 << 10);
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<base::Value> value(
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::JSONReader::Read(input.substr(left, right - left + 1)));
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!value)
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return input.substr(0, 10 << 10);
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TruncateContainedStrings(value.get());
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string json;
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::JSONWriter::WriteWithOptions(
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      value.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &json);
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string display = input.substr(0, left) + json;
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (input.length() > right)
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    display += input.substr(right + 1);
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return display;
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void Log::AddEntry(Log::Level level, const std::string& message) {
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return AddEntry(base::Time::Now(), level, message);
83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Logger::Logger() : min_log_level_(kLog), start_(base::Time::Now()) {}
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Logger::Logger(Level min_log_level)
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : min_log_level_(min_log_level), start_(base::Time::Now()) {}
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Logger::~Logger() {}
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Logger::AddEntry(const base::Time& time,
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      Level level,
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      const std::string& message) {
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (level < min_log_level_)
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char* level_name = "UNKNOWN";
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (level) {
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kDebug:
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      level_name = "DEBUG";
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kLog:
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      level_name = "INFO";
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kWarning:
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      level_name = "WARNING";
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kError:
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      level_name = "ERROR";
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string entry =
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::StringPrintf("[%.3lf][%s]: %s",
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         base::TimeDelta(time - start_).InSecondsF(),
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         level_name,
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         ConvertForDisplay(message).c_str());
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char* format = "%s\n";
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (entry[entry.length() - 1] == '\n')
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    format = "%s";
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fprintf(stderr, format, entry.c_str());
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fflush(stderr);
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
126