log.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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)
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/test/chromedriver/chrome/log.h"
6ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <stdio.h>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/json/json_reader.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/json/json_writer.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/values.h"
14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Truncates the given string to 200 characters, adding an ellipsis if
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// truncation was necessary.
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TruncateString(std::string* data) {
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const size_t kMaxLength = 200;
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (data->length() > kMaxLength) {
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    data->resize(kMaxLength);
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    data->replace(kMaxLength - 3, 3, "...");
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Truncates all strings contained in the given value.
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void TruncateContainedStrings(base::Value* value) {
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::ListValue* list = NULL;
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::DictionaryValue* dict = NULL;
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value->GetAsDictionary(&dict)) {
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         it.Advance()) {
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::string data;
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (it.value().GetAsString(&data)) {
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        TruncateString(&data);
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        dict->SetWithoutPathExpansion(it.key(), new base::StringValue(data));
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      } else {
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::Value* child = NULL;
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        dict->GetWithoutPathExpansion(it.key(), &child);
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        TruncateContainedStrings(child);
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else if (value->GetAsList(&list)) {
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (size_t i = 0; i < list->GetSize(); ++i) {
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Value* child = NULL;
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!list->Get(i, &child))
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        continue;
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::string data;
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (child->GetAsString(&data)) {
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        TruncateString(&data);
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        list->Set(i, new base::StringValue(data));
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      } else {
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        TruncateContainedStrings(child);
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::string ConvertForDisplayInternal(const std::string& input) {
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t left = input.find("{");
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t right = input.rfind("}");
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (left == std::string::npos || right == std::string::npos)
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return input.substr(0, 10 << 10);
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<base::Value> value(
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::JSONReader::Read(input.substr(left, right - left + 1)));
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!value)
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return input.substr(0, 10 << 10);
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TruncateContainedStrings(value.get());
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string json;
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::JSONWriter::WriteWithOptions(
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      value.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &json);
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string display = input.substr(0, left) + json;
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (input.length() > right)
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    display += input.substr(right + 1);
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return display;
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Pretty prints encapsulated JSON and truncates long strings for display.
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::string ConvertForDisplay(const std::string& input) {
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::string display = ConvertForDisplayInternal(input);
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  char remove_chars[] = {'\r', '\0'};
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveChars(display, remove_chars, &display);
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return display;
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Log::AddEntry(Level level, const std::string& message) {
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AddEntryTimestamped(base::Time::Now(), level, message);
92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Logger::Logger() : min_log_level_(kLog), start_(base::Time::Now()) {}
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Logger::Logger(Level min_log_level)
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : min_log_level_(min_log_level), start_(base::Time::Now()) {}
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)Logger::~Logger() {}
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void Logger::AddEntryTimestamped(const base::Time& timestamp,
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 Level level,
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 const std::string& message) {
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (level < min_log_level_)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char* level_name = "UNKNOWN";
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (level) {
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kDebug:
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      level_name = "DEBUG";
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kLog:
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      level_name = "INFO";
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kWarning:
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      level_name = "WARNING";
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kError:
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      level_name = "ERROR";
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string entry =
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::StringPrintf("[%.3lf][%s]: %s",
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         base::TimeDelta(timestamp - start_).InSecondsF(),
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         level_name,
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         ConvertForDisplay(message).c_str());
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char* format = "%s\n";
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (entry[entry.length() - 1] == '\n')
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    format = "%s";
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fprintf(stderr, format, entry.c_str());
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fflush(stderr);
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
135