Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/runtime/runtime_impl.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include <cstdint>
4
#include <memory>
5
#include <string>
6
7
#include "envoy/api/api.h"
8
#include "envoy/common/exception.h"
9
#include "envoy/common/random_generator.h"
10
#include "envoy/config/bootstrap/v3/bootstrap.pb.h"
11
#include "envoy/config/core/v3/config_source.pb.h"
12
#include "envoy/config/subscription.h"
13
#include "envoy/init/manager.h"
14
#include "envoy/runtime/runtime.h"
15
#include "envoy/service/discovery/v3/discovery.pb.h"
16
#include "envoy/service/runtime/v3/rtds.pb.h"
17
#include "envoy/service/runtime/v3/rtds.pb.validate.h"
18
#include "envoy/stats/stats_macros.h"
19
#include "envoy/stats/store.h"
20
#include "envoy/thread_local/thread_local.h"
21
#include "envoy/type/v3/percent.pb.h"
22
#include "envoy/upstream/cluster_manager.h"
23
24
#include "source/common/common/assert.h"
25
#include "source/common/common/logger.h"
26
#include "source/common/common/thread.h"
27
#include "source/common/config/subscription_base.h"
28
#include "source/common/init/manager_impl.h"
29
#include "source/common/init/target_impl.h"
30
#include "source/common/singleton/threadsafe_singleton.h"
31
32
#include "absl/container/node_hash_map.h"
33
#include "spdlog/spdlog.h"
34
35
namespace Envoy {
36
namespace Runtime {
37
38
using RuntimeSingleton = ThreadSafeSingleton<Loader>;
39
40
/**
41
 * All runtime stats. @see stats_macros.h
42
 */
43
#define ALL_RUNTIME_STATS(COUNTER, GAUGE)                                                          \
44
62.3k
  COUNTER(deprecated_feature_use)                                                                  \
45
62.3k
  COUNTER(load_error)                                                                              \
46
62.3k
  COUNTER(load_success)                                                                            \
47
62.3k
  COUNTER(override_dir_exists)                                                                     \
48
62.3k
  COUNTER(override_dir_not_exists)                                                                 \
49
62.3k
  GAUGE(admin_overrides_active, NeverImport)                                                       \
50
62.3k
  GAUGE(deprecated_feature_seen_since_process_start, NeverImport)                                  \
51
62.3k
  GAUGE(num_keys, NeverImport)                                                                     \
52
62.3k
  GAUGE(num_layers, NeverImport)
53
54
/**
55
 * Struct definition for all runtime stats. @see stats_macros.h
56
 */
57
struct RuntimeStats {
58
  ALL_RUNTIME_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT)
59
};
60
61
/**
62
 * Implementation of Snapshot whose source is the vector of layers passed to the constructor.
63
 */
64
class SnapshotImpl : public Snapshot, Logger::Loggable<Logger::Id::runtime> {
65
public:
66
  SnapshotImpl(Random::RandomGenerator& generator, RuntimeStats& stats,
67
               std::vector<OverrideLayerConstPtr>&& layers);
68
69
  // Runtime::Snapshot
70
  bool deprecatedFeatureEnabled(absl::string_view key, bool default_value) const override;
71
  bool runtimeFeatureEnabled(absl::string_view key) const override;
72
  bool featureEnabled(absl::string_view key, uint64_t default_value, uint64_t random_value,
73
                      uint64_t num_buckets) const override;
74
  bool featureEnabled(absl::string_view key, uint64_t default_value) const override;
75
  bool featureEnabled(absl::string_view key, uint64_t default_value,
76
                      uint64_t random_value) const override;
77
  bool featureEnabled(absl::string_view key,
78
                      const envoy::type::v3::FractionalPercent& default_value) const override;
79
  bool featureEnabled(absl::string_view key,
80
                      const envoy::type::v3::FractionalPercent& default_value,
81
                      uint64_t random_value) const override;
82
  ConstStringOptRef get(absl::string_view key) const override;
83
  uint64_t getInteger(absl::string_view key, uint64_t default_value) const override;
84
  double getDouble(absl::string_view key, double default_value) const override;
85
  bool getBoolean(absl::string_view key, bool value) const override;
86
  const std::vector<OverrideLayerConstPtr>& getLayers() const override;
87
88
  const EntryMap& values() const;
89
90
  static Entry createEntry(const ProtobufWkt::Value& value, absl::string_view raw_string,
91
                           const char*& error_message);
92
  static void addEntry(Snapshot::EntryMap& values, const std::string& key,
93
                       const ProtobufWkt::Value& value, absl::string_view raw_string = "");
94
95
private:
96
  const std::vector<OverrideLayerConstPtr> layers_;
97
  EntryMap values_;
98
  Random::RandomGenerator& generator_;
99
  RuntimeStats& stats_;
100
};
101
102
using SnapshotImplPtr = std::unique_ptr<SnapshotImpl>;
103
104
/**
105
 * Base implementation of OverrideLayer that by itself provides an empty values map.
106
 */
107
class OverrideLayerImpl : public Snapshot::OverrideLayer {
108
public:
109
174k
  explicit OverrideLayerImpl(absl::string_view name) : name_{name} {}
110
222k
  const Snapshot::EntryMap& values() const override { return values_; }
111
0
  const std::string& name() const override { return name_; }
112
113
protected:
114
  Snapshot::EntryMap values_;
115
  const std::string name_;
116
};
117
118
/**
119
 * Extension of OverrideLayerImpl that maintains an in-memory set of values. These values can be
120
 * modified programmatically via mergeValues(). AdminLayer is so named because it can be accessed
121
 * and manipulated by Envoy's admin interface.
122
 */
123
class AdminLayer : public OverrideLayerImpl {
124
public:
125
  explicit AdminLayer(absl::string_view name, RuntimeStats& stats)
126
168k
      : OverrideLayerImpl{name}, stats_{stats} {}
127
  /**
128
   * Copy-constructible so that it can snapshotted.
129
   */
130
108k
  AdminLayer(const AdminLayer& admin_layer) : AdminLayer{admin_layer.name_, admin_layer.stats_} {
131
108k
    values_ = admin_layer.values();
132
108k
  }
133
134
  /**
135
   * Merge the provided values into our entry map. An empty value indicates that a key should be
136
   * removed from our map.
137
   */
138
  void mergeValues(const absl::node_hash_map<std::string, std::string>& values);
139
140
private:
141
  RuntimeStats& stats_;
142
};
143
144
using AdminLayerPtr = std::unique_ptr<AdminLayer>;
145
146
/**
147
 * Extension of OverrideLayerImpl that loads values from the file system upon construction.
148
 */
149
class DiskLayer : public OverrideLayerImpl, Logger::Loggable<Logger::Id::runtime> {
150
public:
151
  DiskLayer(absl::string_view name, const std::string& path, Api::Api& api);
152
153
private:
154
  void walkDirectory(const std::string& path, const std::string& prefix, uint32_t depth,
155
                     Api::Api& api);
156
157
  const std::string path_;
158
  const Filesystem::WatcherPtr watcher_;
159
};
160
161
/**
162
 * Extension of OverrideLayerImpl that loads values from a proto Struct representation.
163
 */
164
class ProtoLayer : public OverrideLayerImpl, Logger::Loggable<Logger::Id::runtime> {
165
public:
166
  ProtoLayer(absl::string_view name, const ProtobufWkt::Struct& proto);
167
168
private:
169
  void walkProtoValue(const ProtobufWkt::Value& v, const std::string& prefix);
170
};
171
172
class LoaderImpl;
173
174
struct RtdsSubscription : Envoy::Config::SubscriptionBase<envoy::service::runtime::v3::Runtime>,
175
                          Logger::Loggable<Logger::Id::runtime> {
176
  RtdsSubscription(LoaderImpl& parent,
177
                   const envoy::config::bootstrap::v3::RuntimeLayer::RtdsLayer& rtds_layer,
178
                   Stats::Store& store, ProtobufMessage::ValidationVisitor& validation_visitor);
179
180
  // Config::SubscriptionCallbacks
181
  absl::Status onConfigUpdate(const std::vector<Config::DecodedResourceRef>& resources,
182
                              const std::string& version_info) override;
183
  absl::Status onConfigUpdate(const std::vector<Config::DecodedResourceRef>& added_resources,
184
                              const Protobuf::RepeatedPtrField<std::string>& removed_resources,
185
                              const std::string&) override;
186
187
  void onConfigUpdateFailed(Envoy::Config::ConfigUpdateFailureReason reason,
188
                            const EnvoyException* e) override;
189
190
  void start();
191
  absl::Status validateUpdateSize(uint32_t added_resources_num, uint32_t removed_resources_num);
192
  absl::Status onConfigRemoved(const Protobuf::RepeatedPtrField<std::string>& removed_resources);
193
  void createSubscription();
194
195
  LoaderImpl& parent_;
196
  const envoy::config::core::v3::ConfigSource config_source_;
197
  Stats::Store& store_;
198
  Stats::ScopeSharedPtr stats_scope_;
199
  Config::SubscriptionPtr subscription_;
200
  std::string resource_name_;
201
  Init::TargetImpl init_target_;
202
  ProtobufWkt::Struct proto_;
203
};
204
205
using RtdsSubscriptionPtr = std::unique_ptr<RtdsSubscription>;
206
207
/**
208
 * Implementation of Loader that provides Snapshots of values added via mergeValues().
209
 * A single snapshot is shared among all threads and referenced by shared_ptr such that
210
 * a new runtime can be swapped in by the main thread while workers are still using the previous
211
 * version.
212
 */
213
class LoaderImpl : public Loader, Logger::Loggable<Logger::Id::runtime> {
214
public:
215
  LoaderImpl(Event::Dispatcher& dispatcher, ThreadLocal::SlotAllocator& tls,
216
             const envoy::config::bootstrap::v3::LayeredRuntime& config,
217
             const LocalInfo::LocalInfo& local_info, Stats::Store& store,
218
             Random::RandomGenerator& generator,
219
             ProtobufMessage::ValidationVisitor& validation_visitor, Api::Api& api);
220
221
  // Runtime::Loader
222
  void initialize(Upstream::ClusterManager& cm) override;
223
  const Snapshot& snapshot() override;
224
  SnapshotConstSharedPtr threadsafeSnapshot() override;
225
  void mergeValues(const absl::node_hash_map<std::string, std::string>& values) override;
226
  void startRtdsSubscriptions(ReadyCallback on_done) override;
227
  Stats::Scope& getRootScope() override;
228
  void countDeprecatedFeatureUse() const override;
229
230
private:
231
  friend RtdsSubscription;
232
233
  // Create a new Snapshot
234
  SnapshotImplPtr createNewSnapshot();
235
  // Load a new Snapshot into TLS
236
  void loadNewSnapshot();
237
  RuntimeStats generateStats(Stats::Store& store);
238
  void onRtdsReady();
239
240
  Random::RandomGenerator& generator_;
241
  RuntimeStats stats_;
242
  AdminLayerPtr admin_layer_;
243
  ThreadLocal::SlotPtr tls_;
244
  const envoy::config::bootstrap::v3::LayeredRuntime config_;
245
  const std::string service_cluster_;
246
  Filesystem::WatcherPtr watcher_;
247
  Api::Api& api_;
248
  ReadyCallback on_rtds_initialized_;
249
  Init::WatcherImpl init_watcher_;
250
  Init::ManagerImpl init_manager_{"RTDS"};
251
  std::vector<RtdsSubscriptionPtr> subscriptions_;
252
  Upstream::ClusterManager* cm_{};
253
  Stats::Store& store_;
254
255
  absl::Mutex snapshot_mutex_;
256
  SnapshotConstSharedPtr thread_safe_snapshot_ ABSL_GUARDED_BY(snapshot_mutex_);
257
};
258
259
} // namespace Runtime
260
} // namespace Envoy