Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2010 The Chromium Authors |
[email protected] | 99b7c57f | 2010-09-29 19:26:36 | [diff] [blame] | 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 "base/vlog.h" |
| 6 | |
avi | 9b6f4293 | 2015-12-26 22:15:14 | [diff] [blame] | 7 | #include <stddef.h> |
Olivier Li | 56b00c91 | 2021-11-26 15:30:15 | [diff] [blame] | 8 | |
[email protected] | c014f2b3 | 2013-09-03 23:29:12 | [diff] [blame] | 9 | #include <ostream> |
Aquibuzzaman Md. Sayem | 42abceb7 | 2024-05-08 18:48:27 | [diff] [blame] | 10 | #include <string_view> |
[email protected] | c014f2b3 | 2013-09-03 23:29:12 | [diff] [blame] | 11 | #include <utility> |
| 12 | |
[email protected] | e11de72 | 2010-11-01 20:50:55 | [diff] [blame] | 13 | #include "base/logging.h" |
[email protected] | dfa049e | 2013-02-07 02:57:22 | [diff] [blame] | 14 | #include "base/strings/string_number_conversions.h" |
[email protected] | 5ae0b763e | 2013-02-07 23:01:39 | [diff] [blame] | 15 | #include "base/strings/string_split.h" |
Jan Wilken Dörrie | 4fdd27a6 | 2020-08-17 20:55:14 | [diff] [blame] | 16 | #include "base/strings/string_util.h" |
[email protected] | 99b7c57f | 2010-09-29 19:26:36 | [diff] [blame] | 17 | |
| 18 | namespace logging { |
| 19 | |
| 20 | const int VlogInfo::kDefaultVlogLevel = 0; |
| 21 | |
[email protected] | b0d38d4c | 2010-10-29 00:39:48 | [diff] [blame] | 22 | VlogInfo::VmodulePattern::VmodulePattern(const std::string& pattern) |
Olivier Li | 56b00c91 | 2021-11-26 15:30:15 | [diff] [blame] | 23 | : pattern(pattern), |
| 24 | vlog_level(VlogInfo::kDefaultVlogLevel), |
| 25 | match_target(MATCH_MODULE) { |
[email protected] | b0d38d4c | 2010-10-29 00:39:48 | [diff] [blame] | 26 | // If the pattern contains a {forward,back} slash, we assume that |
| 27 | // it's meant to be tested against the entire __FILE__ string. |
| 28 | std::string::size_type first_slash = pattern.find_first_of("\\/"); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 29 | if (first_slash != std::string::npos) { |
[email protected] | b0d38d4c | 2010-10-29 00:39:48 | [diff] [blame] | 30 | match_target = MATCH_FILE; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 31 | } |
[email protected] | b0d38d4c | 2010-10-29 00:39:48 | [diff] [blame] | 32 | } |
| 33 | |
Olivier Li | 56b00c91 | 2021-11-26 15:30:15 | [diff] [blame] | 34 | VlogInfo::VmodulePattern::VmodulePattern() |
| 35 | : vlog_level(VlogInfo::kDefaultVlogLevel), match_target(MATCH_MODULE) {} |
| 36 | |
Fergal Daly | caf92ba | 2022-05-17 20:11:52 | [diff] [blame] | 37 | // static |
| 38 | std::vector<VlogInfo::VmodulePattern> VlogInfo::ParseVmoduleLevels( |
| 39 | const std::string& vmodule_switch) { |
| 40 | std::vector<VmodulePattern> vmodule_levels; |
| 41 | base::StringPairs kv_pairs; |
| 42 | if (!base::SplitStringIntoKeyValuePairs(vmodule_switch, '=', ',', |
| 43 | &kv_pairs)) { |
| 44 | DLOG(WARNING) << "Could not fully parse vmodule switch \"" << vmodule_switch |
| 45 | << "\""; |
| 46 | } |
| 47 | for (const auto& pair : kv_pairs) { |
| 48 | VmodulePattern pattern(pair.first); |
| 49 | if (!base::StringToInt(pair.second, &pattern.vlog_level)) { |
| 50 | DLOG(WARNING) << "Parsed vlog level for \"" << pair.first << "=" |
| 51 | << pair.second << "\" as " << pattern.vlog_level; |
| 52 | } |
| 53 | vmodule_levels.push_back(pattern); |
| 54 | } |
| 55 | return vmodule_levels; |
| 56 | } |
| 57 | |
[email protected] | 99b7c57f | 2010-09-29 19:26:36 | [diff] [blame] | 58 | VlogInfo::VlogInfo(const std::string& v_switch, |
[email protected] | 162ac0f | 2010-11-04 15:50:49 | [diff] [blame] | 59 | const std::string& vmodule_switch, |
Lei Zhang | ff18636f | 2025-03-11 18:08:23 | [diff] [blame] | 60 | int& min_log_level) |
Fergal Daly | caf92ba | 2022-05-17 20:11:52 | [diff] [blame] | 61 | : vmodule_levels_(ParseVmoduleLevels(vmodule_switch)), |
| 62 | min_log_level_(min_log_level) { |
[email protected] | 162ac0f | 2010-11-04 15:50:49 | [diff] [blame] | 63 | int vlog_level = 0; |
[email protected] | 16328530 | 2010-11-25 00:48:25 | [diff] [blame] | 64 | if (!v_switch.empty()) { |
| 65 | if (base::StringToInt(v_switch, &vlog_level)) { |
| 66 | SetMaxVlogLevel(vlog_level); |
| 67 | } else { |
[email protected] | a42d463 | 2011-10-26 21:48:00 | [diff] [blame] | 68 | DLOG(WARNING) << "Could not parse v switch \"" << v_switch << "\""; |
[email protected] | 16328530 | 2010-11-25 00:48:25 | [diff] [blame] | 69 | } |
[email protected] | 99b7c57f | 2010-09-29 19:26:36 | [diff] [blame] | 70 | } |
[email protected] | 99b7c57f | 2010-09-29 19:26:36 | [diff] [blame] | 71 | } |
| 72 | |
Chris Watkins | bb7211c | 2017-11-29 07:16:38 | [diff] [blame] | 73 | VlogInfo::~VlogInfo() = default; |
[email protected] | 1889dc1b | 2010-10-14 22:03:13 | [diff] [blame] | 74 | |
[email protected] | b0d38d4c | 2010-10-29 00:39:48 | [diff] [blame] | 75 | namespace { |
| 76 | |
| 77 | // Given a path, returns the basename with the extension chopped off |
| 78 | // (and any -inl suffix). We avoid using FilePath to minimize the |
| 79 | // number of dependencies the logging system has. |
Aquibuzzaman Md. Sayem | 42abceb7 | 2024-05-08 18:48:27 | [diff] [blame] | 80 | std::string_view GetModule(std::string_view file) { |
| 81 | std::string_view module(file); |
| 82 | size_t last_slash_pos = module.find_last_of("\\/"); |
| 83 | if (last_slash_pos != std::string_view::npos) { |
Dan McArdle | 5a166e3 | 2021-08-11 00:55:10 | [diff] [blame] | 84 | module.remove_prefix(last_slash_pos + 1); |
Aquibuzzaman Md. Sayem | 42abceb7 | 2024-05-08 18:48:27 | [diff] [blame] | 85 | } |
| 86 | size_t extension_start = module.rfind('.'); |
Olivier Li | 56b00c91 | 2021-11-26 15:30:15 | [diff] [blame] | 87 | module = module.substr(0, extension_start); |
| 88 | static const char kInlSuffix[] = "-inl"; |
Daniel Cheng | f45f4760 | 2022-02-28 22:38:32 | [diff] [blame] | 89 | static const int kInlSuffixLen = std::size(kInlSuffix) - 1; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 90 | if (base::EndsWith(module, kInlSuffix)) { |
Olivier Li | 56b00c91 | 2021-11-26 15:30:15 | [diff] [blame] | 91 | module.remove_suffix(kInlSuffixLen); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 92 | } |
[email protected] | b0d38d4c | 2010-10-29 00:39:48 | [diff] [blame] | 93 | return module; |
| 94 | } |
| 95 | |
| 96 | } // namespace |
| 97 | |
Aquibuzzaman Md. Sayem | 42abceb7 | 2024-05-08 18:48:27 | [diff] [blame] | 98 | int VlogInfo::GetVlogLevel(std::string_view file) const { |
[email protected] | 99b7c57f | 2010-09-29 19:26:36 | [diff] [blame] | 99 | if (!vmodule_levels_.empty()) { |
Aquibuzzaman Md. Sayem | 42abceb7 | 2024-05-08 18:48:27 | [diff] [blame] | 100 | std::string_view module(GetModule(file)); |
Olivier Li | 56b00c91 | 2021-11-26 15:30:15 | [diff] [blame] | 101 | for (const auto& it : vmodule_levels_) { |
Aquibuzzaman Md. Sayem | 42abceb7 | 2024-05-08 18:48:27 | [diff] [blame] | 102 | std::string_view target( |
Olivier Li | 56b00c91 | 2021-11-26 15:30:15 | [diff] [blame] | 103 | (it.match_target == VmodulePattern::MATCH_FILE) ? file : module); |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 104 | if (MatchVlogPattern(target, it.pattern)) { |
Olivier Li | 56b00c91 | 2021-11-26 15:30:15 | [diff] [blame] | 105 | return it.vlog_level; |
Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 106 | } |
[email protected] | 99b7c57f | 2010-09-29 19:26:36 | [diff] [blame] | 107 | } |
| 108 | } |
[email protected] | 162ac0f | 2010-11-04 15:50:49 | [diff] [blame] | 109 | return GetMaxVlogLevel(); |
[email protected] | 99b7c57f | 2010-09-29 19:26:36 | [diff] [blame] | 110 | } |
| 111 | |
[email protected] | eae9c06 | 2011-01-11 00:50:59 | [diff] [blame] | 112 | void VlogInfo::SetMaxVlogLevel(int level) { |
| 113 | // Log severity is the negative verbosity. |
| 114 | *min_log_level_ = -level; |
| 115 | } |
| 116 | |
| 117 | int VlogInfo::GetMaxVlogLevel() const { |
| 118 | return -*min_log_level_; |
| 119 | } |
| 120 | |
Fergal Daly | 432aa7c | 2022-06-14 07:30:54 | [diff] [blame] | 121 | VlogInfo::VlogInfo(std::vector<VmodulePattern> vmodule_levels, |
Lei Zhang | ff18636f | 2025-03-11 18:08:23 | [diff] [blame] | 122 | int& min_log_level) |
Fergal Daly | 432aa7c | 2022-06-14 07:30:54 | [diff] [blame] | 123 | : vmodule_levels_(std::move(vmodule_levels)), |
| 124 | min_log_level_(min_log_level) {} |
| 125 | |
| 126 | VlogInfo* VlogInfo::WithSwitches(const std::string& vmodule_switch) const { |
| 127 | std::vector<VmodulePattern> vmodule_levels = vmodule_levels_; |
| 128 | std::vector<VmodulePattern> additional_vmodule_levels = |
| 129 | ParseVmoduleLevels(vmodule_switch); |
| 130 | vmodule_levels.insert(vmodule_levels.end(), additional_vmodule_levels.begin(), |
| 131 | additional_vmodule_levels.end()); |
Lei Zhang | ff18636f | 2025-03-11 18:08:23 | [diff] [blame] | 132 | return new VlogInfo(std::move(vmodule_levels), *min_log_level_); |
Fergal Daly | 432aa7c | 2022-06-14 07:30:54 | [diff] [blame] | 133 | } |
| 134 | |
Aquibuzzaman Md. Sayem | 42abceb7 | 2024-05-08 18:48:27 | [diff] [blame] | 135 | bool MatchVlogPattern(std::string_view string, std::string_view vlog_pattern) { |
Bin Du | b0f7187 | 2020-07-30 17:03:14 | [diff] [blame] | 136 | // The code implements the glob matching using a greedy approach described in |
| 137 | // https://research.swtch.com/glob. |
| 138 | size_t s = 0, nexts = 0; |
| 139 | size_t p = 0, nextp = 0; |
Olivier Li | 56b00c91 | 2021-11-26 15:30:15 | [diff] [blame] | 140 | size_t slen = string.size(), plen = vlog_pattern.size(); |
Bin Du | b0f7187 | 2020-07-30 17:03:14 | [diff] [blame] | 141 | while (s < slen || p < plen) { |
| 142 | if (p < plen) { |
Dan McArdle | 5a166e3 | 2021-08-11 00:55:10 | [diff] [blame] | 143 | switch (vlog_pattern[p]) { |
Bin Du | b0f7187 | 2020-07-30 17:03:14 | [diff] [blame] | 144 | // A slash (forward or back) must match a slash (forward or back). |
| 145 | case '/': |
| 146 | case '\\': |
Dan McArdle | 5a166e3 | 2021-08-11 00:55:10 | [diff] [blame] | 147 | if (s < slen && (string[s] == '/' || string[s] == '\\')) { |
Bin Du | b0f7187 | 2020-07-30 17:03:14 | [diff] [blame] | 148 | p++, s++; |
| 149 | continue; |
| 150 | } |
| 151 | break; |
| 152 | // A '?' matches anything. |
| 153 | case '?': |
| 154 | if (s < slen) { |
| 155 | p++, s++; |
| 156 | continue; |
| 157 | } |
| 158 | break; |
| 159 | case '*': |
| 160 | nextp = p; |
| 161 | nexts = s + 1; |
| 162 | p++; |
| 163 | continue; |
| 164 | // Anything else must match literally. |
| 165 | default: |
Dan McArdle | 5a166e3 | 2021-08-11 00:55:10 | [diff] [blame] | 166 | if (s < slen && string[s] == vlog_pattern[p]) { |
Bin Du | b0f7187 | 2020-07-30 17:03:14 | [diff] [blame] | 167 | p++, s++; |
| 168 | continue; |
| 169 | } |
| 170 | break; |
| 171 | } |
[email protected] | e11de72 | 2010-11-01 20:50:55 | [diff] [blame] | 172 | } |
Bin Du | b0f7187 | 2020-07-30 17:03:14 | [diff] [blame] | 173 | // Mismatch - maybe restart. |
| 174 | if (0 < nexts && nexts <= slen) { |
| 175 | p = nextp; |
| 176 | s = nexts; |
| 177 | continue; |
| 178 | } |
| 179 | return false; |
[email protected] | e11de72 | 2010-11-01 20:50:55 | [diff] [blame] | 180 | } |
Bin Du | b0f7187 | 2020-07-30 17:03:14 | [diff] [blame] | 181 | return true; |
[email protected] | e11de72 | 2010-11-01 20:50:55 | [diff] [blame] | 182 | } |
| 183 | |
danakj | c3762b9 | 2015-03-07 01:51:42 | [diff] [blame] | 184 | } // namespace logging |