243 lines
6.7 KiB
C++
243 lines
6.7 KiB
C++
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
// Date 2014/09/22 11:57:43
|
|
|
|
#ifndef BVAR_STATUS_H
|
|
#define BVAR_STATUS_H
|
|
|
|
#include <string> // std::string
|
|
#include "butil/atomicops.h"
|
|
#include "butil/type_traits.h"
|
|
#include "butil/string_printf.h"
|
|
#include "butil/synchronization/lock.h"
|
|
#include "bvar/detail/is_atomical.h"
|
|
#include "bvar/variable.h"
|
|
#include "bvar/reducer.h"
|
|
|
|
namespace bvar {
|
|
|
|
// Display a rarely or periodically updated value.
|
|
// Usage:
|
|
// bvar::Status<int> foo_count1(17);
|
|
// foo_count1.expose("my_value");
|
|
//
|
|
// bvar::Status<int> foo_count2;
|
|
// foo_count2.set_value(17);
|
|
//
|
|
// bvar::Status<int> foo_count3("my_value", 17);
|
|
template <typename T, typename Enabler = void>
|
|
class Status : public Variable {
|
|
public:
|
|
Status() {}
|
|
Status(const T& value) : _value(value) {}
|
|
Status(const butil::StringPiece& name, const T& value) : _value(value) {
|
|
this->expose(name);
|
|
}
|
|
Status(const butil::StringPiece& prefix,
|
|
const butil::StringPiece& name, const T& value) : _value(value) {
|
|
this->expose_as(prefix, name);
|
|
}
|
|
// Calling hide() manually is a MUST required by Variable.
|
|
~Status() { hide(); }
|
|
|
|
void describe(std::ostream& os, bool /*quote_string*/) const override {
|
|
os << get_value();
|
|
}
|
|
|
|
#ifdef BAIDU_INTERNAL
|
|
void get_value(boost::any* value) const override {
|
|
butil::AutoLock guard(_lock);
|
|
*value = _value;
|
|
}
|
|
#endif
|
|
|
|
T get_value() const {
|
|
butil::AutoLock guard(_lock);
|
|
const T res = _value;
|
|
return res;
|
|
}
|
|
|
|
void set_value(const T& value) {
|
|
butil::AutoLock guard(_lock);
|
|
_value = value;
|
|
}
|
|
|
|
private:
|
|
T _value;
|
|
// We use lock rather than butil::atomic for generic values because
|
|
// butil::atomic requires the type to be memcpy-able (POD basically)
|
|
mutable butil::Lock _lock;
|
|
};
|
|
|
|
template <typename T>
|
|
class Status<T, typename butil::enable_if<detail::is_atomical<T>::value>::type>
|
|
: public Variable {
|
|
public:
|
|
struct PlaceHolderOp {
|
|
void operator()(T&, const T&) const {}
|
|
};
|
|
class SeriesSampler : public detail::Sampler {
|
|
public:
|
|
typedef typename butil::conditional<
|
|
true, detail::AddTo<T>, PlaceHolderOp>::type Op;
|
|
explicit SeriesSampler(Status* owner)
|
|
: _owner(owner), _series(Op()) {}
|
|
void take_sample() { _series.append(_owner->get_value()); }
|
|
void describe(std::ostream& os) { _series.describe(os, NULL); }
|
|
private:
|
|
Status* _owner;
|
|
detail::Series<T, Op> _series;
|
|
};
|
|
|
|
public:
|
|
Status() : _series_sampler(NULL) {}
|
|
Status(const T& value) : _value(value), _series_sampler(NULL) { }
|
|
Status(const butil::StringPiece& name, const T& value)
|
|
: _value(value), _series_sampler(NULL) {
|
|
this->expose(name);
|
|
}
|
|
Status(const butil::StringPiece& prefix,
|
|
const butil::StringPiece& name, const T& value)
|
|
: _value(value), _series_sampler(NULL) {
|
|
this->expose_as(prefix, name);
|
|
}
|
|
~Status() {
|
|
hide();
|
|
if (_series_sampler) {
|
|
_series_sampler->destroy();
|
|
_series_sampler = NULL;
|
|
}
|
|
}
|
|
|
|
void describe(std::ostream& os, bool /*quote_string*/) const override {
|
|
os << get_value();
|
|
}
|
|
|
|
#ifdef BAIDU_INTERNAL
|
|
void get_value(boost::any* value) const override {
|
|
*value = get_value();
|
|
}
|
|
#endif
|
|
|
|
T get_value() const {
|
|
return _value.load(butil::memory_order_relaxed);
|
|
}
|
|
|
|
void set_value(const T& value) {
|
|
_value.store(value, butil::memory_order_relaxed);
|
|
}
|
|
|
|
int describe_series(std::ostream& os, const SeriesOptions& options) const override {
|
|
if (_series_sampler == NULL) {
|
|
return 1;
|
|
}
|
|
if (!options.test_only) {
|
|
_series_sampler->describe(os);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
protected:
|
|
int expose_impl(const butil::StringPiece& prefix,
|
|
const butil::StringPiece& name,
|
|
DisplayFilter display_filter) override {
|
|
const int rc = Variable::expose_impl(prefix, name, display_filter);
|
|
if (rc == 0 &&
|
|
_series_sampler == NULL &&
|
|
FLAGS_save_series) {
|
|
_series_sampler = new SeriesSampler(this);
|
|
_series_sampler->schedule();
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
private:
|
|
butil::atomic<T> _value;
|
|
SeriesSampler* _series_sampler;
|
|
};
|
|
|
|
// Specialize for std::string, adding a printf-style set_value().
|
|
template <>
|
|
class Status<std::string, void> : public Variable {
|
|
public:
|
|
Status() {}
|
|
Status(const butil::StringPiece& name, const char* fmt, ...) {
|
|
if (fmt) {
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
butil::string_vprintf(&_value, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
expose(name);
|
|
}
|
|
Status(const butil::StringPiece& prefix,
|
|
const butil::StringPiece& name, const char* fmt, ...) {
|
|
if (fmt) {
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
butil::string_vprintf(&_value, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
expose_as(prefix, name);
|
|
}
|
|
|
|
~Status() { hide(); }
|
|
|
|
void describe(std::ostream& os, bool quote_string) const override {
|
|
if (quote_string) {
|
|
os << '"' << get_value() << '"';
|
|
} else {
|
|
os << get_value();
|
|
}
|
|
}
|
|
|
|
std::string get_value() const {
|
|
butil::AutoLock guard(_lock);
|
|
return _value;
|
|
}
|
|
|
|
#ifdef BAIDU_INTERNAL
|
|
void get_value(boost::any* value) const override {
|
|
*value = get_value();
|
|
}
|
|
#endif
|
|
|
|
void set_value(const char* fmt, ...) {
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
{
|
|
butil::AutoLock guard(_lock);
|
|
butil::string_vprintf(&_value, fmt, ap);
|
|
}
|
|
va_end(ap);
|
|
}
|
|
|
|
void set_value(const std::string& s) {
|
|
butil::AutoLock guard(_lock);
|
|
_value = s;
|
|
}
|
|
|
|
private:
|
|
std::string _value;
|
|
mutable butil::Lock _lock;
|
|
};
|
|
|
|
} // namespace bvar
|
|
|
|
#endif //BVAR_STATUS_H
|