blob: 029b59ff7fbaffd47c1c0028cb3ab91e74e69d0f [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2010 The Chromium Authors
[email protected]99b7c57f2010-09-29 19:26:362// 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
avi9b6f42932015-12-26 22:15:147#include <stddef.h>
Olivier Li56b00c912021-11-26 15:30:158
[email protected]c014f2b32013-09-03 23:29:129#include <ostream>
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:2710#include <string_view>
[email protected]c014f2b32013-09-03 23:29:1211#include <utility>
12
[email protected]e11de722010-11-01 20:50:5513#include "base/logging.h"
[email protected]dfa049e2013-02-07 02:57:2214#include "base/strings/string_number_conversions.h"
[email protected]5ae0b763e2013-02-07 23:01:3915#include "base/strings/string_split.h"
Jan Wilken Dörrie4fdd27a62020-08-17 20:55:1416#include "base/strings/string_util.h"
[email protected]99b7c57f2010-09-29 19:26:3617
18namespace logging {
19
20const int VlogInfo::kDefaultVlogLevel = 0;
21
[email protected]b0d38d4c2010-10-29 00:39:4822VlogInfo::VmodulePattern::VmodulePattern(const std::string& pattern)
Olivier Li56b00c912021-11-26 15:30:1523 : pattern(pattern),
24 vlog_level(VlogInfo::kDefaultVlogLevel),
25 match_target(MATCH_MODULE) {
[email protected]b0d38d4c2010-10-29 00:39:4826 // 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 Kasting134ef9af2024-12-28 02:30:0929 if (first_slash != std::string::npos) {
[email protected]b0d38d4c2010-10-29 00:39:4830 match_target = MATCH_FILE;
Peter Kasting134ef9af2024-12-28 02:30:0931 }
[email protected]b0d38d4c2010-10-29 00:39:4832}
33
Olivier Li56b00c912021-11-26 15:30:1534VlogInfo::VmodulePattern::VmodulePattern()
35 : vlog_level(VlogInfo::kDefaultVlogLevel), match_target(MATCH_MODULE) {}
36
Fergal Dalycaf92ba2022-05-17 20:11:5237// static
38std::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]99b7c57f2010-09-29 19:26:3658VlogInfo::VlogInfo(const std::string& v_switch,
[email protected]162ac0f2010-11-04 15:50:4959 const std::string& vmodule_switch,
Lei Zhangff18636f2025-03-11 18:08:2360 int& min_log_level)
Fergal Dalycaf92ba2022-05-17 20:11:5261 : vmodule_levels_(ParseVmoduleLevels(vmodule_switch)),
62 min_log_level_(min_log_level) {
[email protected]162ac0f2010-11-04 15:50:4963 int vlog_level = 0;
[email protected]163285302010-11-25 00:48:2564 if (!v_switch.empty()) {
65 if (base::StringToInt(v_switch, &vlog_level)) {
66 SetMaxVlogLevel(vlog_level);
67 } else {
[email protected]a42d4632011-10-26 21:48:0068 DLOG(WARNING) << "Could not parse v switch \"" << v_switch << "\"";
[email protected]163285302010-11-25 00:48:2569 }
[email protected]99b7c57f2010-09-29 19:26:3670 }
[email protected]99b7c57f2010-09-29 19:26:3671}
72
Chris Watkinsbb7211c2017-11-29 07:16:3873VlogInfo::~VlogInfo() = default;
[email protected]1889dc1b2010-10-14 22:03:1374
[email protected]b0d38d4c2010-10-29 00:39:4875namespace {
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. Sayem42abceb72024-05-08 18:48:2780std::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 McArdle5a166e32021-08-11 00:55:1084 module.remove_prefix(last_slash_pos + 1);
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:2785 }
86 size_t extension_start = module.rfind('.');
Olivier Li56b00c912021-11-26 15:30:1587 module = module.substr(0, extension_start);
88 static const char kInlSuffix[] = "-inl";
Daniel Chengf45f47602022-02-28 22:38:3289 static const int kInlSuffixLen = std::size(kInlSuffix) - 1;
Peter Kasting134ef9af2024-12-28 02:30:0990 if (base::EndsWith(module, kInlSuffix)) {
Olivier Li56b00c912021-11-26 15:30:1591 module.remove_suffix(kInlSuffixLen);
Peter Kasting134ef9af2024-12-28 02:30:0992 }
[email protected]b0d38d4c2010-10-29 00:39:4893 return module;
94}
95
96} // namespace
97
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:2798int VlogInfo::GetVlogLevel(std::string_view file) const {
[email protected]99b7c57f2010-09-29 19:26:3699 if (!vmodule_levels_.empty()) {
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:27100 std::string_view module(GetModule(file));
Olivier Li56b00c912021-11-26 15:30:15101 for (const auto& it : vmodule_levels_) {
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:27102 std::string_view target(
Olivier Li56b00c912021-11-26 15:30:15103 (it.match_target == VmodulePattern::MATCH_FILE) ? file : module);
Peter Kasting134ef9af2024-12-28 02:30:09104 if (MatchVlogPattern(target, it.pattern)) {
Olivier Li56b00c912021-11-26 15:30:15105 return it.vlog_level;
Peter Kasting134ef9af2024-12-28 02:30:09106 }
[email protected]99b7c57f2010-09-29 19:26:36107 }
108 }
[email protected]162ac0f2010-11-04 15:50:49109 return GetMaxVlogLevel();
[email protected]99b7c57f2010-09-29 19:26:36110}
111
[email protected]eae9c062011-01-11 00:50:59112void VlogInfo::SetMaxVlogLevel(int level) {
113 // Log severity is the negative verbosity.
114 *min_log_level_ = -level;
115}
116
117int VlogInfo::GetMaxVlogLevel() const {
118 return -*min_log_level_;
119}
120
Fergal Daly432aa7c2022-06-14 07:30:54121VlogInfo::VlogInfo(std::vector<VmodulePattern> vmodule_levels,
Lei Zhangff18636f2025-03-11 18:08:23122 int& min_log_level)
Fergal Daly432aa7c2022-06-14 07:30:54123 : vmodule_levels_(std::move(vmodule_levels)),
124 min_log_level_(min_log_level) {}
125
126VlogInfo* 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 Zhangff18636f2025-03-11 18:08:23132 return new VlogInfo(std::move(vmodule_levels), *min_log_level_);
Fergal Daly432aa7c2022-06-14 07:30:54133}
134
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:27135bool MatchVlogPattern(std::string_view string, std::string_view vlog_pattern) {
Bin Dub0f71872020-07-30 17:03:14136 // 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 Li56b00c912021-11-26 15:30:15140 size_t slen = string.size(), plen = vlog_pattern.size();
Bin Dub0f71872020-07-30 17:03:14141 while (s < slen || p < plen) {
142 if (p < plen) {
Dan McArdle5a166e32021-08-11 00:55:10143 switch (vlog_pattern[p]) {
Bin Dub0f71872020-07-30 17:03:14144 // A slash (forward or back) must match a slash (forward or back).
145 case '/':
146 case '\\':
Dan McArdle5a166e32021-08-11 00:55:10147 if (s < slen && (string[s] == '/' || string[s] == '\\')) {
Bin Dub0f71872020-07-30 17:03:14148 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 McArdle5a166e32021-08-11 00:55:10166 if (s < slen && string[s] == vlog_pattern[p]) {
Bin Dub0f71872020-07-30 17:03:14167 p++, s++;
168 continue;
169 }
170 break;
171 }
[email protected]e11de722010-11-01 20:50:55172 }
Bin Dub0f71872020-07-30 17:03:14173 // Mismatch - maybe restart.
174 if (0 < nexts && nexts <= slen) {
175 p = nextp;
176 s = nexts;
177 continue;
178 }
179 return false;
[email protected]e11de722010-11-01 20:50:55180 }
Bin Dub0f71872020-07-30 17:03:14181 return true;
[email protected]e11de722010-11-01 20:50:55182}
183
danakjc3762b92015-03-07 01:51:42184} // namespace logging