Coverage Report

Created: 2025-08-05 06:45

/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