// balm_metricformat.h -*-C++-*- // ---------------------------------------------------------------------------- // NOTICE // // This component is not up to date with current BDE coding standards, and // should not be used as an example for new development. // ---------------------------------------------------------------------------- #ifndef INCLUDED_BALM_METRICFORMAT #define INCLUDED_BALM_METRICFORMAT #include <bsls_ident.h> BSLS_IDENT("$Id: balm_metricformat.h,v 1.8 2008/04/16 20:00:49 hversche Exp $") //@PURPOSE: Provide a formatting specification for a metric. // //@CLASSES: // balm::MetricFormat: description for how to format a metric // balm::MetricFormatSpec: specification for formatting an individual aggregate // //@SEE_ALSO: balm_metricdescription // //@DESCRIPTION: This component provides classes for describing the formatting // for a metric. For each published aggregate type (e.g., count, total, min, // max, etc.), a 'balm::MetricFormat' object holds a 'balm::MetricFormatSpec' // object describing how values of that aggregate may be formatted. // 'balm::MetricFormat' provides the 'setFormatSpec' method to set the format // specification for a particular publication type, and the 'formatSpec' method // to retrieve the format specification for a publication type (or null if no // format specification has been provided for the indicated publication type). // // 'balm::MetricFormatSpec' is an unconstrained pure-attribute class that // represents the specification for formatting a particular publication type of // a metric (e.g., total, count, min, max, etc.). The attributes held by // 'balm::MetricFormatSpec' are given in the following table: //.. // Attribute Type Description Default // --------- ------------ ---------------------------------- ------- // scale float multiplier for scaling value 1.0 // format const char * 'printf'-style format for 'double' "%f" //.. // The string provided must be a 'printf'-style format valid for formatting a // single 'double' value. // // Note that 'balm::Publisher' implementations determine how to use the format // information associated with a metric (i.e., there is no guarantee that every // publisher will format a metric using its 'balm::MetricFormat'). // ///Alternative Systems for Telemetry ///--------------------------------- // Bloomberg software may alternatively use the GUTS telemetry API, which is // integrated into Bloomberg infrastructure. // ///Thread Safety ///------------- // 'balm::MetricFormat' is *const* *thread-safe*, meaning that accessors may be // invoked concurrently from different threads, but it is not safe to access or // modify a 'balm::MetricFormat' in one thread while another thread modifies // the same object. // // 'balm::MetricFormatSpec' is *const* *thread-safe*, meaning that accessors // may be invoked concurrently from different threads, but it is not safe to // access or modify a 'balm::MetricFormatSpec' in one thread while another // thread modifies the same object. // ///Usage ///----- // The following example demonstrates how to create and configure a // 'balm::MetricFormat'. Note that clients of the 'balm' package can set the // format for a metric through 'balm_configurationutil' or // 'balm_metricregistry'. // // We start by creating a 'balm::MetricFormat' object: //.. // bslma::Allocator *allocator = bslma::Default::allocator(0); // balm::MetricFormat format(allocator); //.. // Next we specify that average values should only be printed to two decimal // places: //.. // format.setFormatSpec(balm::PublicationType::e_AVG, // balm::MetricFormatSpec(1.0, "%.2f")); //.. // Next we specify that rate values should be formatted as a percentage -- // i.e., multiplied by 100, and then displayed with a "%" character: //.. // format.setFormatSpec(balm::PublicationType::e_RATE, // balm::MetricFormatSpec(100.0, "%.2f%%")); //.. // We can verify that the correct format specifications have been set: //.. // assert(balm::MetricFormatSpec(1.0, "%.2f") == // *format.formatSpec(balm::PublicationType::e_AVG)); // assert(balm::MetricFormatSpec(100.0, "%.2f%%") == // *format.formatSpec(balm::PublicationType::e_RATE)); // assert(0 == format.formatSpec(balm::PublicationType::e_TOTAL)); //.. // We can use the 'balm::MetricFormatSpec::formatValue' utility function to // format the value 0.055 to the console. Note however, that there is no // guarantee that every implementation of 'balm::Publisher' will format metrics // in this way. //.. // balm::MetricFormatSpec::formatValue( // bsl::cout, .055, *format.formatSpec(balm::PublicationType::e_AVG)); // bsl::cout << bsl::endl; // balm::MetricFormatSpec::formatValue( // bsl::cout, .055, *format.formatSpec(balm::PublicationType::e_RATE)); // bsl::cout << bsl::endl; //.. // The resulting console output will be: //.. // 0.06 // 5.50% //.. #include <balscm_version.h> #include <balm_publicationtype.h> #include <bdlb_nullablevalue.h> #include <bslmf_nestedtraitdeclaration.h> #include <bsl_iosfwd.h> #include <bsl_vector.h> #include <bsl_cstring.h> // for 'bsl::strcmp' namespace BloombergLP { namespace balm { // ====================== // class MetricFormatSpec // ====================== class MetricFormatSpec { // This class provides a value-semantic representation of the formatting // specification for a metric aggregate value. The 'scale()' is a // multiplier used to scale the numeric value. The 'format()' is a // 'printf'-style format string suitable for formatting a single // floating-point value. // DATA float d_scale; // multiplier for scaling published values const char *d_format; // 'printf'-style format string for formatting a // single floating-point numeric value // PRIVATE CONSTANTS static const char *k_DEFAULT_FORMAT; // default format ("%f") public: // CLASS METHODS static bsl::ostream& formatValue(bsl::ostream& stream, double value, const MetricFormatSpec& format); // Write the specified 'value' to the specified 'stream' using the // specified 'format', and return a reference to the modifiable // 'stream'. // CREATORS MetricFormatSpec(); // Create a metric format spec having default values for 'scale' and // 'format'. The default value for 'scale' is 1.0 and the default // value for 'format' is "%f". MetricFormatSpec(float scale, const char *format); // Create a metric format spec having the specified 'scale' and // 'format'. The 'scale' indicates the multiplier that may be used // when formatting values, and 'format' must be a 'printf'-style format // string for formatting a single floating-point value. The behavior // is undefined unless 'format' is null-terminated, contains a // 'printf'-style format string valid for a single floating-point // value, and remains valid and unmodified for the lifetime of this // object. MetricFormatSpec(const MetricFormatSpec& original); // Create a metric format spec having the same value as the specified // 'original' format spec. The behavior is undefined unless // 'original.format()' remains valid and unmodified for the lifetime of // this object. // ~MetricFormatSpec(); // Destroy this format spec. Note that this trivial destructor is // generated by the compiler. // MANIPULATORS MetricFormatSpec& operator=(const MetricFormatSpec& rhs); // Assign to this format spec the value of the specified 'rhs' format // spec, and return a reference to this modifiable format spec. void setScale(float scale); // Set, to the specified 'scale', the scale multiplier that may be // applied when formatting values. void setFormat(const char *format); // Set, to the specified 'format', the 'printf'-style formatting string // that may be applied when formatting values. The behavior is // undefined unless 'format' is null-terminated, contains a // 'printf'-style format string valid for a single floating-point // value, and remains valid and unmodified for the lifetime of this // object. // ACCESSORS float scale() const; // Return the floating-point multiplier value that may be applied to // scale formatted values. const char *format() const; // Return the address of the null-terminated string containing the // 'printf'-style format that may be used to format values. bsl::ostream& print(bsl::ostream& stream, int level = 0, int spacesPerLevel = -1) const; // Format this object to the specified output 'stream' at the (absolute // value of) the optionally specified indentation 'level' and return a // reference to 'stream'. If 'level' is specified, optionally specify // 'spacesPerLevel', the number of spaces per indentation level for // this and all of its nested objects. If 'level' is negative, // suppress indentation of the first line. If 'spacesPerLevel' is // negative, format the entire output on one line, suppressing all but // the initial indentation (as governed by 'level'). If 'stream' is // not valid on entry, this operation has no effect. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // FREE OPERATORS inline bool operator==(const MetricFormatSpec& lhs, const MetricFormatSpec& rhs); // Return 'true' if the specified 'lhs' and 'rhs' metric format specs have // the same value, and 'false' otherwise. Two format specs have the same // value if they have the same values for their 'scale' and 'format' // attributes, respectively. inline bool operator!=(const MetricFormatSpec& lhs, const MetricFormatSpec& rhs); // Return 'true' if the specified 'lhs' and 'rhs' metric format specs do // not have the same value, and 'false' otherwise. Two format specs do // not have same value if they differ in their respective values for // 'scale' or 'format' attributes. inline bsl::ostream& operator<<(bsl::ostream& stream, const MetricFormatSpec& rhs); // Write a formatted description of the specified 'rhs' format spec to the // specified 'stream', and return a reference to the modifiable 'stream'. // ================== // class MetricFormat // ================== class MetricFormat { // This class provides a value-semantic description for the formatting of a // metric. For each published aggregate type of a metric (e.g., count, // total, min, max, etc.), a 'MetricFormat' contains a 'MetricFormatSpec' // object describing how to format values of that aggregate, or null if no // formatting information is supplied. 'Metricformat' provides the // 'setFormatSpec' method to set the format spec for a publication type, // and the 'formatSpec' method to retrieve the format spec for a // publication type (or 0 if no format spec has been provided for the // indicated publication type). Note that the types of published // aggregates explicitly provided by the 'balm' package are defined in the // 'PublicationType' enumeration. // TYPES typedef bdlb::NullableValue<MetricFormatSpec> AggregateFormatSpec; // DATA bsl::vector<AggregateFormatSpec> d_formatSpecs; // array of length 0, or of length // 'PublicationType::k_LENGTH', holding a // mapping of the publication type to the // (possibly null) formatting options for that // type // FRIENDS friend bool operator==(const MetricFormat& lhs, const MetricFormat& rhs); public: // PUBLIC TRAITS BSLMF_NESTED_TRAIT_DECLARATION(MetricFormat, bslma::UsesBslmaAllocator); // CREATORS MetricFormat(bslma::Allocator *basicAllocator = 0); // Create an empty metric format object. Optionally specify a // 'basicAllocator' used to supply memory. If 'basicAllocator' is 0, // the currently installed default allocator is used. Note that // 'formatSpec' will return 0 for all supplied publication types. MetricFormat(const MetricFormat& original, bslma::Allocator *basicAllocator = 0); // Create a metric format object having the same value as the specified // 'original' format. Optionally specify a 'basicAllocator' used to // supply memory. If 'basicAllocator' is 0, the currently installed // default allocator is used. // ~MetricFormat(); // Destroy this metric format object. Note that this trivial // destructor is generated by the compiler. // MANIPULATORS MetricFormat& operator=(const MetricFormat& rhs); // Assign to this metric format object the value of the specified 'rhs' // metric format, and return a reference to this modifiable metric // format. void setFormatSpec(PublicationType::Value publicationType, const MetricFormatSpec& formatSpec); // Set the format spec for the metric aggregate indicated by the // specified 'publicationType' to the specified 'formatSpec'. void clearFormatSpecs(); // Remove all format specs from this metric format object and put this // object into its default-constructed state. After this method // returns, 'formatSpec' will return 0 for all supplied publication // types. void clearFormatSpec(PublicationType::Value publicationType); // Remove the format spec for the specified 'publicationType' from this // metric format object. After this methods returns, // 'formatSpec(publicationType)' will return 0. // ACCESSORS const MetricFormatSpec *formatSpec( PublicationType::Value publicationType) const; // Return the address of the non-modifiable format spec for the // specified 'publicationType', or 0 if no format spec has been // provided for 'publicationType'. bsl::ostream& print(bsl::ostream& stream, int level = 0, int spacesPerLevel = 4) const; // Format this object to the specified output 'stream' at the (absolute // value of) the optionally specified indentation 'level' and return a // reference to 'stream'. If 'level' is specified, optionally specify // 'spacesPerLevel', the number of spaces per indentation level for // this and all of its nested objects. If 'level' is negative, // suppress indentation of the first line. If 'spacesPerLevel' is // negative, format the entire output on one line, suppressing all but // the initial indentation (as governed by 'level'). If 'stream' is // not valid on entry, this operation has no effect. }; // FREE OPERATORS inline bool operator==(const MetricFormat& lhs, const MetricFormat& rhs); // Return 'true' if the specified 'lhs' and 'rhs' metric formats have the // same value, and 'false' otherwise. Two metric formats have the same // value if they have the same value for 'formatSpec' for each of the // enumerated publication types. inline bool operator!=(const MetricFormat& lhs, const MetricFormat& rhs); // Return 'true' if the specified 'lhs' and 'rhs' metric formats do not // have the same value, and 'false' otherwise. Two metric formats do not // have same value if they differ in their 'formatSpec' for any of the // enumerated publication types. inline bsl::ostream& operator<<(bsl::ostream& stream, const MetricFormat& rhs); // Write a formatted description of the specified 'rhs' metric format to // the specified 'stream', and return a reference to the modifiable // 'stream'. // ============================================================================ // INLINE FUNCTION DEFINITIONS // ============================================================================ // ---------------------- // class MetricFormatSpec // ---------------------- // CREATORS inline MetricFormatSpec::MetricFormatSpec() : d_scale(1.0f) , d_format(k_DEFAULT_FORMAT) { } inline MetricFormatSpec::MetricFormatSpec(float scale, const char *format) : d_scale(scale) , d_format(format) { } inline MetricFormatSpec::MetricFormatSpec( const MetricFormatSpec& original) : d_scale(original.d_scale) , d_format(original.d_format) { } // MANIPULATORS inline MetricFormatSpec& MetricFormatSpec::operator=( const MetricFormatSpec& rhs) { d_scale = rhs.d_scale; d_format = rhs.d_format; return *this; } inline void MetricFormatSpec::setScale(float scale) { d_scale = scale; } inline void MetricFormatSpec::setFormat(const char *format) { d_format = format; } // ACCESSORS inline float MetricFormatSpec::scale() const { return d_scale; } inline const char *MetricFormatSpec::format() const { return d_format; } } // close package namespace // FREE OPERATORS inline bool balm::operator==(const MetricFormatSpec& lhs, const MetricFormatSpec& rhs) { return lhs.scale() == rhs.scale() && 0 == bsl::strcmp(lhs.format(), rhs.format()); } inline bool balm::operator!=(const MetricFormatSpec& lhs, const MetricFormatSpec& rhs) { return !(lhs == rhs); } inline bsl::ostream& balm::operator<<(bsl::ostream& stream, const MetricFormatSpec& rhs) { return rhs.print(stream, 0, -1); } namespace balm { // ------------------ // class MetricFormat // ------------------ // CREATORS inline MetricFormat::MetricFormat(bslma::Allocator *basicAllocator) : d_formatSpecs(basicAllocator) { } inline MetricFormat::MetricFormat(const MetricFormat& original, bslma::Allocator *basicAllocator) : d_formatSpecs(original.d_formatSpecs, basicAllocator) { } // MANIPULATORS inline MetricFormat& MetricFormat::operator=(const MetricFormat& rhs) { d_formatSpecs = rhs.d_formatSpecs; return *this; } inline void MetricFormat::setFormatSpec(PublicationType::Value publicationType, const MetricFormatSpec& formatSpec) { if (d_formatSpecs.empty()) { d_formatSpecs.resize(PublicationType::k_LENGTH); } d_formatSpecs[(int)publicationType].makeValue(formatSpec); } inline void MetricFormat::clearFormatSpecs() { d_formatSpecs.clear(); } // ACCESSORS inline const MetricFormatSpec *MetricFormat::formatSpec( PublicationType::Value publicationType) const { if (d_formatSpecs.empty()) { return 0; // RETURN } const AggregateFormatSpec& spec = d_formatSpecs[publicationType]; return spec.isNull() ? 0 : &spec.value(); } } // close package namespace // FREE OPERATORS inline bool balm::operator==(const MetricFormat& lhs, const MetricFormat& rhs) { return lhs.d_formatSpecs == rhs.d_formatSpecs; } inline bool balm::operator!=(const MetricFormat& lhs, const MetricFormat& rhs) { return !(lhs == rhs); } inline bsl::ostream& balm::operator<<(bsl::ostream& stream, const MetricFormat& rhs) { return rhs.print(stream, 0, -1); } } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2015 Bloomberg Finance L.P. // // 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. // ----------------------------- END-OF-FILE ----------------------------------