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