/usr/include/hphp/util/service-data.h is in hhvm-dev 3.11.1+dfsg-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | /*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2015 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_SERVICE_DATA_H_
#define incl_HPHP_SERVICE_DATA_H_
#include <atomic>
#include <chrono>
#include <map>
#include <string>
#include <vector>
#include <folly/RWSpinLock.h>
#include <folly/Synchronized.h>
#include <folly/stats/Histogram.h>
#include <folly/stats/MultiLevelTimeSeries.h>
#include <folly/Optional.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
/*
* A globally accessible statistics tracking facility. This can be used to keep
* track of internal runtime statistics in the form of flat counters, timeseries
* counters or histograms.
*
* ServiceData provides a globally accessible entry point to all the internal
* statistics. A 'statistic counter' of different types could be created by
* calling createCouter() createTimeseries() or createHistogram(). The caller
* can then add values at different time points to the statistic counters. The
* statistic can then be retrieved and reported via the exportAll() call on
* ServiceData.
*
* Thread safety:
* ==============
* All functions in ServiceData namespace are thread safe. It is safe
* (and recommended) to cache the object returned by create...() methods and
* repeatedly add data points to it. It is safe to call create...() with the
* same name from multiple threads. In this case, only one object will be
* created and passed back to different threads.
*
* All objects returned by returned by the various create...() calls are thread
* safe. It is okay to add data points to it from multiple threads concurrently.
* These objects are internally synchronized with spin locks.
*
* Example Usage:
* ==============
* // create a flat counter named foo.
* auto counter = ServiceData::createCouter("foo");
* counter->increment();
*
* // create timeseries data named bar with default setting (avg value for the
* // last 1 minute, 10 minute, hour and all time).
* auto timeseries = ServiceData::createTimeseries("bar");
* timeseries->addValue(3);
*
* // create a histogram with 10 buckets, min of 1, max of 100 and export the
* // 50th and 90th percentile value for reporting.
* auto histogram = ServiceData::createHistogram("blah", 10, 1, 100,
* {0.5, 0.9});
* histogram->addValue(10);
*
* // You can report the data like so.
* std::map<std::string, int64_t> statsMap;
* ServiceData::exportAll(statsMap);
*
* and statsMap will contain these keys:
*
* "foo"
* "bar.avg.60", "bar.avg.600", "bar.avg.3600", "bar.avg"
* "blah.hist.p50", "blah.hist.p90"
*
* Anti pattern:
* =============
* ServiceData::createCounter("foo")->increment(); // don't do this.
* Don't do this in performance critical code. You will incur the cost of a
* std::map look up whenever createCounter() is called. Rather, you should call
* ServiceData::createCounter("foo") just once, cache the returned pointer and
* repeatedly adding data points to it.
*/
namespace ServiceData {
class ExportedCounter;
class ExportedHistogram;
class ExportedTimeSeries;
namespace detail {
template <class ClassWithPrivateDestructor>
class FriendDeleter;
};
enum class StatsType { AVG, SUM, RATE, COUNT, PCT };
/*
* Create a flat counter named 'name'. Return an existing counter if it has
* already been created.
*/
ExportedCounter* createCounter(const std::string& name);
/*
* Create a timeseries counter named 'name'. Return an existing one if it
* has already been created.
*
* Timeseries data is implemented as a number of buckets (buckted by time).
* As data point is added and time rolls forward, new bucket is created and
* the earliest bucket expires.
*
* We keep multiple of timeseries data at different granularity and update
* them simultaneously. This allows us to commute statistics at different
* levels. For example, we can simultaneously compute the avg of some counter
* value over the last 5 minutes, 10 minutes and hour. This is a similar
* concept to the load counters from the unix 'uptime' command.
*
* 'exportTypes' specifies what kind of statistics to export for each level.
* More export types can be added after the timeseries is created.
*
* 'levels' specifies at which granularity should the stats be tracked. The
* time duration must be strictly increasing. Special value '0' means all
* time and should always come last.
*
* 'numBuckets' specifies how many buckets to keep at each level. More buckets
* will produce more precise data at the expense of memory.
*/
ExportedTimeSeries* createTimeseries(
const std::string& name,
const std::vector<StatsType>& exportTypes =
std::vector<StatsType>{ StatsType::AVG },
const std::vector<std::chrono::seconds>& levels =
std::vector<std::chrono::seconds>{
std::chrono::seconds(60),
std::chrono::seconds(600),
std::chrono::seconds(3600),
std::chrono::seconds(0) /* all time */ },
int numBuckets = 60);
/*
* Create a histogram counter named 'name'. Return an existing one if it has
* already been created.
*
* 'bucketSize' specifies how many buckets to track for the histogram.
* 'min' is the minimal value in the histogram.
* 'max' is the maximal value in the histogram.
* 'exportPercentile' specifies at what percentile values we should report the
* stat. A set of doubles between 0 and 1.0. For example, 0.5 means p50 and
* 0.99 means p99.
*/
ExportedHistogram* createHistogram(
const std::string& name,
int64_t bucketSize,
int64_t min,
int64_t max,
const std::vector<double>& exportPercentile);
/*
* Export all the statistics as simple key, value pairs.
*/
void exportAll(std::map<std::string, int64_t>& statsMap);
/*
* Export a specific counter by key name.
*/
folly::Optional<int64_t> exportCounterByKey(std::string& key);
// Interface for a flat counter. All methods are thread safe.
class ExportedCounter {
public:
ExportedCounter() : m_value(0) {}
void increment() { m_value.fetch_add(1, std::memory_order_relaxed); }
void decrement() { m_value.fetch_sub(1, std::memory_order_relaxed); }
void addValue(int64_t value) {
m_value.fetch_add(value, std::memory_order_relaxed);
}
void setValue(int64_t value) {
m_value.store(value, std::memory_order_relaxed);
}
int64_t getValue() const { return m_value.load(std::memory_order_relaxed); }
private:
friend class detail::FriendDeleter<ExportedCounter>;
~ExportedCounter() {}
std::atomic_int_fast64_t m_value;
};
// Interface for timeseries data. All methods are thread safe.
class ExportedTimeSeries {
public:
ExportedTimeSeries(int numBuckets,
const std::vector<std::chrono::seconds>& durations,
const std::vector<StatsType>& exportTypes);
void addValue(int64_t value);
void addValue(int64_t value, int64_t times);
void addValueAggregated(int64_t sum, int64_t nsamples);
int64_t getSum();
void exportAll(const std::string& prefix,
std::map<std::string, int64_t>& statsMap);
private:
friend class detail::FriendDeleter<ExportedTimeSeries>;
~ExportedTimeSeries() {}
folly::Synchronized<folly::MultiLevelTimeSeries<int64_t>,
folly::RWSpinLock > m_timeseries;
const std::vector<ServiceData::StatsType> m_exportTypes;
};
// Interface for histogram data. All methods are thread safe.
class ExportedHistogram {
public:
ExportedHistogram(int64_t bucketSize, int64_t min, int64_t max,
const std::vector<double>& exportPercentiles);
void addValue(int64_t value);
void removeValue(int64_t value);
void exportAll(const std::string& prefix,
std::map<std::string, int64_t>& statsMap);
private:
friend class detail::FriendDeleter<ExportedHistogram>;
~ExportedHistogram() {}
folly::Synchronized<folly::Histogram<int64_t>, folly::RWSpinLock> m_histogram;
const std::vector<double> m_exportPercentiles;
};
}; // namespace ServiceData
///////////////////////////////////////////////////////////////////////////////
}
#include "hphp/util/service-data-inl.h"
#endif // incl_HPHP_SERVICE_DATA_H_
|