Line data Source code
1 : #pragma once 2 : 3 : #include <cstdint> 4 : #include <functional> 5 : #include <limits> 6 : #include <memory> 7 : #include <string> 8 : #include <vector> 9 : 10 : #include "envoy/common/pure.h" 11 : #include "envoy/stats/store.h" 12 : #include "envoy/thread_local/thread_local_object.h" 13 : #include "envoy/type/v3/percent.pb.h" 14 : 15 : #include "source/common/common/assert.h" 16 : #include "source/common/singleton/threadsafe_singleton.h" 17 : 18 : #include "absl/container/flat_hash_map.h" 19 : #include "absl/container/node_hash_map.h" 20 : #include "absl/types/optional.h" 21 : 22 : namespace Envoy { 23 : 24 : namespace Upstream { 25 : class ClusterManager; 26 : } 27 : 28 : namespace Runtime { 29 : 30 : /** 31 : * A snapshot of runtime data. 32 : */ 33 : class Snapshot : public ThreadLocal::ThreadLocalObject { 34 : public: 35 : struct Entry { 36 : std::string raw_string_value_; 37 : absl::optional<uint64_t> uint_value_; 38 : absl::optional<double> double_value_; 39 : absl::optional<envoy::type::v3::FractionalPercent> fractional_percent_value_; 40 : absl::optional<bool> bool_value_; 41 : }; 42 : 43 : using EntryMap = absl::flat_hash_map<std::string, Entry>; 44 : 45 : /** 46 : * A provider of runtime values. One or more of these compose the snapshot's source of values, 47 : * where successive layers override the previous ones. 48 : */ 49 : class OverrideLayer { 50 : public: 51 2879 : virtual ~OverrideLayer() = default; 52 : 53 : /** 54 : * @return const absl::flat_hash_map<std::string, Entry>& the values in this layer. 55 : */ 56 : virtual const EntryMap& values() const PURE; 57 : 58 : /** 59 : * @return const std::string& a user-friendly alias for this layer, e.g. "admin" or "disk". 60 : */ 61 : virtual const std::string& name() const PURE; 62 : }; 63 : 64 : using OverrideLayerConstPtr = std::unique_ptr<const OverrideLayer>; 65 : 66 : /** 67 : * Returns true if a deprecated feature is allowed. 68 : * 69 : * Fundamentally, deprecated features are boolean values. 70 : * They are allowed by default or with explicit configuration to "true" via runtime configuration. 71 : * They can be disallowed either by inclusion in the hard-coded disallowed_features[] list, or by 72 : * configuration of "false" in runtime config. 73 : * @param key supplies the key to lookup. 74 : * @param default_value supplies the default value that will be used if either the key 75 : * does not exist or it is not a boolean. 76 : */ 77 : virtual bool deprecatedFeatureEnabled(absl::string_view key, bool default_enabled) const PURE; 78 : 79 : // Returns true if a runtime feature is enabled. 80 : // 81 : // Runtime features are used to easily allow switching between old and new code paths for high 82 : // risk changes. The intent is for the old code path to be short lived - the old code path is 83 : // deprecated as the feature is defaulted true, and removed with the following Envoy release. 84 : virtual bool runtimeFeatureEnabled(absl::string_view key) const PURE; 85 : 86 : /** 87 : * Test if a feature is enabled using the built in random generator. This is done by generating 88 : * a random number in the range 0-99 and seeing if this number is < the value stored in the 89 : * runtime key, or the default_value if the runtime key is invalid. 90 : * NOTE: In the current implementation, this routine may return different results each time it is 91 : * called because a new random number is used each time. Callers should understand this 92 : * behavior and not assume that subsequent calls using the same snapshot will be consistent. 93 : * @param key supplies the feature key to lookup. 94 : * @param default_value supplies the default value that will be used if either the feature key 95 : * does not exist or it is not an integer. 96 : * @return true if the feature is enabled. 97 : */ 98 : virtual bool featureEnabled(absl::string_view key, uint64_t default_value) const PURE; 99 : 100 : /** 101 : * Test if a feature is enabled using a supplied stable random value. This variant is used if 102 : * the caller wants a stable result over multiple calls. 103 : * @param key supplies the feature key to lookup. 104 : * @param default_value supplies the default value that will be used if either the feature key 105 : * does not exist or it is not an integer. 106 : * @param random_value supplies the stable random value to use for determining whether the feature 107 : * is enabled. 108 : * @return true if the feature is enabled. 109 : */ 110 : virtual bool featureEnabled(absl::string_view key, uint64_t default_value, 111 : uint64_t random_value) const PURE; 112 : 113 : /** 114 : * Test if a feature is enabled using a supplied stable random value and total number of buckets 115 : * for sampling. 116 : * This variant is used if the caller wants a stable result over multiple calls 117 : * and have more granularity for samples. 118 : * @param key supplies the feature key to lookup. 119 : * @param default_value supplies the default value that will be used if either the feature key 120 : * does not exist or it is not an integer. 121 : * @param random_value supplies the stable random value to use for determining whether the feature 122 : * is enabled. 123 : * @param num_buckets control max number of buckets for sampling. Sampled value will be in a range 124 : * of [0, num_buckets). 125 : * @return true if the feature is enabled. 126 : */ 127 : virtual bool featureEnabled(absl::string_view key, uint64_t default_value, uint64_t random_value, 128 : uint64_t num_buckets) const PURE; 129 : 130 : /** 131 : * Test if a feature is enabled using the built in random generator. This is done by generating a 132 : * random number between 0 and the fractional percent denominator and seeing if this number is < 133 : * the numerator value stored in the runtime key. The default_value's numerator/denominator is 134 : * used if the runtime key is invalid. 135 : * 136 : * If the runtime value for the provided runtime key is provided as an integer, it is assumed that 137 : * the value is the numerator and the denominator is 100. 138 : * 139 : * NOTE: In the current implementation, this routine may return different results each time it is 140 : * called because a new random number is used each time. Callers should understand this 141 : * behavior and not assume that subsequent calls using the same snapshot will be consistent. 142 : * @param key supplies the feature key to lookup. 143 : * @param default_value supplies the default value that will be used if either the feature key 144 : * does not exist or it is not a fractional percent. 145 : * @return true if the feature is enabled. 146 : */ 147 : virtual bool featureEnabled(absl::string_view key, 148 : const envoy::type::v3::FractionalPercent& default_value) const PURE; 149 : 150 : /** 151 : * Test if a feature is enabled using a supplied stable random value. This variant is used if 152 : * the caller wants a stable result over multiple calls. 153 : * 154 : * If the runtime value for the provided runtime key is provided as an integer, it is assumed that 155 : * the value is the numerator and the denominator is 100. 156 : * 157 : * @param key supplies the feature key to lookup. 158 : * @param default_value supplies the default value that will be used if either the feature key 159 : * does not exist or it is not a fractional percent. 160 : * @param random_value supplies the stable random value to use for determining whether the feature 161 : * is enabled. 162 : * @return true if the feature is enabled. 163 : */ 164 : virtual bool featureEnabled(absl::string_view key, 165 : const envoy::type::v3::FractionalPercent& default_value, 166 : uint64_t random_value) const PURE; 167 : 168 : using ConstStringOptRef = absl::optional<std::reference_wrapper<const std::string>>; 169 : /** 170 : * Fetch raw runtime data based on key. 171 : * @param key supplies the key to fetch. 172 : * @return absl::nullopt if the key does not exist or reference to the value std::string. 173 : */ 174 : virtual ConstStringOptRef get(absl::string_view key) const PURE; 175 : 176 : /** 177 : * Fetch an integer runtime key. Runtime keys larger than ~2^53 may not be accurately converted 178 : * into integers and will return default_value. 179 : * @param key supplies the key to fetch. 180 : * @param default_value supplies the value to return if the key does not exist or it does not 181 : * contain an integer. 182 : * @return uint64_t the runtime value or the default value. 183 : */ 184 : virtual uint64_t getInteger(absl::string_view key, uint64_t default_value) const PURE; 185 : 186 : /** 187 : * Fetch a double runtime key. 188 : * @param key supplies the key to fetch. 189 : * @param default_value supplies the value to return if the key does not exist or it does not 190 : * contain a double. 191 : * @return double the runtime value or the default value. 192 : */ 193 : virtual double getDouble(absl::string_view key, double default_value) const PURE; 194 : 195 : /** 196 : * Fetch a boolean runtime key. 197 : * @param key supplies the key to fetch. 198 : * @param default_value supplies the value to return if the key does not exist or it does not 199 : * contain a boolean. 200 : * @return bool the runtime value or the default value. 201 : */ 202 : virtual bool getBoolean(absl::string_view key, bool default_value) const PURE; 203 : 204 : /** 205 : * Fetch the OverrideLayers that provide values in this snapshot. Layers are ordered from bottom 206 : * to top; for instance, the second layer's entries override the first layer's entries, and so on. 207 : * Any layer can add a key in addition to overriding keys in layers below. The layer vector is 208 : * safe only for the lifetime of the Snapshot. 209 : * @return const std::vector<OverrideLayerConstPtr>& the raw map of loaded values. 210 : */ 211 : virtual const std::vector<OverrideLayerConstPtr>& getLayers() const PURE; 212 : }; 213 : 214 : using SnapshotConstSharedPtr = std::shared_ptr<const Snapshot>; 215 : 216 : /** 217 : * Loads runtime snapshots from storage (local disk, etc.). 218 : */ 219 : class Loader { 220 : public: 221 4216 : virtual ~Loader() = default; 222 : 223 : using ReadyCallback = std::function<void()>; 224 : 225 : /** 226 : * Post-construction initialization. Runtime will be generally available after 227 : * the constructor is finished, with the exception of dynamic RTDS layers, 228 : * which require ClusterManager. 229 : * @param cm cluster manager reference. 230 : */ 231 : virtual void initialize(Upstream::ClusterManager& cm) PURE; 232 : 233 : /** 234 : * @return const Snapshot& the current snapshot. This reference is safe to use for the duration of 235 : * the calling routine, but may be overwritten on a future event loop cycle so should be 236 : * fetched again when needed. This may only be called from worker threads. 237 : */ 238 : virtual const Snapshot& snapshot() PURE; 239 : 240 : /** 241 : * @return shared_ptr<const Snapshot> the current snapshot. This function may safely be called 242 : * from non-worker threads. 243 : */ 244 : virtual SnapshotConstSharedPtr threadsafeSnapshot() PURE; 245 : 246 : /** 247 : * Merge the given map of key-value pairs into the runtime's state. To remove a previous merge for 248 : * a key, use an empty string as the value. 249 : * @param values the values to merge 250 : */ 251 : virtual void mergeValues(const absl::node_hash_map<std::string, std::string>& values) PURE; 252 : 253 : /** 254 : * Initiate all RTDS subscriptions. The `on_done` callback is invoked when all RTDS requests 255 : * have either received and applied their responses or timed out. 256 : */ 257 : virtual void startRtdsSubscriptions(ReadyCallback on_done) PURE; 258 : 259 : /** 260 : * @return Stats::Scope& the root scope. 261 : */ 262 : virtual Stats::Scope& getRootScope() PURE; 263 : 264 : /** 265 : * Updates deprecated feature use stats. 266 : */ 267 : virtual void countDeprecatedFeatureUse() const PURE; 268 : }; 269 : 270 : using LoaderPtr = std::unique_ptr<Loader>; 271 : 272 : } // namespace Runtime 273 : } // namespace Envoy