1 | // Licensed to the Apache Software Foundation (ASF) under one |
2 | // or more contributor license agreements. See the NOTICE file |
3 | // distributed with this work for additional information |
4 | // regarding copyright ownership. The ASF licenses this file |
5 | // to you under the Apache License, Version 2.0 (the |
6 | // "License"); you may not use this file except in compliance |
7 | // with the License. You may obtain a copy of the License at |
8 | // |
9 | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | // |
11 | // Unless required by applicable law or agreed to in writing, |
12 | // software distributed under the License is distributed on an |
13 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | // KIND, either express or implied. See the License for the |
15 | // specific language governing permissions and limitations |
16 | // under the License. |
17 | |
18 | // Date: 2014/09/22 11:57:43 |
19 | |
20 | #ifndef BVAR_VARIABLE_H |
21 | #define BVAR_VARIABLE_H |
22 | |
23 | #include <ostream> // std::ostream |
24 | #include <string> // std::string |
25 | #include <vector> // std::vector |
26 | #include <gflags/gflags_declare.h> |
27 | #include "butil/macros.h" // DISALLOW_COPY_AND_ASSIGN |
28 | #include "butil/strings/string_piece.h" // butil::StringPiece |
29 | |
30 | #ifdef BAIDU_INTERNAL |
31 | #include <boost/any.hpp> |
32 | #else |
33 | namespace boost { |
34 | class any; |
35 | } |
36 | #endif |
37 | |
38 | namespace bvar { |
39 | |
40 | DECLARE_bool(save_series); |
41 | |
42 | // Bitwise masks of displayable targets |
43 | enum DisplayFilter { |
44 | DISPLAY_ON_HTML = 1, |
45 | DISPLAY_ON_PLAIN_TEXT = 2, |
46 | DISPLAY_ON_ALL = 3, |
47 | }; |
48 | |
49 | // Implement this class to write variables into different places. |
50 | // If dump() returns false, Variable::dump_exposed() stops and returns -1. |
51 | class Dumper { |
52 | public: |
53 | virtual ~Dumper() { } |
54 | virtual bool dump(const std::string& name, |
55 | const butil::StringPiece& description) = 0; |
56 | }; |
57 | |
58 | // Options for Variable::dump_exposed(). |
59 | struct DumpOptions { |
60 | // Constructed with default options. |
61 | DumpOptions(); |
62 | |
63 | // If this is true, string-type values will be quoted. |
64 | bool quote_string; |
65 | |
66 | // The ? in wildcards. Wildcards in URL need to use another character |
67 | // because ? is reserved. |
68 | char question_mark; |
69 | |
70 | // Dump variables with matched display_filter |
71 | DisplayFilter display_filter; |
72 | |
73 | // Name matched by these wildcards (or exact names) are kept. |
74 | std::string white_wildcards; |
75 | |
76 | // Name matched by these wildcards (or exact names) are skipped. |
77 | std::string black_wildcards; |
78 | }; |
79 | |
80 | struct SeriesOptions { |
81 | SeriesOptions() : fixed_length(true), test_only(false) {} |
82 | |
83 | bool fixed_length; // useless now |
84 | bool test_only; |
85 | }; |
86 | |
87 | // Base class of all bvar. |
88 | // |
89 | // About thread-safety: |
90 | // bvar is thread-compatible: |
91 | // Namely you can create/destroy/expose/hide or do whatever you want to |
92 | // different bvar simultaneously in different threads. |
93 | // bvar is NOT thread-safe: |
94 | // You should not operate one bvar from different threads simultaneously. |
95 | // If you need to, protect the ops with locks. Similarly with ordinary |
96 | // variables, const methods are thread-safe, namely you can call |
97 | // describe()/get_description()/get_value() etc from diferent threads |
98 | // safely (provided that there's no non-const methods going on). |
99 | class Variable { |
100 | public: |
101 | Variable() {} |
102 | virtual ~Variable(); |
103 | |
104 | // Implement this method to print the variable into ostream. |
105 | virtual void describe(std::ostream&, bool quote_string) const = 0; |
106 | |
107 | // string form of describe(). |
108 | std::string get_description() const; |
109 | |
110 | #ifdef BAIDU_INTERNAL |
111 | // Get value. |
112 | // If subclass does not override this method, the value is the description |
113 | // and the type is std::string. |
114 | virtual void get_value(boost::any* value) const; |
115 | #endif |
116 | |
117 | // Describe saved series as a json-string into the stream. |
118 | // The output will be ploted by flot.js |
119 | // Returns 0 on success, 1 otherwise(this variable does not save series). |
120 | virtual int describe_series(std::ostream&, const SeriesOptions&) const |
121 | { return 1; } |
122 | |
123 | // Expose this variable globally so that it's counted in following |
124 | // functions: |
125 | // list_exposed |
126 | // count_exposed |
127 | // describe_exposed |
128 | // find_exposed |
129 | // Return 0 on success, -1 otherwise. |
130 | int expose(const butil::StringPiece& name, |
131 | DisplayFilter display_filter = DISPLAY_ON_ALL) { |
132 | return expose_impl(butil::StringPiece(), name, display_filter); |
133 | } |
134 | |
135 | // Expose this variable with a prefix. |
136 | // Example: |
137 | // namespace foo { |
138 | // namespace bar { |
139 | // class ApplePie { |
140 | // ApplePie() { |
141 | // // foo_bar_apple_pie_error |
142 | // _error.expose_as("foo_bar_apple_pie", "error"); |
143 | // } |
144 | // private: |
145 | // bvar::Adder<int> _error; |
146 | // }; |
147 | // } // foo |
148 | // } // bar |
149 | // Returns 0 on success, -1 otherwise. |
150 | int expose_as(const butil::StringPiece& prefix, |
151 | const butil::StringPiece& name, |
152 | DisplayFilter display_filter = DISPLAY_ON_ALL) { |
153 | return expose_impl(prefix, name, display_filter); |
154 | } |
155 | |
156 | // Hide this variable so that it's not counted in *_exposed functions. |
157 | // Returns false if this variable is already hidden. |
158 | // CAUTION!! Subclasses must call hide() manually to avoid displaying |
159 | // a variable that is just destructing. |
160 | bool hide(); |
161 | |
162 | // Get exposed name. If this variable is not exposed, the name is empty. |
163 | const std::string& name() const { return _name; } |
164 | |
165 | // ==================================================================== |
166 | |
167 | // Put names of all exposed variables into `names'. |
168 | // If you want to print all variables, you have to go through `names' |
169 | // and call `describe_exposed' on each name. This prevents an iteration |
170 | // from taking the lock too long. |
171 | static void list_exposed(std::vector<std::string>* names, |
172 | DisplayFilter = DISPLAY_ON_ALL); |
173 | |
174 | // Get number of exposed variables. |
175 | static size_t count_exposed(); |
176 | |
177 | // Find an exposed variable by `name' and put its description into `os'. |
178 | // Returns 0 on found, -1 otherwise. |
179 | static int describe_exposed(const std::string& name, |
180 | std::ostream& os, |
181 | bool quote_string = false, |
182 | DisplayFilter = DISPLAY_ON_ALL); |
183 | // String form. Returns empty string when not found. |
184 | static std::string describe_exposed(const std::string& name, |
185 | bool quote_string = false, |
186 | DisplayFilter = DISPLAY_ON_ALL); |
187 | |
188 | // Describe saved series of variable `name' as a json-string into `os'. |
189 | // The output will be ploted by flot.js |
190 | // Returns 0 on success, 1 when the variable does not save series, -1 |
191 | // otherwise (no variable named so). |
192 | static int describe_series_exposed(const std::string& name, |
193 | std::ostream&, |
194 | const SeriesOptions&); |
195 | |
196 | #ifdef BAIDU_INTERNAL |
197 | // Find an exposed variable by `name' and put its value into `value'. |
198 | // Returns 0 on found, -1 otherwise. |
199 | static int get_exposed(const std::string& name, boost::any* value); |
200 | #endif |
201 | |
202 | // Find all exposed variables matching `white_wildcards' but |
203 | // `black_wildcards' and send them to `dumper'. |
204 | // Use default options when `options' is NULL. |
205 | // Return number of dumped variables, -1 on error. |
206 | static int dump_exposed(Dumper* dumper, const DumpOptions* options); |
207 | |
208 | protected: |
209 | virtual int expose_impl(const butil::StringPiece& prefix, |
210 | const butil::StringPiece& name, |
211 | DisplayFilter display_filter); |
212 | |
213 | private: |
214 | std::string _name; |
215 | |
216 | // bvar uses TLS, thus copying/assignment need to copy TLS stuff as well, |
217 | // which is heavy. We disable copying/assignment now. |
218 | DISALLOW_COPY_AND_ASSIGN(Variable); |
219 | }; |
220 | |
221 | // Make name only use lowercased alphabets / digits / underscores, and append |
222 | // the result to `out'. |
223 | // Examples: |
224 | // foo-inl.h -> foo_inl_h |
225 | // foo::bar::Apple -> foo_bar_apple |
226 | // Car_Rot -> car_rot |
227 | // FooBar -> foo_bar |
228 | // RPCTest -> rpctest |
229 | // HELLO -> hello |
230 | void to_underscored_name(std::string* out, const butil::StringPiece& name); |
231 | |
232 | } // namespace bvar |
233 | |
234 | // Make variables printable. |
235 | namespace std { |
236 | |
237 | inline ostream& operator<<(ostream &os, const ::bvar::Variable &var) { |
238 | var.describe(os, false); |
239 | return os; |
240 | } |
241 | |
242 | } // namespace std |
243 | |
244 | #endif // BVAR_VARIABLE_H |
245 | |