blob: e82c5436f5a24789d4bc110c3cefda0de2ba35a7 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <stdint.h>
#include <cobalt-client/cpp/collector.h>
#include <cobalt-client/cpp/histogram-internal.h>
#include <cobalt-client/cpp/metric-options.h>
#include <cobalt-client/cpp/types-internal.h>
#include <zircon/assert.h>
namespace cobalt_client {
// Thin wrapper for a histogram. This class does not own the data, but acts as a proxy.
//
// This class is not copyable, moveable or assignable.
// This class is thread-safe.
template <uint32_t num_buckets>
class Histogram {
public:
static_assert(num_buckets > 0, "num_buckets must be postive.");
// Underlying type used for representing bucket count.
using Count = uint64_t;
Histogram() = default;
Histogram(const HistogramOptions& options)
: remote_histogram_(internal::RemoteMetricInfo::From(options)), options_(options) {}
// Collector's lifetime must exceed the histogram's lifetime.
Histogram(const HistogramOptions& options, Collector* collector)
: remote_histogram_(internal::RemoteMetricInfo::From(options)), options_(options),
collector_(collector) {
ZX_DEBUG_ASSERT_MSG(!options_.IsLazy(),
"Cannot initialize histogram with |kLazy| options.");
if (collector_ != nullptr) {
collector_->Subscribe(&remote_histogram_);
}
}
// Constructor for internal use only.
Histogram(const HistogramOptions& options, internal::FlushInterface** flush_interface)
: remote_histogram_(internal::RemoteMetricInfo::From(options)), options_(options) {
ZX_DEBUG_ASSERT_MSG(!options_.IsLazy(),
"Cannot initialize histogram with |kLazy| options.");
*flush_interface = &remote_histogram_;
}
Histogram(const Histogram&) = delete;
Histogram(Histogram&& other) = delete;
Histogram& operator=(const Histogram&) = delete;
Histogram& operator=(Histogram&&) = delete;
~Histogram() {
if (collector_ != nullptr) {
collector_->UnSubscribe(&remote_histogram_);
}
}
// Optionally initialize lazily the histogram, if is more readable to do so
// in the constructor or function body.
void Initialize(const HistogramOptions& options, Collector* collector) {
ZX_DEBUG_ASSERT_MSG(!options.IsLazy(),
"Cannot initialize histogram with |kLazy| options.");
options_ = options;
collector_ = collector;
remote_histogram_.Initialize(options_);
if (collector_ != nullptr) {
collector_->Subscribe(&remote_histogram_);
}
}
// Returns the number of buckets allocated for this histogram. This includes
// the overflow and underflow buckets.
constexpr uint32_t size() const { return num_buckets + 2; }
// Increases the count of the bucket containing |value| by |times|.
// |ValueType| must either be an (u)int or a double.
template <typename ValueType>
void Add(ValueType value, Count times = 1) {
ZX_DEBUG_ASSERT_MSG(!options_.IsLazy(),
"Histogram must be initialized before operation.");
double dbl_value = static_cast<double>(value);
uint32_t bucket = options_.map_fn(dbl_value, size(), options_);
remote_histogram_.IncrementCount(bucket, times);
}
// Returns the count of the bucket containing |value|, since it was last sent
// to cobalt.
// |ValueType| must either be an (u)int or a double.
template <typename ValueType>
Count GetRemoteCount(ValueType value) const {
ZX_DEBUG_ASSERT_MSG(!options_.IsLazy(),
"Histogram must be initialized before operation.");
double dbl_value = static_cast<double>(value);
uint32_t bucket = options_.map_fn(dbl_value, size(), options_);
return remote_histogram_.GetCount(bucket);
}
private:
// Two extra buckets for overflow and underflow buckets.
internal::RemoteHistogram<num_buckets + 2> remote_histogram_;
HistogramOptions options_;
Collector* collector_ = nullptr;
};
} // namespace cobalt_client