// Copyright (c) 2014 Baidu, Inc. // // Licensed 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. // Author: Ge,Jun (gejun@baidu.com) // Date: 2014/09/22 11:57:43 #ifndef BVAR_VARIABLE_H #define BVAR_VARIABLE_H #include <ostream> // std::ostream #include <string> // std::string #include <vector> // std::vector #include <gflags/gflags_declare.h> #include "butil/macros.h" // DISALLOW_COPY_AND_ASSIGN #include "butil/strings/string_piece.h" // butil::StringPiece #ifdef BAIDU_INTERNAL #include <boost/any.hpp> #else namespace boost { class any; } #endif namespace bvar { DECLARE_bool(save_series); // Bitwise masks of displayable targets enum DisplayFilter { DISPLAY_ON_HTML = 1, DISPLAY_ON_PLAIN_TEXT = 2, DISPLAY_ON_ALL = 3, }; // Implement this class to write variables into different places. // If dump() returns false, Variable::dump_exposed() stops and returns -1. class Dumper { public: virtual ~Dumper() { } virtual bool dump(const std::string& name, const butil::StringPiece& description) = 0; }; // Options for Variable::dump_exposed(). struct DumpOptions { // Constructed with default options. DumpOptions(); // If this is true, string-type values will be quoted. bool quote_string; // The ? in wildcards. Wildcards in URL need to use another character // because ? is reserved. char question_mark; // Dump variables with matched display_filter DisplayFilter display_filter; // Name matched by these wildcards (or exact names) are kept. std::string white_wildcards; // Name matched by these wildcards (or exact names) are skipped. std::string black_wildcards; }; struct SeriesOptions { SeriesOptions() : fixed_length(true), test_only(false) {} bool fixed_length; // useless now bool test_only; }; // Base class of all bvar. // // About thread-safety: // bvar is thread-compatible: // Namely you can create/destroy/expose/hide or do whatever you want to // different bvar simultaneously in different threads. // bvar is NOT thread-safe: // You should not operate one bvar from different threads simultaneously. // If you need to, protect the ops with locks. Similarly with ordinary // variables, const methods are thread-safe, namely you can call // describe()/get_description()/get_value() etc from diferent threads // safely (provided that there's no non-const methods going on). class Variable { public: Variable() {} virtual ~Variable(); // Implement this method to print the variable into ostream. virtual void describe(std::ostream&, bool quote_string) const = 0; // string form of describe(). std::string get_description() const; #ifdef BAIDU_INTERNAL // Get value. // If subclass does not override this method, the value is the description // and the type is std::string. virtual void get_value(boost::any* value) const; #endif // Describe saved series as a json-string into the stream. // The output will be ploted by flot.js // Returns 0 on success, 1 otherwise(this variable does not save series). virtual int describe_series(std::ostream&, const SeriesOptions&) const { return 1; } // Expose this variable globally so that it's counted in following // functions: // list_exposed // count_exposed // describe_exposed // find_exposed // Return 0 on success, -1 otherwise. int expose(const butil::StringPiece& name, DisplayFilter display_filter = DISPLAY_ON_ALL) { return expose_impl(butil::StringPiece(), name, display_filter); } // Expose this variable with a prefix. // Example: // namespace foo { // namespace bar { // class ApplePie { // ApplePie() { // // foo_bar_apple_pie_error // _error.expose_as("foo_bar_apple_pie", "error"); // } // private: // bvar::Adder<int> _error; // }; // } // foo // } // bar // Returns 0 on success, -1 otherwise. int expose_as(const butil::StringPiece& prefix, const butil::StringPiece& name, DisplayFilter display_filter = DISPLAY_ON_ALL) { return expose_impl(prefix, name, display_filter); } // Hide this variable so that it's not counted in *_exposed functions. // Returns false if this variable is already hidden. // CAUTION!! Subclasses must call hide() manually to avoid displaying // a variable that is just destructing. bool hide(); // Get exposed name. If this variable is not exposed, the name is empty. const std::string& name() const { return _name; } // ==================================================================== // Put names of all exposed variables into `names'. // If you want to print all variables, you have to go through `names' // and call `describe_exposed' on each name. This prevents an iteration // from taking the lock too long. static void list_exposed(std::vector<std::string>* names, DisplayFilter = DISPLAY_ON_ALL); // Get number of exposed variables. static size_t count_exposed(); // Find an exposed variable by `name' and put its description into `os'. // Returns 0 on found, -1 otherwise. static int describe_exposed(const std::string& name, std::ostream& os, bool quote_string = false, DisplayFilter = DISPLAY_ON_ALL); // String form. Returns empty string when not found. static std::string describe_exposed(const std::string& name, bool quote_string = false, DisplayFilter = DISPLAY_ON_ALL); // Describe saved series of variable `name' as a json-string into `os'. // The output will be ploted by flot.js // Returns 0 on success, 1 when the variable does not save series, -1 // otherwise (no variable named so). static int describe_series_exposed(const std::string& name, std::ostream&, const SeriesOptions&); #ifdef BAIDU_INTERNAL // Find an exposed variable by `name' and put its value into `value'. // Returns 0 on found, -1 otherwise. static int get_exposed(const std::string& name, boost::any* value); #endif // Find all exposed variables matching `white_wildcards' but // `black_wildcards' and send them to `dumper'. // Use default options when `options' is NULL. // Return number of dumped variables, -1 on error. static int dump_exposed(Dumper* dumper, const DumpOptions* options); protected: virtual int expose_impl(const butil::StringPiece& prefix, const butil::StringPiece& name, DisplayFilter display_filter); private: std::string _name; // bvar uses TLS, thus copying/assignment need to copy TLS stuff as well, // which is heavy. We disable copying/assignment now. DISALLOW_COPY_AND_ASSIGN(Variable); }; // Make name only use lowercased alphabets / digits / underscores, and append // the result to `out'. // Examples: // foo-inl.h -> foo_inl_h // foo::bar::Apple -> foo_bar_apple // Car_Rot -> car_rot // FooBar -> foo_bar // RPCTest -> rpctest // HELLO -> hello void to_underscored_name(std::string* out, const butil::StringPiece& name); } // namespace bvar // Make variables printable. namespace std { inline ostream& operator<<(ostream &os, const ::bvar::Variable &var) { var.describe(os, false); return os; } } // namespace std #endif // BVAR_VARIABLE_H