// balm_configurationutil.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_CONFIGURATIONUTIL #define INCLUDED_BALM_CONFIGURATIONUTIL #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a namespace for metrics configuration utilities. // //@CLASSES: // balm::ConfigurationUtil: namespace for metrics configuration utilities // //@SEE_ALSO: balm_metricsmanager, balm_defaultmetricsmanager // //@DESCRIPTION: This component provides a set of utility functions for // configuring metrics. The 'balm::ConfigurationUtil' 'struct' provides // short-cuts for common configuration operations that are performed on other // components in the 'balm' package. // ///Alternative Systems for Telemetry ///--------------------------------- // Bloomberg software may alternatively use the GUTS telemetry API, which is // integrated into Bloomberg infrastructure. // ///Thread Safety ///------------- // 'balm::ConfigurationUtil' is fully *thread-safe*, meaning that all the // methods can be safely invoked simultaneously from multiple threads. // ///Usage ///----- // The following examples demonstrate how to use 'balm::ConfigurationUtil'. // ///Configuring the Output of a Metric /// - - - - - - - - - - - - - - - - - // This example uses 'balm::ConfigurationUtil' to configure the output for a // metric. // // We start by initializing a default metrics manager by creating a // 'balm::DefaultMetricsManagerScopedGuard', which manages the lifetime of the // default metrics manager object. At construction, we provide the scoped // guard an output stream ('stdout') to which the default metrics manager will // publish metrics. Note that the default metrics manager is intended to be // created and destroyed by the *owner* of 'main'. A metrics manager should // be created during the initialization of an application (while the task has // a single thread) and destroyed just prior to termination (when there is // similarly a single thread). //.. // int main(int argc, char *argv[]) // { // // ... // // balm::DefaultMetricsManagerScopedGuard managerGuard(bsl::cout); //.. // Next we create a metric, "avgElapsedTimeMs", that will output the average // time, in milliseconds, spent in a section of code. We set the preferred // publication type for the metric to be average: //.. // balm::ConfigurationUtil::setPreferredPublicationType( // "myCategory", // "avgElapsedTimeMs", // balm::PublicationType::e_AVG); //.. // Next, because we will record the elapsed time in seconds, we configure a // format to scale the elapsed time by 1000.0: //.. // balm::ConfigurationUtil::setFormatSpec( // "myCategory", // "avgElapsedTimeMs", // balm::PublicationType::e_AVG, // balm::MetricFormatSpec(1000.0, "%.2f ms"); //.. // We now collect an example value of .005: //.. // BALM_METRIC_UPDATE("myCategory", "avgElapsedTimeMs", .005); //.. // Finally, we publish the metric. Note that in practice, clients of the // 'balm' package can use the 'balm::PublicationScheduler' to schedule the // periodic publication of metrics: //.. // balm::DefaultMetricsManager::instance()->publishAll(); //.. // The output for the publication will look like: //.. // 06AUG2009_20:27:51.982+0000 1 Records // Elapsed Time: 0.000816s // myCategory.avgElapsedTimeMs[ avg (total/count) = 5.00 ms ] //.. // ///Using a Metric's User Data /// - - - - - - - - - - - - - // In the following example we configure, using 'balm::ConfigurationUtil', // application-specific publication thresholds for a series of metrics. We // will create an application-specific publisher that will use the configured // thresholds to determine whether a metric should be written to the console. // For simplicity, the metric thresholds in this example will be a single // unsigned integer value that will be compared with the metric's total. // // We start by defining an application-specific publisher implementation. // This implementation is supplied a user data key on construction, which it // uses to look up the threshold for a particular metric. If a metric's total // value is greater than its threshold, it will log the metric to the console. //.. // // thresholdpublisher.h // class ThresholdPublisher : public balm::Publisher { // // A simple implementation of the 'balm::Publisher' protocol that // // writes metric records to the console when their value is greater // // than an application-specific threshold. // // // DATA // balm::MetricDescription::UserDataKey d_thresholdKey; // key for a // // metric's // // threshold // // // NOT IMPLEMENTED // ThresholdPublisher(const ThresholdPublisher&); // ThresholdPublisher& operator=(const ThresholdPublisher&); // // public: // // CREATORS // ThresholdPublisher(balm::MetricDescription::UserDataKey thresholdKey); // // Create a publisher that will publish metrics to the console if // // their total value is greater than their associated threshold, // // accessed via the specified 'thresholdKey'. // // virtual ~ThresholdPublisher(); // // Destroy this publisher. // // // MANIPULATORS // virtual void publish(const balm::MetricSample& metricValues); // // Publish the specified 'metricValues' to the console if they are // // greater than their associated threshold. // }; // // // thresholdpublisher.cpp // // // CREATORS // ThresholdPublisher::ThresholdPublisher( // balm::MetricDescription::UserDataKey thresholdKey) // : d_thresholdKey(thresholdKey) // { // } // // ThresholdPublisher::~ThresholdPublisher() // { // } // // // MANIPULATORS // void ThresholdPublisher::publish(const balm::MetricSample& metricValues) // { // if (0 >= metricValues.numRecords()) { // return; // RETURN // } // balm::MetricSample::const_iterator sIt = metricValues.begin(); // for (; sIt != metricValues.end(); ++sIt) { // balm::MetricSampleGroup::const_iterator gIt = sIt->begin(); // for (; gIt != sIt->end(); ++gIt) { //.. // We now use the user data key to lookup the address of the threshold value. // If this address is 0, no threshold is specified for the metric. //.. // const balm::MetricDescription& description = // *gIt->metricId().description(); // unsigned int *thresholdPtr = // (unsigned int *)description.userData(d_thresholdKey); // if (thresholdPtr && gIt->total() > *thresholdPtr) { // bsl::cout << "WARNING: " << gIt->metricId() // << " = " << gIt->total() // << bsl::endl; // } // } // } // } //.. // Now we examine how to configure a metrics manager with a // 'ThresholdPublisher', and set the thresholds for a couple of metrics. We // start by defining a couple of threshold constants for our metrics: //.. // static const unsigned int ELAPSED_TIME_THRESHOLD = 10; // static const unsigned int NUM_REQUESTS_THRESHOLD = 100; //.. // Now, we configure a default metrics manager and publish a couple of example // metrics. We start by initializing a default metrics manager by creating a // 'balm::DefaultMetricsManagerScopedGuard', which manages the lifetime of the // default metrics manager: //.. // int main(int argc, char *argv[]) // { // // ... // bslma::Allocator *allocator = bslma::Default::allocator(0); // balm::DefaultMetricsManagerScopedGuard managerGuard; //.. // Now we create a user data key for our threshold information: //.. // balm::MetricDescription::UserDataKey thresholdKey = // balm::ConfigurationUtil::createUserDataKey(); //.. // Next we create an object of our application-specific publisher type, // 'ThresholdPublisher', and configure the default metrics manager to publish // metrics using this publisher: //.. // bsl::shared_ptr<balm::Publisher> publisher( // new (*allocator) ThresholdPublisher(thresholdKey), // allocator); // balm::DefaultMetricsManager::instance()->addGeneralPublisher(publisher); //.. // Next we configure two metric thresholds: //.. // balm::ConfigurationUtil::setUserData("myCategory", // "elapsedTime", // thresholdKey, // &ELAPSED_TIME_THRESHOLD); // balm::ConfigurationUtil::setUserData("myCategory", // "numRequests", // thresholdKey, // &NUM_REQUESTS_THRESHOLD); //.. // Now we update the value of a couple of metrics. Note that the recorded // number of requests is greater than the metric's configured threshold: //.. // BALM_METRICS_UPDATE("myCategory", "elapsedTime", 2); // BALM_METRICS_UPDATE("myCategory", "numRequests", 150); //.. // Finally, we publish the collected metrics. Note that in practice, clients // of the 'balm' package can use the 'balm::PublicationScheduler' to schedule // the periodic publication of metrics: //.. // balm::DefaultMetricsManager::instance()->publishAll(); //.. // The console output of the call to 'publishAll' will look like: //.. // WARNING: myCategory.numRequests = 150 //.. #include <balscm_version.h> #include <balm_metricdescription.h> #include <balm_publicationtype.h> namespace BloombergLP { namespace balm { class MetricFormat; class MetricFormatSpec; class MetricsManager; // ======================== // struct ConfigurationUtil // ======================== struct ConfigurationUtil { // This 'struct' provides utilities for configuring metrics. // CLASS METHODS static int setFormat(const char *category, const char *metricName, const MetricFormat& format, MetricsManager *manager = 0); // Set the format specification for the metric indicated by the // specified 'category' and 'metricName' to the specified 'format'. // Optionally specify a metrics 'manager' to configure. If 'manager' // is 0, configure the default metrics manager; if 'manager' is 0 and // the default metrics manager has not been initialized, this method // has no effect. Return 0 on success, or a non-zero value if // 'manager' is 0 and the default metrics manager has not been // initialized. If a 'MetricId' does not exist for 'category' and // 'metricName', create one and add it to the metric registry of the // indicated metrics manager. static int setFormatSpec(const char *category, const char *metricName, PublicationType::Value publicationType, const MetricFormatSpec& formatSpec, MetricsManager *manager = 0); // Set the format specification for the metric aggregate indicated by // the specified 'category', 'metricName', and 'publicationType' to // the specified 'formatSpec'. Optionally specify a metrics 'manager' // to configure. If 'manager' is 0, configure the default metrics // manager; if 'manager' is 0 and the default metrics manager has not // been initialized, this method has no effect. Return 0 on success, // or a non-zero value if 'manager' is 0 and the default metrics // manager has not been initialized. If a 'MetricId' does not exist // for 'category' and 'metricName', create one and add it to the metric // registry of the indicated metrics manager. For example a // publication type of 'e_AVG', and a format spec with a scale of // 1000.0 and a format of "%.2f ms", indicates that the average value // of the indicated metric should be formatted by scaling the value by // 1000 and then rounding the value to the second decimal place and // appending " ms". static int setPreferredPublicationType( const char *category, const char *metricName, PublicationType::Value publicationType, MetricsManager *manager = 0); // Set the preferred publication type of the metric identified by the // specified 'category' and 'metricName' to the specified // 'publicationType'. Optionally specify a metrics 'manager' to // configure. If 'manager' is 0, configure the default metrics // manager; if 'manager' is 0 and the default metrics manager has not // been initialized, this method has no effect. Return 0 on success, // or a non-zero value if 'manager' is 0 and the default metrics // manager has not been initialized. The preferred publication type of // a metric indicates the preferred aggregate to publish for that // metric, or 'PublicationType::e_UNSPECIFIED' if there is no // preference. For example, specifying 'e_AVG' indicates that the // average value of the collected metric should be reported. If a // 'MetricId' does not exist for 'category' and 'metricName', create // one and add it to the metric registry of the indicated metrics // manager. Note that there is no uniform definition for how // publishers will interpret this value. static MetricDescription::UserDataKey createUserDataKey( MetricsManager *manager = 0); // Return a new unique key that can be used to associate (via // 'setUserData') a value with a metric (or group of metrics). // Optionally specify a metrics 'manager' to configure. If 'manager' // is 0, configure the default metrics manager; if 'manager' is 0 and // the default metrics manager has not been initialized, then an // unspecified integer value is returned. Note that the returned key // can be used by clients of 'balm' to associate additional // information with a metric. static void setUserData(const char *category, const char *metricName, MetricDescription::UserDataKey key, const void *value, MetricsManager *manager = 0); // Associate the specified 'value' with the specified data 'key' in the // description of the metric having the specified 'category' and // 'metricName'. Optionally specify a metrics 'manager' to configure. // If 'manager' is 0, configure the default metrics manager; if // 'manager' is 0 and the default metrics manager has not been // initialized, this method has no effect. If a 'MetricId' does not // exist for the 'category' and 'metricName', create one and add it to // the metric registry of the indicated metrics manager. The behavior // is undefined unless 'key' was previously created for the indicated // metrics manager's metrics registry (e.g., by calling // 'createUserDataKey'). Note that this method allows clients of // 'balm' to associate (opaque) application-specific information with a // metric. static void setUserData(const char *categoryName, MetricDescription::UserDataKey key, const void *value, MetricsManager *manager = 0); // Associate the specified 'value' with the specified data 'key' in // any metric belonging to a category having the specified // 'categoryName', or, if 'categoryName' ends with an asterisk ('*'), // any metric belonging to a category whose name begins with // 'categoryName' (without the asterisk). Optionally specify a // metrics 'manager' to configure. If 'manager' is 0, configure the // default metrics manager; if 'manager' is 0 and the default metrics // manager has not been initialized, this method has no effect. This // association applies to existing metrics as well as any subsequently // created ones. When a metric is created that matches more than one // registered category prefix, it is not specified which supplied // value will be associated with 'key', unless only one of those values // is non-null, in which case the unique non-null value is used. The // behavior is undefined unless 'key' was previously created for the // indicated metrics manager's metrics registry (e.g., by calling // 'createUserDataKey'). }; } // close package namespace // ============================================================================ // INLINE DEFINITIONS // ============================================================================ } // 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 ----------------------------------