blob: 786a16c1b3a75b0114f30a92493713c4d67d2830 [file] [log] [blame]
Ben Chanbc49ac72012-04-10 19:59:45 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
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 "shill/scope_logger.h"
6
7#include <vector>
8
Ben Chanbc49ac72012-04-10 19:59:45 -07009#include <base/string_util.h>
Paul Stewart5ad16062013-02-21 18:10:48 -080010#include <base/strings/string_tokenizer.h>
Ben Chanbc49ac72012-04-10 19:59:45 -070011
Paul Stewart5ad16062013-02-21 18:10:48 -080012using base::StringTokenizer;
Ben Chanbc49ac72012-04-10 19:59:45 -070013using std::string;
14using std::vector;
15
16namespace shill {
17
18namespace {
19
20const int kDefaultVerboseLevel = 0;
21
22// Scope names corresponding to the scope defined by ScopeLogger::Scope.
23const char *const kScopeNames[] = {
24 "cellular",
25 "connection",
26 "crypto",
Ben Chanfad4a0b2012-04-18 15:49:59 -070027 "daemon",
Ben Chanbc49ac72012-04-10 19:59:45 -070028 "dbus",
29 "device",
Ben Chanfad4a0b2012-04-18 15:49:59 -070030 "dhcp",
31 "dns",
Ben Chanbc49ac72012-04-10 19:59:45 -070032 "ethernet",
Ben Chanfad4a0b2012-04-18 15:49:59 -070033 "http",
34 "httpproxy",
Ben Chanbc49ac72012-04-10 19:59:45 -070035 "inet",
Paul Stewart6c72c972012-07-27 11:29:20 -070036 "link",
Ben Chanbc49ac72012-04-10 19:59:45 -070037 "manager",
38 "metrics",
39 "modem",
40 "portal",
Ben Chanfad4a0b2012-04-18 15:49:59 -070041 "power",
mukesh agrawal9da07772013-05-15 14:15:17 -070042 "ppp",
Ben Chanbc49ac72012-04-10 19:59:45 -070043 "profile",
Ben Chanfad4a0b2012-04-18 15:49:59 -070044 "property",
45 "resolver",
46 "route",
Ben Chanbc49ac72012-04-10 19:59:45 -070047 "rtnl",
48 "service",
49 "storage",
50 "task",
51 "vpn",
52 "wifi",
Darin Petkov096b3472012-05-15 10:26:22 +020053 "wimax",
Ben Chanbc49ac72012-04-10 19:59:45 -070054};
55
56COMPILE_ASSERT(arraysize(kScopeNames) == ScopeLogger::kNumScopes,
57 scope_tags_does_not_have_expected_number_of_strings);
58
Ben Chanfdfdc872012-04-24 08:31:36 -070059// ScopeLogger needs to be a 'leaky' singleton as it needs to survive to
60// handle logging till the very end of the shill process. Making ScopeLogger
61// leaky is fine as it does not need to clean up or release any resource at
62// destruction.
63base::LazyInstance<ScopeLogger>::Leaky g_scope_logger =
64 LAZY_INSTANCE_INITIALIZER;
Ben Chanbc49ac72012-04-10 19:59:45 -070065
66} // namespace
67
68// static
69ScopeLogger* ScopeLogger::GetInstance() {
70 return g_scope_logger.Pointer();
71}
72
73ScopeLogger::ScopeLogger()
74 : verbose_level_(kDefaultVerboseLevel) {
75}
76
77ScopeLogger::~ScopeLogger() {
78}
79
80bool ScopeLogger::IsLogEnabled(Scope scope, int verbose_level) const {
Paul Stewart5581d072012-12-17 17:30:20 -080081 return IsScopeEnabled(scope) && verbose_level <= verbose_level_;
82}
83
84bool ScopeLogger::IsScopeEnabled(Scope scope) const {
Ben Chanbc49ac72012-04-10 19:59:45 -070085 CHECK_GE(scope, 0);
86 CHECK_LT(scope, kNumScopes);
87
Paul Stewart5581d072012-12-17 17:30:20 -080088 return scope_enabled_[scope];
Ben Chanbc49ac72012-04-10 19:59:45 -070089}
90
91string ScopeLogger::GetAllScopeNames() const {
92 vector<string> names(kScopeNames, kScopeNames + arraysize(kScopeNames));
Ben Chan1c722602012-04-17 17:37:35 -070093 return JoinString(names, '+');
Ben Chanbc49ac72012-04-10 19:59:45 -070094}
95
96string ScopeLogger::GetEnabledScopeNames() const {
97 vector<string> names;
98 for (size_t i = 0; i < arraysize(kScopeNames); ++i) {
99 if (scope_enabled_[i])
100 names.push_back(kScopeNames[i]);
101 }
102 return JoinString(names, '+');
103}
104
105void ScopeLogger::EnableScopesByName(const string &expression) {
106 if (expression.empty()) {
107 DisableAllScopes();
108 return;
109 }
110
111 // As described in the header file, if the first scope name in the
112 // sequence specified by |expression| is not prefixed by a plus or
113 // minus sign, it indicates that all scopes are first disabled before
114 // enabled by |expression|.
115 if (expression[0] != '+' && expression[0] != '-')
116 DisableAllScopes();
117
118 bool enable_scope = true;
119 StringTokenizer tokenizer(expression, "+-");
120 tokenizer.set_options(StringTokenizer::RETURN_DELIMS);
121 while (tokenizer.GetNext()) {
122 if (tokenizer.token_is_delim()) {
123 enable_scope = (tokenizer.token() == "+");
124 continue;
125 }
126
127 if (tokenizer.token().empty())
128 continue;
129
130 size_t i;
131 for (i = 0; i < arraysize(kScopeNames); ++i) {
132 if (tokenizer.token() == kScopeNames[i]) {
133 SetScopeEnabled(static_cast<Scope>(i), enable_scope);
134 break;
135 }
136 }
137 LOG_IF(WARNING, i == arraysize(kScopeNames))
138 << "Unknown scope '" << tokenizer.token() << "'";
139 }
140}
141
Paul Stewart5581d072012-12-17 17:30:20 -0800142void ScopeLogger::RegisterScopeEnableChangedCallback(
143 Scope scope, ScopeEnableChangedCallback callback) {
144 CHECK_GE(scope, 0);
145 CHECK_LT(scope, kNumScopes);
146 log_scope_callbacks_[scope].push_back(callback);
147}
148
Ben Chanbc49ac72012-04-10 19:59:45 -0700149void ScopeLogger::DisableAllScopes() {
Paul Stewart5581d072012-12-17 17:30:20 -0800150 // Iterate over all scopes so the notification side-effect occurs.
151 for (size_t i = 0; i < arraysize(kScopeNames); ++i) {
152 SetScopeEnabled(static_cast<Scope>(i), false);
153 }
Ben Chanbc49ac72012-04-10 19:59:45 -0700154}
155
156void ScopeLogger::SetScopeEnabled(Scope scope, bool enabled) {
157 CHECK_GE(scope, 0);
158 CHECK_LT(scope, kNumScopes);
159
Paul Stewart5581d072012-12-17 17:30:20 -0800160 if (scope_enabled_[scope] != enabled) {
161 ScopeEnableChangedCallbacks &callbacks = log_scope_callbacks_[scope];
162 ScopeEnableChangedCallbacks::iterator it;
163 for (it = callbacks.begin(); it != callbacks.end(); ++it) {
164 (*it).Run(enabled);
165 }
166 }
167
Ben Chanbc49ac72012-04-10 19:59:45 -0700168 scope_enabled_[scope] = enabled;
169}
170
171} // namespace shill