Repository: envoyproxy/envoy
File: envoy/stats/scope.h (C/C++)

Code before:

#include "absl/types/optional.h"

namespace Envoy {
namespace Stats {

class Counter;
class Gauge;
class Histogram;
class NullGaugeImpl;
class Scope;
class Store;
class TextReadout;

using CounterOptConstRef = absl::optional<std::reference_wrapper<const Counter>>;
using GaugeOptConstRef = absl::optional<std::reference_wrapper<const Gauge>>;
using HistogramOptConstRef = absl::optional<std::reference_wrapper<const Histogram>>;
using TextReadoutOptConstRef = absl::optional<std::reference_wrapper<const TextReadout>>;
using ConstScopeSharedPtr = std::shared_ptr<const Scope>;
using ScopeSharedPtr = std::shared_ptr<Scope>;

// Settings for limiting the number of counters, gauges and histograms allowed
// in a scope.
struct ScopeStatsLimitSettings {
  // Max number of counters allowed in this scope.
  absl::optional<uint64_t> max_counters = absl::nullopt;
  // Max number of gauges allowed in this scope.
  absl::optional<uint64_t> max_gauges = absl::nullopt;
  // Max number of histograms allowed in this scope.
  absl::optional<uint64_t> max_histograms = absl::nullopt;
};

template <class StatType> using IterateFn = std::function<bool(const RefcountPtr<StatType>&)>;

/**
 * A named scope for stats. Scopes are a grouping of stats that can be acted on
 * as a unit if needed (for example to free/delete all of them).
 *
 * Every counters, gauges, histograms, and text-readouts is managed by a Scope.
 *
 * Scopes are managed by shared pointers. This makes it possible for the admin
 * stats handler to safely capture all the scope references and remain robust to
 * other threads deleting those scopes while rendering an admin stats page.
 *
 * It is invalid to allocate a Scope using std::unique_ptr or directly on the
 * stack.
 *
 * We use std::shared_ptr rather than Stats::RefcountPtr, which we use for other
 * stats, because:
 *  * existing uses of shared_ptr<Scope> exist in the Wasm extension and would
 *    need to be rewritten to allow for RefcountPtr<Scope>.

Review comment (suggestion):
Realistically, these are more like uint32 or even less? Moreover, this struct is inlined into every scope (even the ones not needing it) which will increase memory usage (e.g. per-cluster memory). I think we could pack it better, e.g. use uint32_t with 0 as "disabled" rather than optional.

Code after:

#include "absl/types/optional.h"

namespace Envoy {
namespace Stats {

class Counter;
class Gauge;
class Histogram;
class NullGaugeImpl;
class Scope;
class Store;
class TextReadout;

using CounterOptConstRef = absl::optional<std::reference_wrapper<const Counter>>;
using GaugeOptConstRef = absl::optional<std::reference_wrapper<const Gauge>>;
using HistogramOptConstRef = absl::optional<std::reference_wrapper<const Histogram>>;
using TextReadoutOptConstRef = absl::optional<std::reference_wrapper<const TextReadout>>;
using ConstScopeSharedPtr = std::shared_ptr<const Scope>;
using ScopeSharedPtr = std::shared_ptr<Scope>;

// Settings for limiting the number of counters, gauges and histograms allowed
// in a scope. This currently only supports thread local stats.
struct ScopeStatsLimitSettings {
  // Max number of counters allowed in this scope. 0 means no limit.
  uint32_t max_counters = 0;
  // Max number of gauges allowed in this scope. 0 means no limit.
  uint32_t max_gauges = 0;
  // Max number of histograms allowed in this scope. 0 means no limit.
  uint32_t max_histograms = 0;
};

template <class StatType> using IterateFn = std::function<bool(const RefcountPtr<StatType>&)>;

/**
 * A named scope for stats. Scopes are a grouping of stats that can be acted on
 * as a unit if needed (for example to free/delete all of them).
 *
 * Every counters, gauges, histograms, and text-readouts is managed by a Scope.
 *
 * Scopes are managed by shared pointers. This makes it possible for the admin
 * stats handler to safely capture all the scope references and remain robust to
 * other threads deleting those scopes while rendering an admin stats page.
 *
 * It is invalid to allocate a Scope using std::unique_ptr or directly on the
 * stack.
 *
 * We use std::shared_ptr rather than Stats::RefcountPtr, which we use for other
 * stats, because:
 *  * existing uses of shared_ptr<Scope> exist in the Wasm extension and would
 *    need to be rewritten to allow for RefcountPtr<Scope>.