13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 23345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Use of this source code is governed by a BSD-style license that can be 33345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// found in the LICENSE file. 43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 53345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/vlog.h" 63345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/basictypes.h" 8513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/logging.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_split.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricknamespace logging { 133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst int VlogInfo::kDefaultVlogLevel = 0; 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstruct VlogInfo::VmodulePattern { 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen enum MatchTarget { MATCH_MODULE, MATCH_FILE }; 1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen explicit VmodulePattern(const std::string& pattern); 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen VmodulePattern(); 2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string pattern; 2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int vlog_level; 2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MatchTarget match_target; 2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 28513209b27ff55e2841eac0e4120199c23acce758Ben MurdochVlogInfo::VmodulePattern::VmodulePattern(const std::string& pattern) 29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : pattern(pattern), 30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch vlog_level(VlogInfo::kDefaultVlogLevel), 31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch match_target(MATCH_MODULE) { 32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // If the pattern contains a {forward,back} slash, we assume that 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // it's meant to be tested against the entire __FILE__ string. 34513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string::size_type first_slash = pattern.find_first_of("\\/"); 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (first_slash != std::string::npos) 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch match_target = MATCH_FILE; 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 39513209b27ff55e2841eac0e4120199c23acce758Ben MurdochVlogInfo::VmodulePattern::VmodulePattern() 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : vlog_level(VlogInfo::kDefaultVlogLevel), 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch match_target(MATCH_MODULE) {} 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickVlogInfo::VlogInfo(const std::string& v_switch, 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& vmodule_switch, 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int* min_log_level) 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : min_log_level_(min_log_level) { 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(min_log_level != NULL); 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick typedef std::pair<std::string, std::string> KVPair; 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int vlog_level = 0; 51201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!v_switch.empty()) { 52201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (base::StringToInt(v_switch, &vlog_level)) { 53201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SetMaxVlogLevel(vlog_level); 54201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } else { 55201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LOG(WARNING) << "Could not parse v switch \"" << v_switch << "\""; 56201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<KVPair> kv_pairs; 603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!base::SplitStringIntoKeyValuePairs( 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick vmodule_switch, '=', ',', &kv_pairs)) { 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(WARNING) << "Could not fully parse vmodule switch \"" 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick << vmodule_switch << "\""; 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (std::vector<KVPair>::const_iterator it = kv_pairs.begin(); 663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick it != kv_pairs.end(); ++it) { 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch VmodulePattern pattern(it->first); 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!base::StringToInt(it->second, &pattern.vlog_level)) { 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(WARNING) << "Parsed vlog level for \"" 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick << it->first << "=" << it->second 71513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch << "\" as " << pattern.vlog_level; 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch vmodule_levels_.push_back(pattern); 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 77731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickVlogInfo::~VlogInfo() {} 78731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace { 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Given a path, returns the basename with the extension chopped off 82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// (and any -inl suffix). We avoid using FilePath to minimize the 83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// number of dependencies the logging system has. 84513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbase::StringPiece GetModule(const base::StringPiece& file) { 85513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::StringPiece module(file); 86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::StringPiece::size_type last_slash_pos = 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch module.find_last_of("\\/"); 88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (last_slash_pos != base::StringPiece::npos) 89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch module.remove_prefix(last_slash_pos + 1); 90513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::StringPiece::size_type extension_start = module.rfind('.'); 91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch module = module.substr(0, extension_start); 92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch static const char kInlSuffix[] = "-inl"; 93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch static const int kInlSuffixLen = arraysize(kInlSuffix) - 1; 94513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (module.ends_with(kInlSuffix)) 95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch module.remove_suffix(kInlSuffixLen); 96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return module; 97513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace 100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 101513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint VlogInfo::GetVlogLevel(const base::StringPiece& file) const { 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!vmodule_levels_.empty()) { 103513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::StringPiece module(GetModule(file)); 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (std::vector<VmodulePattern>::const_iterator it = 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick vmodule_levels_.begin(); it != vmodule_levels_.end(); ++it) { 106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::StringPiece target( 107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (it->match_target == VmodulePattern::MATCH_FILE) ? file : module); 108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (MatchVlogPattern(target, it->pattern)) 109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return it->vlog_level; 110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 112513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return GetMaxVlogLevel(); 113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid VlogInfo::SetMaxVlogLevel(int level) { 11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Log severity is the negative verbosity. 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *min_log_level_ = -level; 11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint VlogInfo::GetMaxVlogLevel() const { 12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return -*min_log_level_; 12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 124513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool MatchVlogPattern(const base::StringPiece& string, 125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const base::StringPiece& vlog_pattern) { 126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::StringPiece p(vlog_pattern); 127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::StringPiece s(string); 128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Consume characters until the next star. 129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch while (!p.empty() && !s.empty() && (p[0] != '*')) { 130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch switch (p[0]) { 131513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // A slash (forward or back) must match a slash (forward or back). 132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case '/': 133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case '\\': 134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if ((s[0] != '/') && (s[0] != '\\')) 135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 137513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // A '?' matches anything. 139513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case '?': 140513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 142513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Anything else must match literally. 143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch default: 144513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (p[0] != s[0]) 145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch p.remove_prefix(1), s.remove_prefix(1); 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // An empty pattern here matches only an empty string. 152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (p.empty()) 153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return s.empty(); 154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Coalesce runs of consecutive stars. There should be at least 156513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // one. 157513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch while (!p.empty() && (p[0] == '*')) 158513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch p.remove_prefix(1); 159513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 160513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Since we moved past the stars, an empty pattern here matches 161513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // anything. 162513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (p.empty()) 163513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return true; 164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 165513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Since we moved past the stars and p is non-empty, if some 166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // non-empty substring of s matches p, then we ourselves match. 167513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch while (!s.empty()) { 168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (MatchVlogPattern(s, p)) 169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return true; 170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch s.remove_prefix(1); 171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Otherwise, we couldn't find a match. 174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} // namespace 178