#pragma once
#include <library/cpp/histogram/hdr/histogram.h>
#include <util/system/spinlock.h>
#include <util/stream/output.h>
namespace NMonitoring {
/**
* A statistical snapshot of values recorded in histogram.
*/
struct THistogramSnapshot {
double Mean;
double StdDeviation;
i64 Min;
i64 Max;
i64 Percentile50;
i64 Percentile75;
i64 Percentile90;
i64 Percentile95;
i64 Percentile98;
i64 Percentile99;
i64 Percentile999;
i64 TotalCount;
void Print(IOutputStream* out) const;
};
/**
* Special counter which calculates the distribution of a value.
*/
class THdrHistogram {
public:
/**
* Construct a histogram given the Lowest and Highest values to be tracked
* and a number of significant decimal digits. Providing a
* lowestDiscernibleValue is useful in situations where the units used for
* the histogram's values are much smaller that the minimal accuracy
* required. E.g. when tracking time values stated in nanosecond units,
* where the minimal accuracy required is a microsecond, the proper value
* for lowestDiscernibleValue would be 1000.
*
* @param lowestDiscernibleValue The lowest value that can be discerned
* (distinguished from 0) by the histogram. Must be a positive
* integer that is >= 1. May be internally rounded down to nearest
* power of 2.
*
* @param highestTrackableValue The highest value to be tracked by the
* histogram. Must be a positive integer that is
* >= (2 * lowestDiscernibleValue).
*
* @param numberOfSignificantValueDigits Specifies the precision to use.
* This is the number of significant decimal digits to which the
* histogram will maintain value resolution and separation. Must be
* a non-negative integer between 0 and 5.
*/
THdrHistogram(i64 lowestDiscernibleValue, i64 highestTrackableValue,
i32 numberOfSignificantValueDigits)
: Data_(lowestDiscernibleValue, highestTrackableValue,
numberOfSignificantValueDigits) {
}
/**
* Records a value in the histogram, will round this value of to a
* precision at or better than the NumberOfSignificantValueDigits specified
* at construction time.
*
* @param value Value to add to the histogram
* @return false if the value is larger than the HighestTrackableValue
* and can't be recorded, true otherwise.
*/
bool RecordValue(i64 value) {
with_lock (Lock_) {
return Data_.RecordValue(value);
}
}
/**
* Records count values in the histogram, will round this value of to a
* precision at or better than the NumberOfSignificantValueDigits specified
* at construction time.
*
* @param value Value to add to the histogram
* @param count Number of values to add to the histogram
* @return false if the value is larger than the HighestTrackableValue
* and can't be recorded, true otherwise.
*/
bool RecordValues(i64 value, i64 count) {
with_lock (Lock_) {
return Data_.RecordValues(value, count);
}
}
/**
* Records a value in the histogram and backfill based on an expected
* interval. Value will be rounded this to a precision at or better
* than the NumberOfSignificantValueDigits specified at contruction time.
* This is specifically used for recording latency. If the value is larger
* than the expectedInterval then the latency recording system has
* experienced co-ordinated omission. This method fills in the values that
* would have occured had the client providing the load not been blocked.
*
* @param value Value to add to the histogram
* @param expectedInterval The delay between recording values
* @return false if the value is larger than the HighestTrackableValue
* and can't be recorded, true otherwise.
*/
bool RecordValueWithExpectedInterval(i64 value, i64 expectedInterval) {
with_lock (Lock_) {
return Data_.RecordValueWithExpectedInterval(value, expectedInterval);
}
}
/**
* Record a value in the histogram count times. Applies the same correcting
* logic as {@link THdrHistogram::RecordValueWithExpectedInterval}.
*
* @param value Value to add to the histogram
* @param count Number of values to add to the histogram
* @param expectedInterval The delay between recording values.
* @return false if the value is larger than the HighestTrackableValue
* and can't be recorded, true otherwise.
*/
bool RecordValuesWithExpectedInterval(
i64 value, i64 count, i64 expectedInterval) {
with_lock (Lock_) {
return Data_.RecordValuesWithExpectedInterval(
value, count, expectedInterval);
}
}
/**
* @return The configured lowestDiscernibleValue
*/
i64 GetLowestDiscernibleValue() const {
with_lock (Lock_) {
return Data_.GetLowestDiscernibleValue();
}
}
/**
* @return The configured highestTrackableValue
*/
i64 GetHighestTrackableValue() const {
with_lock (Lock_) {
return Data_.GetHighestTrackableValue();
}
}
/**
* @return The configured numberOfSignificantValueDigits
*/
i32 GetNumberOfSignificantValueDigits() const {
with_lock (Lock_) {
return Data_.GetNumberOfSignificantValueDigits();
}
}
/**
* @return The total count of all recorded values in the histogram
*/
i64 GetTotalCount() const {
with_lock (Lock_) {
return Data_.GetTotalCount();
}
}
/**
* Place a copy of the value counts accumulated since the last snapshot
* was taken into {@code snapshot}. Calling this member-function will
* reset the value counts, and start accumulating value counts for the
* next interval.
*
* @param snapshot the structure into which the values should be copied.
*/
void TakeSnaphot(THistogramSnapshot* snapshot);
private:
mutable TSpinLock Lock_;
NHdr::THistogram Data_;
};
}
template <>
inline void Out<NMonitoring::THistogramSnapshot>(
IOutputStream& out, const NMonitoring::THistogramSnapshot& snapshot) {
snapshot.Print(&out);
}