1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <stdint.h> 8 #include <unistd.h> 9 10 #include <cobalt-client/cpp/counter-internal.h> 11 #include <cobalt-client/cpp/types-internal.h> 12 #include <fbl/function.h> 13 #include <fbl/string.h> 14 #include <fbl/vector.h> 15 16 namespace cobalt_client { 17 namespace internal { 18 19 // Note: Everything on this namespace is internal, no external users should rely 20 // on the behaviour of any of these classes. 21 22 // Base class for histogram, that provides a thin layer over a collection of buckets 23 // that represent a histogram. Once constructed, unless moved, the class is thread-safe. 24 // All allocations happen when constructed. 25 // 26 // This class is not moveable, not copyable or assignable. 27 // This class is thread-compatible. 28 template <uint32_t num_buckets> 29 class BaseHistogram { 30 public: 31 using Count = uint64_t; 32 using Bucket = uint32_t; 33 34 BaseHistogram() = default; 35 BaseHistogram(const BaseHistogram&) = delete; 36 BaseHistogram(BaseHistogram&&) = delete; 37 BaseHistogram& operator=(const BaseHistogram&) = delete; 38 BaseHistogram& operator=(BaseHistogram&&) = delete; 39 ~BaseHistogram() = default; 40 41 // Returns the number of buckets of this histogram. size()42 constexpr uint32_t size() const { return num_buckets; } 43 44 void IncrementCount(Bucket bucket, Count val = 1) { 45 ZX_DEBUG_ASSERT_MSG(bucket < size(), "IncrementCount bucket(%u) out of range(%u).", bucket, 46 size()); 47 buckets_[bucket].Increment(val); 48 } 49 GetCount(uint32_t bucket)50 Count GetCount(uint32_t bucket) const { 51 ZX_DEBUG_ASSERT_MSG(bucket < size(), "GetCount bucket out of range."); 52 return buckets_[bucket].Load(); 53 } 54 55 protected: 56 // Counter for the abs frequency of every histogram bucket. 57 BaseCounter<uint64_t> buckets_[num_buckets]; 58 }; 59 60 // Free functions to move logic outside the templated class. 61 62 // Initializes buckets such that bucket[i].index = i and bucket[i].count = 0. 63 void InitBucketBuffer(HistogramBucket* buckets, uint32_t bucket_count); 64 65 // Sets |metric_info| to respective values from |options|, and initializes the buckets. 66 void InitLazily(const MetricOptions& options, HistogramBucket* buckets, uint32_t num_buckets, 67 RemoteMetricInfo* metric_info); 68 69 // Sets the count of each bucket in |bucket_buffer| to the respective value in 70 // |buckets|, and sets the count in |buckets| to 0. 71 bool HistogramFlush(const RemoteMetricInfo& metric_info, Logger* logger, 72 BaseCounter<uint64_t>* buckets, HistogramBucket* bucket_buffer, 73 uint32_t num_buckets); 74 75 // Undo's an ungoing Flush effects. 76 void HistogramUndoFlush(BaseCounter<uint64_t>* buckets, HistogramBucket* bucket_buffer, 77 uint32_t num_buckets); 78 79 // This class provides a histogram which represents a full fledged cobalt metric. The histogram 80 // owner will call |Flush| which is meant to incrementally persist data to cobalt. 81 // 82 // This class is not moveable, copyable or assignable. 83 // This class is thread-compatible. 84 template <uint32_t num_buckets> 85 class RemoteHistogram : public BaseHistogram<num_buckets>, public FlushInterface { 86 public: 87 RemoteHistogram() = default; RemoteHistogram(const RemoteMetricInfo & metric_info)88 RemoteHistogram(const RemoteMetricInfo& metric_info) 89 : BaseHistogram<num_buckets>(), metric_info_(metric_info) { 90 InitBucketBuffer(bucket_buffer_, num_buckets); 91 } 92 RemoteHistogram(const RemoteHistogram&) = delete; 93 RemoteHistogram(RemoteHistogram&&) = delete; 94 RemoteHistogram& operator=(const RemoteHistogram&) = delete; 95 RemoteHistogram& operator=(RemoteHistogram&&) = delete; 96 ~RemoteHistogram() override = default; 97 Initialize(const MetricOptions & options)98 void Initialize(const MetricOptions& options) { 99 InitLazily(options, bucket_buffer_, num_buckets, &metric_info_); 100 } 101 Flush(Logger * logger)102 bool Flush(Logger* logger) override { 103 return HistogramFlush(metric_info_, logger, this->buckets_, bucket_buffer_, num_buckets); 104 } 105 UndoFlush()106 void UndoFlush() override { HistogramUndoFlush(this->buckets_, bucket_buffer_, num_buckets); } 107 108 // Returns the metric_id associated with this remote metric. metric_info()109 const RemoteMetricInfo& metric_info() const { return metric_info_; } 110 111 private: 112 // Buffer for out of line allocation for the data being sent 113 // through fidl. This buffer is rewritten on every flush, and contains 114 // an entry for each bucket. 115 HistogramBucket bucket_buffer_[num_buckets]; 116 117 // Metric information such as metric_id, event_code and component. 118 RemoteMetricInfo metric_info_; 119 }; 120 121 } // namespace internal 122 } // namespace cobalt_client 123