scope_logger.h revision d34a47c06c38f2594c85b14b0f9cee2bf37c0e84
1// 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#ifndef SHILL_SCOPE_LOGGER_H_
6#define SHILL_SCOPE_LOGGER_H_
7
8#include <bitset>
9#include <string>
10
11#include <base/basictypes.h>
12#include <base/lazy_instance.h>
13#include <base/logging.h>
14#include <gtest/gtest_prod.h>
15
16// Helper macros to enable logging based on scope and verbose level.
17//
18// The SLOG macro and its variants are similar to the LOG and VLOG macros
19// defined in base/logging.h, except that the SLOG macros take an additional
20// |scope| argument to enable logging only if |scope| is enabled.
21//
22// Like VLOG, SLOG macros internally map verbosity to LOG severity using
23// negative values, i.e. SLOG(scope, 1) corresponds to LOG(-1).
24//
25// Example usages:
26//  SLOG(Service, 1) << "Printed when the 'service' scope is enabled and "
27//                      "the verbose level is greater than or equal to 1";
28//
29//  SLOG_IF(Service, 1, (size > 1024))
30//      << "Printed when the 'service' scope is enabled, the verbose level "
31//         "is greater than or equal to 1, and size is more than 1024";
32//
33//  SPLOG and SPLOG_IF are similar to SLOG and SLOG_IF, respectively, but
34//  append the last system error to the message in string form, which is
35//  taken from errno.
36
37#define SLOG_IS_ON(scope, verbose_level) \
38  ::shill::ScopeLogger::GetInstance()->IsLogEnabled( \
39      ::shill::ScopeLogger::k##scope, verbose_level)
40
41#define SLOG_STREAM(verbose_level) \
42  ::logging::LogMessage(__FILE__, __LINE__, -verbose_level).stream()
43
44#define SLOG(scope, verbose_level) \
45  LAZY_STREAM(SLOG_STREAM(verbose_level), SLOG_IS_ON(scope, verbose_level))
46
47#define SLOG_IF(scope, verbose_level, condition) \
48  LAZY_STREAM(SLOG_STREAM(verbose_level), \
49              SLOG_IS_ON(scope, verbose_level) && (condition))
50
51#define SPLOG_STREAM(verbose_level) \
52  ::logging::ErrnoLogMessage(__FILE__, __LINE__, -verbose_level, \
53                             ::logging::GetLastSystemErrorCode()).stream()
54
55#define SPLOG(scope, verbose_level) \
56  LAZY_STREAM(SPLOG_STREAM(verbose_level), SLOG_IS_ON(scope, verbose_level))
57
58#define SPLOG_IF(scope, verbose_level, condition) \
59  LAZY_STREAM(SPLOG_STREAM(verbose_level), \
60              SLOG_IS_ON(scope, verbose_level) && (condition))
61
62namespace shill {
63
64// A class that enables logging based on scope and verbose level. It is not
65// intended to be used directly but via the SLOG() macros.
66class ScopeLogger {
67 public:
68  // Logging scopes.
69  //
70  // Update kScopeNames in scope_logger.cc after changing this enumerated type.
71  // These scope identifiers are sorted by their scope names alphabetically.
72  enum Scope {
73    kCellular = 0,
74    kConnection,
75    kCrypto,
76    kDaemon,
77    kDBus,
78    kDevice,
79    kDHCP,
80    kDNS,
81    kEthernet,
82    kHTTP,
83    kHTTPProxy,
84    kInet,
85    kManager,
86    kMetrics,
87    kModem,
88    kPortal,
89    kPower,
90    kProfile,
91    kProperty,
92    kResolver,
93    kRoute,
94    kRTNL,
95    kService,
96    kStorage,
97    kTask,
98    kVPN,
99    kWiFi,
100    kWiMax,
101    kNumScopes
102  };
103
104  // Returns a singleton of this class.
105  static ScopeLogger *GetInstance();
106
107  ~ScopeLogger();
108
109  // Returns true if logging is enabled for |scope| and |verbose_level|, i.e.
110  // scope_enable_[|scope|] is true and |verbose_level| <= |verbose_level_|
111  bool IsLogEnabled(Scope scope, int verbose_level) const;
112
113  // Returns a string comprising the names, separated by commas, of all scopes.
114  std::string GetAllScopeNames() const;
115
116  // Returns a string comprising the names, separated by plus signs, of all
117  // scopes that are enabled for logging.
118  std::string GetEnabledScopeNames() const;
119
120  // Enables/disables scopes as specified by |expression|.
121  //
122  // |expression| is a string comprising a sequence of scope names, each
123  // prefixed by a plus '+' or minus '-' sign. A scope prefixed by a plus
124  // sign is enabled for logging, whereas a scope prefixed by a minus sign
125  // is disabled for logging. Scopes that are not mentioned in |expression|
126  // remain the same state.
127  //
128  // To allow resetting the state of all scopes, an exception is made for the
129  // first scope name in the sequence, which may not be prefixed by any sign.
130  // That is considered as an implicit plus sign for that scope and also
131  // indicates that all scopes are first disabled before enabled by
132  // |expression|.
133  //
134  // If |expression| is an empty string, all scopes are disabled. Any unknown
135  // scope name found in |expression| is ignored.
136  void EnableScopesByName(const std::string &expression);
137
138  // Sets the verbose level for all scopes to |verbose_level|.
139  void set_verbose_level(int verbose_level) { verbose_level_ = verbose_level; }
140
141 private:
142  // Required for constructing LazyInstance<ScopeLogger>.
143  friend struct base::DefaultLazyInstanceTraits<ScopeLogger>;
144  friend class ScopeLoggerTest;
145  FRIEND_TEST(ScopeLoggerTest, GetEnabledScopeNames);
146  FRIEND_TEST(ScopeLoggerTest, SetScopeEnabled);
147  FRIEND_TEST(ScopeLoggerTest, SetVerboseLevel);
148
149  // Disables logging for all scopes.
150  void DisableAllScopes();
151
152  // Enables or disables logging for |scope|.
153  void SetScopeEnabled(Scope scope, bool enabled);
154
155  // Boolean values to indicate whether logging is enabled for each scope.
156  std::bitset<kNumScopes> scope_enabled_;
157
158  // Verbose level that is applied to all scopes.
159  int verbose_level_;
160
161  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeLogger);
162};
163
164}  // namespace shill
165
166#endif  // SHILL_SCOPE_LOGGER_H_
167