aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/statistics/window_stats.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/statistics/window_stats.h')
-rw-r--r--src/core/statistics/window_stats.h173
1 files changed, 173 insertions, 0 deletions
diff --git a/src/core/statistics/window_stats.h b/src/core/statistics/window_stats.h
new file mode 100644
index 0000000000..677f40031e
--- /dev/null
+++ b/src/core/statistics/window_stats.h
@@ -0,0 +1,173 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GRPC_INTERNAL_STATISTICS_WINDOW_STATS_H_
+#define __GRPC_INTERNAL_STATISTICS_WINDOW_STATS_H_
+
+#include <grpc/support/time.h>
+
+/* Keep rolling sums of a user-defined statistic (containing a number of
+ measurements) over a a number of time intervals ("windows"). For example,
+ you can use a window_stats object to answer questions such as
+ "Approximately how many RPCs/s did I receive over the past minute, and
+ approximately how many bytes did I send out over that period?".
+
+ The type of data to record, and the time intervals to keep are specified
+ when creating the object via a call to census_window_stats_create().
+
+ A window's interval is divided into one or more "buckets"; the interval
+ must be divisible by the number of buckets. Internally, these buckets
+ control the granularity of window_stats' measurements. Increasing the
+ number of buckets lets the object respond more quickly to changes in the
+ overall rate of data added into the object, at the cost of additional
+ memory usage.
+
+ Here's some code which keeps one minute/hour measurements for two values
+ (latency in seconds and bytes transferred), with each interval divided into
+ 4 buckets.
+
+ typedef struct my_stat {
+ double latency;
+ int bytes;
+ } my_stat;
+
+ void add_my_stat(void* base, const void* addme) {
+ my_stat* b = (my_stat*)base;
+ const my_stat* a = (const my_stat*)addme;
+ b->latency += a->latency;
+ b->bytes += a->bytes;
+ }
+
+ void add_proportion_my_stat(double p, void* base, const void* addme) {
+ (my_stat*)result->latency += p * (const my_stat*)base->latency;
+ (my_stat*)result->bytes += p * (const my_stat*)base->bytes;
+ }
+
+ #define kNumIntervals 2
+ #define kMinInterval 0
+ #define kHourInterval 1
+ #define kNumBuckets 4
+
+ const struct census_window_stats_stat_info kMyStatInfo
+ = { sizeof(my_stat), NULL, add_my_stat, add_proportion_my_stat };
+ gpr_timespec intervals[kNumIntervals] = {{60, 0}, {3600, 0}};
+ my_stat stat;
+ my_stat sums[kNumIntervals];
+ census_window_stats_sums result[kNumIntervals];
+ struct census_window_stats* stats
+ = census_window_stats_create(kNumIntervals, intervals, kNumBuckets,
+ &kMyStatInfo);
+ // Record a new event, taking 15.3ms, transferring 1784 bytes.
+ stat.latency = 0.153;
+ stat.bytes = 1784;
+ census_window_stats_add(stats, gpr_now(), &stat);
+ // Get sums and print them out
+ result[kMinInterval].statistic = &sums[kMinInterval];
+ result[kHourInterval].statistic = &sums[kHourInterval];
+ census_window_stats_get_sums(stats, gpr_now(), result);
+ printf("%d events/min, average time %gs, average bytes %g\n",
+ result[kMinInterval].count,
+ (my_stat*)result[kMinInterval].statistic->latency /
+ result[kMinInterval].count,
+ (my_stat*)result[kMinInterval].statistic->bytes /
+ result[kMinInterval].count
+ );
+ printf("%d events/hr, average time %gs, average bytes %g\n",
+ result[kHourInterval].count,
+ (my_stat*)result[kHourInterval].statistic->latency /
+ result[kHourInterval].count,
+ (my_stat*)result[kHourInterval].statistic->bytes /
+ result[kHourInterval].count
+ );
+*/
+
+/* Opaque structure for representing window_stats object */
+struct census_window_stats;
+
+/* Information provided by API user on the information they want to record */
+typedef struct census_window_stats_stat_info {
+ /* Number of bytes in user-defined object. */
+ size_t stat_size;
+ /* Function to initialize a user-defined statistics object. If this is set
+ * to NULL, then the object will be zero-initialized. */
+ void (*stat_initialize)(void* stat);
+ /* Function to add one user-defined statistics object ('addme') to 'base' */
+ void (*stat_add)(void* base, const void* addme);
+ /* As for previous function, but only add a proportion 'p'. This API will
+ currently only use 'p' values in the range [0,1], but other values are
+ possible in the future, and should be supported. */
+ void (*stat_add_proportion)(double p, void* base, const void* addme);
+} census_window_stats_stat_info;
+
+/* Create a new window_stats object. 'nintervals' is the number of
+ 'intervals', and must be >=1. 'granularity' is the number of buckets, with
+ a larger number using more memory, but providing greater accuracy of
+ results. 'granularity should be > 2. We also require that each interval be
+ at least 10 * 'granularity' nanoseconds in size. 'stat_info' contains
+ information about the statistic to be gathered. Intervals greater than ~192
+ years will be treated as essentially infinite in size. This function will
+ GPR_ASSERT() if the object cannot be created or any of the parameters have
+ invalid values. This function is thread-safe. */
+struct census_window_stats* census_window_stats_create(
+ int nintervals, const gpr_timespec intervals[], int granularity,
+ const census_window_stats_stat_info* stat_info);
+
+/* Add a new measurement (in 'stat_value'), as of a given time ('when').
+ This function is thread-compatible. */
+void census_window_stats_add(struct census_window_stats* wstats,
+ const gpr_timespec when, const void* stat_value);
+
+/* Structure used to record a single intervals sum for a given statistic */
+typedef struct census_window_stats_sum {
+ /* Total count of samples. Note that because some internal interpolation
+ is performed, the count of samples returned for each interval may not be an
+ integral value. */
+ double count;
+ /* Sum for statistic */
+ void* statistic;
+} census_window_stats_sums;
+
+/* Retrieve a set of all values stored in a window_stats object 'wstats'. The
+ number of 'sums' MUST be the same as the number 'nintervals' used in
+ census_window_stats_create(). This function is thread-compatible. */
+void census_window_stats_get_sums(const struct census_window_stats* wstats,
+ const gpr_timespec when,
+ struct census_window_stats_sum sums[]);
+
+/* Destroy a window_stats object. Once this function has been called, the
+ object will no longer be usable from any of the above functions (and
+ calling them will most likely result in a NULL-pointer dereference or
+ assertion failure). This function is thread-compatible. */
+void census_window_stats_destroy(struct census_window_stats* wstats);
+
+#endif /* __GRPC_INTERNAL_STATISTICS_WINDOW_STATS_H_ */