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
42369
    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
302265
  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
   * @return a status indicating if initialization was successful.
231
   */
232
  virtual absl::Status initialize(Upstream::ClusterManager& cm) PURE;
233

            
234
  /**
235
   * @return const Snapshot& the current snapshot. This reference is safe to use for the duration of
236
   *         the calling routine, but may be overwritten on a future event loop cycle so should be
237
   *         fetched again when needed. This may only be called from worker threads.
238
   */
239
  virtual const Snapshot& snapshot() const PURE;
240

            
241
  /**
242
   * @return shared_ptr<const Snapshot> the current snapshot. This function may safely be called
243
   *         from non-worker threads.
244
   */
245
  virtual SnapshotConstSharedPtr threadsafeSnapshot() PURE;
246

            
247
  /**
248
   * Merge the given map of key-value pairs into the runtime's state. To remove a previous merge for
249
   * a key, use an empty string as the value.
250
   * @param values the values to merge
251
   * @return a status indicating success or failure.
252
   */
253
  virtual absl::Status
254
  mergeValues(const absl::node_hash_map<std::string, std::string>& values) PURE;
255

            
256
  /**
257
   * Initiate all RTDS subscriptions. The `on_done` callback is invoked when all RTDS requests
258
   * have either received and applied their responses or timed out.
259
   */
260
  virtual void startRtdsSubscriptions(ReadyCallback on_done) PURE;
261

            
262
  /**
263
   * @return Stats::Scope& the root scope.
264
   */
265
  virtual Stats::Scope& getRootScope() PURE;
266

            
267
  /**
268
   * Updates deprecated feature use stats.
269
   */
270
  virtual void countDeprecatedFeatureUse() const PURE;
271
};
272

            
273
using LoaderPtr = std::unique_ptr<Loader>;
274

            
275
} // namespace Runtime
276
} // namespace Envoy