// balm_integercollector.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_INTEGERCOLLECTOR #define INCLUDED_BALM_INTEGERCOLLECTOR #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a container for collecting integral metric values. // //@CLASSES: // balm::IntegerCollector: a container for collecting integral values // //@SEE_ALSO: // //@DESCRIPTION: This component provides a class for collecting and aggregating // the values of an integral metric. The 'balm::IntegerCollector' records the // number of times an event occurs as well as an associated integral // measurement value. This component does *not* define what constitutes an // event or what the value measures. The collector manages, in a fully // thread-safe manner, the count of event occurrences and the aggregated // minimum, maximum, and total of the measured metric value. This collector // class provides operations to update the aggregated value, a 'load' method // to populate a 'balm::MetricRecord' with the current state of the collector, // a 'reset' operator to reset the current state of the integer collector, and // finally a combined 'loadAndReset' method that performs both a load and a // reset in a single (atomic) operation. // ///Alternative Systems for Telemetry ///--------------------------------- // Bloomberg software may alternatively use the GUTS telemetry API, which is // integrated into Bloomberg infrastructure. // ///Thread Safety ///------------- // 'balm::IntegerCollector' is fully *thread-safe*, meaning that all // non-creator operations on a given instance can be safely invoked // simultaneously from multiple threads. // ///Usage ///----- // The following example creates a 'balm::IntegerCollector', modifies its // values, then collects a 'balm::MetricRecord'. // // We start by creating a 'balm::MetricId' object by hand, but in practice, an // id should be obtained from a 'balm::MetricRegistry' object (such as the one // owned by a 'balm::MetricsManager'): //.. // balm::Category myCategory("MyCategory"); // balm::MetricDescription description(&myCategory, "MyMetric"); // balm::MetricId myMetric(&description); //.. // Now we create a 'balm::IntegerCollector' object for 'myMetric' and use the // 'update' method to update its collected value: //.. // balm::IntegerCollector collector(myMetric); // // collector.update(1); // collector.update(3); //.. // The collector accumulated the values 1 and 3. The result should have a // count of 2, a total of 4 (3 + 1), a max of 3 (max(3, 1)), and a min of 1 // (min(3, 1)). //.. // balm::MetricRecord record; // collector.loadAndReset(&record); // // assert(myMetric == record.metricId()); // assert(2 == record.count()); // assert(4 == record.total()); // assert(1 == record.min()); // assert(3 == record.max()); //.. #include <bsl_algorithm.h> #include <balscm_version.h> #include <balm_metricid.h> #include <balm_metricrecord.h> #include <bslmt_mutex.h> #include <bslmt_lockguard.h> #include <bsls_types.h> namespace BloombergLP { namespace balm { // ====================== // class IntegerCollector // ====================== class IntegerCollector { // This class provides a mechanism for collecting and aggregating the // value of an integer metric over a period of time. The collector // contains a 'MetricId' object identifying the metric being collected, // the number of times an event occurred, and the total, minimum, and // maximum aggregates of the associated measurement value. The default // value for the count is 0, the default value for the total is 0, the // default value for the minimum is 'k_DEFAULT_MIN', and the default value // for the maximum is 'k_DEFAULT_MAX'. // DATA MetricId d_metricId; // metric identifier int d_count; // aggregated count of events bsls::Types::Int64 d_total; // total of values across events int d_min; // minimum value across events int d_max; // maximum value across events mutable bslmt::Mutex d_mutex; // synchronizes access to data // NOT IMPLEMENTED IntegerCollector(const IntegerCollector&); IntegerCollector& operator=(const IntegerCollector&); public: // PUBLIC CONSTANTS static const int k_DEFAULT_MIN; // default minimum value (INT_MAX) static const int k_DEFAULT_MAX; // default maximum value (INT_MIN) #ifndef BDE_OMIT_INTERNAL_DEPRECATED static const int DEFAULT_MIN; static const int DEFAULT_MAX; #endif // CREATORS IntegerCollector(const MetricId& metricId); // Create an integer collector for a metric having the specified // 'metricId', and having an initial count of 0, total of 0, min of // 'k_DEFAULT_MIN', and max of 'k_DEFAULT_MAX'. ~IntegerCollector(); // Destroy this object. // MANIPULATORS void reset(); // Reset the count, total, minimum, and maximum values of the metric // being collected to their default states. After this operation, the // count and total values will be 0, the minimum value will be // 'k_DEFAULT_MIN', and the maximum value will be 'k_DEFAULT_MAX'. void loadAndReset(MetricRecord *records); // Load into the specified 'record' the id of the metric being // collected as well as the current count, total, minimum, and maximum // aggregated values for that metric; then reset the count, total, // minimum, and maximum values to their default states. After this // operation, the count and total values will be 0, the minimum value // will be 'k_DEFAULT_MIN', and the maximum value will be // 'k_DEFAULT_MAX'. Note that // 'k_DEFAULT_MIN != MetricRecord::k_DEFAULT_MIN' and // 'k_DEFAULT_MAX != MetricRecord::k_DEFAULT_MAX'; when populating // 'record', this operation will convert default values for minimum and // maximum. A minimum value of 'k_DEFAULT_MIN' will populate a minimum // value of 'MetricRecord::k_DEFAULT_MIN' and a maximum value of // 'k_DEFAULT_MAX' will populate a maximum value of // 'MetricRecord::k_DEFAULT_MAX'. void update(int value); // Increment the event count by 1, add the specified 'value' to the // total, if 'value' is less than the minimum value, set 'value' to be // the minimum value, and if 'value' is greater than the maximum // value, set 'value' to be the maximum value. void accumulateCountTotalMinMax(int count, int total, int min, int max); // Increment the event count by the specified 'count', add the // specified 'total' to the accumulated total, and if the specified // 'min' is less than the minimum value, set 'min' to be the minimum // value, and if the specified 'max' is greater than the maximum value, // set 'max' to be the maximum value. void setCountTotalMinMax(int count, int total, int min, int max); // Set the event count to the specified 'count', the total aggregate to // the specified 'total', the minimum aggregate to the specified 'min' // and the maximum aggregate to the specified 'max'. // ACCESSORS const MetricId& metricId() const; // Return a reference to the non-modifiable 'MetricId' object // identifying the metric for which this object collects values. void load(MetricRecord *record) const; // Load into the specified 'record' the id of the metric being // collected, as well as the current count, total, minimum, and // maximum aggregated values for the metric. Note that // 'k_DEFAULT_MIN != MetricRecord::k_DEFAULT_MIN' and // 'k_DEFAULT_MAX != MetricRecord::k_DEFAULT_MAX'; when populating // 'record', this operation will convert default values for minimum // and maximum. A minimum value of 'k_DEFAULT_MIN' will populate a // minimum value of 'MetricRecord::k_DEFAULT_MIN' and a maximum value // of 'k_DEFAULT_MAX' will populate a maximum value of // 'MetricRecord::k_DEFAULT_MAX'. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ---------------------- // class IntegerCollector // ---------------------- // CREATORS inline IntegerCollector::IntegerCollector(const MetricId& metricId) : d_metricId(metricId) , d_count(0) , d_total(0) , d_min(k_DEFAULT_MIN) , d_max(k_DEFAULT_MAX) , d_mutex() { } inline IntegerCollector::~IntegerCollector() { } // MANIPULATORS inline void IntegerCollector::reset() { bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); d_count = 0; d_total = 0; d_min = k_DEFAULT_MIN; d_max = k_DEFAULT_MAX; } inline void IntegerCollector::update(int value) { bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); ++d_count; d_total += value; d_min = bsl::min(value, d_min); d_max = bsl::max(value, d_max); } inline void IntegerCollector::accumulateCountTotalMinMax(int count, int total, int min, int max) { bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); d_count += count; d_total += total; d_min = bsl::min(min, d_min); d_max = bsl::max(max, d_max); } inline void IntegerCollector::setCountTotalMinMax(int count, int total, int min, int max) { bslmt::LockGuard<bslmt::Mutex> guard(&d_mutex); d_count = count; d_total = total; d_min = min; d_max = max; } // ACCESSORS inline const MetricId& IntegerCollector::metricId() const { return d_metricId; } } // close package namespace } // 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 ----------------------------------