blob: 8c1d956060712b56713bb6e3af7760ce4ea2f5d7 [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
9#include <base/string_tokenizer.h>
10#include <base/string_util.h>
11
12using std::string;
13using std::vector;
14
15namespace shill {
16
17namespace {
18
19const int kDefaultVerboseLevel = 0;
20
21// Scope names corresponding to the scope defined by ScopeLogger::Scope.
22const char *const kScopeNames[] = {
23 "cellular",
24 "connection",
25 "crypto",
Ben Chanfad4a0b2012-04-18 15:49:59 -070026 "daemon",
Ben Chanbc49ac72012-04-10 19:59:45 -070027 "dbus",
28 "device",
Ben Chanfad4a0b2012-04-18 15:49:59 -070029 "dhcp",
30 "dns",
Ben Chanbc49ac72012-04-10 19:59:45 -070031 "ethernet",
Ben Chanfad4a0b2012-04-18 15:49:59 -070032 "http",
33 "httpproxy",
Ben Chanbc49ac72012-04-10 19:59:45 -070034 "inet",
Paul Stewart6c72c972012-07-27 11:29:20 -070035 "link",
Ben Chanbc49ac72012-04-10 19:59:45 -070036 "manager",
37 "metrics",
38 "modem",
39 "portal",
Ben Chanfad4a0b2012-04-18 15:49:59 -070040 "power",
Ben Chanbc49ac72012-04-10 19:59:45 -070041 "profile",
Ben Chanfad4a0b2012-04-18 15:49:59 -070042 "property",
43 "resolver",
44 "route",
Ben Chanbc49ac72012-04-10 19:59:45 -070045 "rtnl",
46 "service",
47 "storage",
48 "task",
49 "vpn",
50 "wifi",
Darin Petkov096b3472012-05-15 10:26:22 +020051 "wimax",
Ben Chanbc49ac72012-04-10 19:59:45 -070052};
53
54COMPILE_ASSERT(arraysize(kScopeNames) == ScopeLogger::kNumScopes,
55 scope_tags_does_not_have_expected_number_of_strings);
56
Ben Chanfdfdc872012-04-24 08:31:36 -070057// ScopeLogger needs to be a 'leaky' singleton as it needs to survive to
58// handle logging till the very end of the shill process. Making ScopeLogger
59// leaky is fine as it does not need to clean up or release any resource at
60// destruction.
61base::LazyInstance<ScopeLogger>::Leaky g_scope_logger =
62 LAZY_INSTANCE_INITIALIZER;
Ben Chanbc49ac72012-04-10 19:59:45 -070063
64} // namespace
65
66// static
67ScopeLogger* ScopeLogger::GetInstance() {
68 return g_scope_logger.Pointer();
69}
70
71ScopeLogger::ScopeLogger()
72 : verbose_level_(kDefaultVerboseLevel) {
73}
74
75ScopeLogger::~ScopeLogger() {
76}
77
78bool ScopeLogger::IsLogEnabled(Scope scope, int verbose_level) const {
Paul Stewart5581d072012-12-17 17:30:20 -080079 return IsScopeEnabled(scope) && verbose_level <= verbose_level_;
80}
81
82bool ScopeLogger::IsScopeEnabled(Scope scope) const {
Ben Chanbc49ac72012-04-10 19:59:45 -070083 CHECK_GE(scope, 0);
84 CHECK_LT(scope, kNumScopes);
85
Paul Stewart5581d072012-12-17 17:30:20 -080086 return scope_enabled_[scope];
Ben Chanbc49ac72012-04-10 19:59:45 -070087}
88
89string ScopeLogger::GetAllScopeNames() const {
90 vector<string> names(kScopeNames, kScopeNames + arraysize(kScopeNames));
Ben Chan1c722602012-04-17 17:37:35 -070091 return JoinString(names, '+');
Ben Chanbc49ac72012-04-10 19:59:45 -070092}
93
94string ScopeLogger::GetEnabledScopeNames() const {
95 vector<string> names;
96 for (size_t i = 0; i < arraysize(kScopeNames); ++i) {
97 if (scope_enabled_[i])
98 names.push_back(kScopeNames[i]);
99 }
100 return JoinString(names, '+');
101}
102
103void ScopeLogger::EnableScopesByName(const string &expression) {
104 if (expression.empty()) {
105 DisableAllScopes();
106 return;
107 }
108
109 // As described in the header file, if the first scope name in the
110 // sequence specified by |expression| is not prefixed by a plus or
111 // minus sign, it indicates that all scopes are first disabled before
112 // enabled by |expression|.
113 if (expression[0] != '+' && expression[0] != '-')
114 DisableAllScopes();
115
116 bool enable_scope = true;
117 StringTokenizer tokenizer(expression, "+-");
118 tokenizer.set_options(StringTokenizer::RETURN_DELIMS);
119 while (tokenizer.GetNext()) {
120 if (tokenizer.token_is_delim()) {
121 enable_scope = (tokenizer.token() == "+");
122 continue;
123 }
124
125 if (tokenizer.token().empty())
126 continue;
127
128 size_t i;
129 for (i = 0; i < arraysize(kScopeNames); ++i) {
130 if (tokenizer.token() == kScopeNames[i]) {
131 SetScopeEnabled(static_cast<Scope>(i), enable_scope);
132 break;
133 }
134 }
135 LOG_IF(WARNING, i == arraysize(kScopeNames))
136 << "Unknown scope '" << tokenizer.token() << "'";
137 }
138}
139
Paul Stewart5581d072012-12-17 17:30:20 -0800140void ScopeLogger::RegisterScopeEnableChangedCallback(
141 Scope scope, ScopeEnableChangedCallback callback) {
142 CHECK_GE(scope, 0);
143 CHECK_LT(scope, kNumScopes);
144 log_scope_callbacks_[scope].push_back(callback);
145}
146
Ben Chanbc49ac72012-04-10 19:59:45 -0700147void ScopeLogger::DisableAllScopes() {
Paul Stewart5581d072012-12-17 17:30:20 -0800148 // Iterate over all scopes so the notification side-effect occurs.
149 for (size_t i = 0; i < arraysize(kScopeNames); ++i) {
150 SetScopeEnabled(static_cast<Scope>(i), false);
151 }
Ben Chanbc49ac72012-04-10 19:59:45 -0700152}
153
154void ScopeLogger::SetScopeEnabled(Scope scope, bool enabled) {
155 CHECK_GE(scope, 0);
156 CHECK_LT(scope, kNumScopes);
157
Paul Stewart5581d072012-12-17 17:30:20 -0800158 if (scope_enabled_[scope] != enabled) {
159 ScopeEnableChangedCallbacks &callbacks = log_scope_callbacks_[scope];
160 ScopeEnableChangedCallbacks::iterator it;
161 for (it = callbacks.begin(); it != callbacks.end(); ++it) {
162 (*it).Run(enabled);
163 }
164 }
165
Ben Chanbc49ac72012-04-10 19:59:45 -0700166 scope_enabled_[scope] = enabled;
167}
168
169} // namespace shill