/src/brpc/src/bvar/status.h
Line | Count | Source (jump to first uncovered line) |
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_STATUS_H |
21 | | #define BVAR_STATUS_H |
22 | | |
23 | | #include <string> // std::string |
24 | | #include "butil/atomicops.h" |
25 | | #include "butil/type_traits.h" |
26 | | #include "butil/string_printf.h" |
27 | | #include "butil/synchronization/lock.h" |
28 | | #include "bvar/detail/is_atomical.h" |
29 | | #include "bvar/variable.h" |
30 | | #include "bvar/reducer.h" |
31 | | |
32 | | namespace bvar { |
33 | | |
34 | | // Display a rarely or periodically updated value. |
35 | | // Usage: |
36 | | // bvar::Status<int> foo_count1(17); |
37 | | // foo_count1.expose("my_value"); |
38 | | // |
39 | | // bvar::Status<int> foo_count2; |
40 | | // foo_count2.set_value(17); |
41 | | // |
42 | | // bvar::Status<int> foo_count3("my_value", 17); |
43 | | template <typename T, typename Enabler = void> |
44 | | class Status : public Variable { |
45 | | public: |
46 | | Status() {} |
47 | | Status(const T& value) : _value(value) {} |
48 | | Status(const butil::StringPiece& name, const T& value) : _value(value) { |
49 | | this->expose(name); |
50 | | } |
51 | | Status(const butil::StringPiece& prefix, |
52 | | const butil::StringPiece& name, const T& value) : _value(value) { |
53 | | this->expose_as(prefix, name); |
54 | | } |
55 | | // Calling hide() manually is a MUST required by Variable. |
56 | | ~Status() { hide(); } |
57 | | |
58 | | void describe(std::ostream& os, bool /*quote_string*/) const override { |
59 | | os << get_value(); |
60 | | } |
61 | | |
62 | | #ifdef BAIDU_INTERNAL |
63 | | void get_value(boost::any* value) const override { |
64 | | butil::AutoLock guard(_lock); |
65 | | *value = _value; |
66 | | } |
67 | | #endif |
68 | | |
69 | | T get_value() const { |
70 | | butil::AutoLock guard(_lock); |
71 | | const T res = _value; |
72 | | return res; |
73 | | } |
74 | | |
75 | | void set_value(const T& value) { |
76 | | butil::AutoLock guard(_lock); |
77 | | _value = value; |
78 | | } |
79 | | |
80 | | private: |
81 | | T _value; |
82 | | // We use lock rather than butil::atomic for generic values because |
83 | | // butil::atomic requires the type to be memcpy-able (POD basically) |
84 | | mutable butil::Lock _lock; |
85 | | }; |
86 | | |
87 | | template <typename T> |
88 | | class Status<T, typename butil::enable_if<detail::is_atomical<T>::value>::type> |
89 | | : public Variable { |
90 | | public: |
91 | | struct PlaceHolderOp { |
92 | | void operator()(T&, const T&) const {} |
93 | | }; |
94 | | class SeriesSampler : public detail::Sampler { |
95 | | public: |
96 | | typedef typename butil::conditional< |
97 | | true, detail::AddTo<T>, PlaceHolderOp>::type Op; |
98 | | explicit SeriesSampler(Status* owner) |
99 | | : _owner(owner), _series(Op()) {} |
100 | | void take_sample() { _series.append(_owner->get_value()); } |
101 | | void describe(std::ostream& os) { _series.describe(os, NULL); } |
102 | | private: |
103 | | Status* _owner; |
104 | | detail::Series<T, Op> _series; |
105 | | }; |
106 | | |
107 | | public: |
108 | | Status() : _series_sampler(NULL) {} |
109 | | Status(const T& value) : _value(value), _series_sampler(NULL) { } |
110 | | Status(const butil::StringPiece& name, const T& value) |
111 | | : _value(value), _series_sampler(NULL) { |
112 | | this->expose(name); |
113 | | } |
114 | | Status(const butil::StringPiece& prefix, |
115 | | const butil::StringPiece& name, const T& value) |
116 | | : _value(value), _series_sampler(NULL) { |
117 | | this->expose_as(prefix, name); |
118 | | } |
119 | | ~Status() { |
120 | | hide(); |
121 | | if (_series_sampler) { |
122 | | _series_sampler->destroy(); |
123 | | _series_sampler = NULL; |
124 | | } |
125 | | } |
126 | | |
127 | | void describe(std::ostream& os, bool /*quote_string*/) const override { |
128 | | os << get_value(); |
129 | | } |
130 | | |
131 | | #ifdef BAIDU_INTERNAL |
132 | | void get_value(boost::any* value) const override { |
133 | | *value = get_value(); |
134 | | } |
135 | | #endif |
136 | | |
137 | | T get_value() const { |
138 | | return _value.load(butil::memory_order_relaxed); |
139 | | } |
140 | | |
141 | | void set_value(const T& value) { |
142 | | _value.store(value, butil::memory_order_relaxed); |
143 | | } |
144 | | |
145 | | int describe_series(std::ostream& os, const SeriesOptions& options) const override { |
146 | | if (_series_sampler == NULL) { |
147 | | return 1; |
148 | | } |
149 | | if (!options.test_only) { |
150 | | _series_sampler->describe(os); |
151 | | } |
152 | | return 0; |
153 | | } |
154 | | |
155 | | protected: |
156 | | int expose_impl(const butil::StringPiece& prefix, |
157 | | const butil::StringPiece& name, |
158 | | DisplayFilter display_filter) override { |
159 | | const int rc = Variable::expose_impl(prefix, name, display_filter); |
160 | | if (rc == 0 && |
161 | | _series_sampler == NULL && |
162 | | FLAGS_save_series) { |
163 | | _series_sampler = new SeriesSampler(this); |
164 | | _series_sampler->schedule(); |
165 | | } |
166 | | return rc; |
167 | | } |
168 | | |
169 | | private: |
170 | | butil::atomic<T> _value; |
171 | | SeriesSampler* _series_sampler; |
172 | | }; |
173 | | |
174 | | // Specialize for std::string, adding a printf-style set_value(). |
175 | | template <> |
176 | | class Status<std::string, void> : public Variable { |
177 | | public: |
178 | 0 | Status() {} |
179 | 0 | Status(const butil::StringPiece& name, const char* fmt, ...) { |
180 | 0 | if (fmt) { |
181 | 0 | va_list ap; |
182 | 0 | va_start(ap, fmt); |
183 | 0 | butil::string_vprintf(&_value, fmt, ap); |
184 | 0 | va_end(ap); |
185 | 0 | } |
186 | 0 | expose(name); |
187 | 0 | } |
188 | | Status(const butil::StringPiece& prefix, |
189 | 0 | const butil::StringPiece& name, const char* fmt, ...) { |
190 | 0 | if (fmt) { |
191 | 0 | va_list ap; |
192 | 0 | va_start(ap, fmt); |
193 | 0 | butil::string_vprintf(&_value, fmt, ap); |
194 | 0 | va_end(ap); |
195 | 0 | } |
196 | 0 | expose_as(prefix, name); |
197 | 0 | } |
198 | | |
199 | 0 | ~Status() { hide(); } |
200 | | |
201 | 0 | void describe(std::ostream& os, bool quote_string) const override { |
202 | 0 | if (quote_string) { |
203 | 0 | os << '"' << get_value() << '"'; |
204 | 0 | } else { |
205 | 0 | os << get_value(); |
206 | 0 | } |
207 | 0 | } |
208 | | |
209 | 0 | std::string get_value() const { |
210 | 0 | butil::AutoLock guard(_lock); |
211 | 0 | return _value; |
212 | 0 | } |
213 | | |
214 | | #ifdef BAIDU_INTERNAL |
215 | | void get_value(boost::any* value) const override { |
216 | | *value = get_value(); |
217 | | } |
218 | | #endif |
219 | | |
220 | 0 | void set_value(const char* fmt, ...) { |
221 | 0 | va_list ap; |
222 | 0 | va_start(ap, fmt); |
223 | 0 | { |
224 | 0 | butil::AutoLock guard(_lock); |
225 | 0 | butil::string_vprintf(&_value, fmt, ap); |
226 | 0 | } |
227 | 0 | va_end(ap); |
228 | 0 | } |
229 | | |
230 | 0 | void set_value(const std::string& s) { |
231 | 0 | butil::AutoLock guard(_lock); |
232 | 0 | _value = s; |
233 | 0 | } |
234 | | |
235 | | private: |
236 | | std::string _value; |
237 | | mutable butil::Lock _lock; |
238 | | }; |
239 | | |
240 | | } // namespace bvar |
241 | | |
242 | | #endif //BVAR_STATUS_H |