1
#pragma once
2

            
3
#include <map>
4
#include <memory>
5
#include <string>
6
#include <vector>
7

            
8
#include "envoy/common/time.h"
9
#include "envoy/config/core/v3/base.pb.h"
10
#include "envoy/network/address.h"
11
#include "envoy/network/transport_socket.h"
12
#include "envoy/stats/primitive_stats_macros.h"
13
#include "envoy/stats/stats_macros.h"
14
#include "envoy/upstream/health_check_host_monitor.h"
15
#include "envoy/upstream/outlier_detection.h"
16
#include "envoy/upstream/resource_manager.h"
17

            
18
#include "absl/strings/string_view.h"
19
#include "xds/data/orca/v3/orca_load_report.pb.h"
20

            
21
namespace Envoy {
22
namespace StreamInfo {
23
class StreamInfo;
24
} // namespace StreamInfo
25
namespace Upstream {
26

            
27
using OrcaLoadReport = xds::data::orca::v3::OrcaLoadReport;
28

            
29
using MetadataConstSharedPtr = std::shared_ptr<const envoy::config::core::v3::Metadata>;
30

            
31
/**
32
 * All per host stats. @see stats_macros.h
33
 *
34
 * {rq_success, rq_error} have specific semantics driven by the needs of EDS load reporting. See
35
 * envoy.api.v2.endpoint.UpstreamLocalityStats for the definitions of success/error. These are
36
 * latched by LoadStatsReporter interface implementations, independent of the normal stats sink
37
 * flushing.
38

            
39
 */
40
#define ALL_HOST_STATS(COUNTER, GAUGE)                                                             \
41
7
  COUNTER(cx_connect_fail)                                                                         \
42
41
  COUNTER(cx_total)                                                                                \
43
41
  COUNTER(rq_error)                                                                                \
44
41
  COUNTER(rq_success)                                                                              \
45
41
  COUNTER(rq_timeout)                                                                              \
46
41
  COUNTER(rq_total)                                                                                \
47
41
  GAUGE(cx_active)                                                                                 \
48
41
  GAUGE(rq_active)
49

            
50
/**
51
 * All per host stats defined. @see stats_macros.h
52
 */
53
struct HostStats {
54
  ALL_HOST_STATS(GENERATE_PRIMITIVE_COUNTER_STRUCT, GENERATE_PRIMITIVE_GAUGE_STRUCT);
55

            
56
  // Provide access to name,counter pairs.
57
7
  std::vector<std::pair<absl::string_view, Stats::PrimitiveCounterReference>> counters() {
58
42
    return {ALL_HOST_STATS(PRIMITIVE_COUNTER_NAME_AND_REFERENCE, IGNORE_PRIMITIVE_GAUGE)};
59
7
  }
60

            
61
  // Provide access to name,gauge pairs.
62
34
  std::vector<std::pair<absl::string_view, Stats::PrimitiveGaugeReference>> gauges() {
63
68
    return {ALL_HOST_STATS(IGNORE_PRIMITIVE_COUNTER, PRIMITIVE_GAUGE_NAME_AND_REFERENCE)};
64
34
  }
65
};
66

            
67
/**
68
 * Weakly-named load metrics to be reported as EndpointLoadMetricStats. Individual stats are
69
 * accumulated by calling add(), which combines stats with the same name. The aggregated stats are
70
 * retrieved by calling latch(), which also clears the current load metrics.
71
 */
72
class LoadMetricStats {
73
public:
74
201427
  virtual ~LoadMetricStats() = default;
75

            
76
  struct Stat {
77
    uint64_t num_requests_with_metric = 0;
78
    double total_metric_value = 0.0;
79
  };
80

            
81
  using StatMap = absl::flat_hash_map<std::string, Stat>;
82
  using StatMapPtr = std::unique_ptr<StatMap>;
83

            
84
  // Adds the given stat to the map. If the stat already exists in the map, then the stat is
85
  // combined with the existing map entry by incrementing num_requests_with_metric and summing the
86
  // total_metric_value fields. Otherwise, the stat is added with the provided value to the map,
87
  // which retains all entries until the next call to latch(). This allows metrics to be added
88
  // whose keys may not necessarily be known at startup time.
89
  virtual void add(const absl::string_view key, double value) PURE;
90

            
91
  // Returns an owning pointer to the current load metrics and clears the map.
92
  virtual StatMapPtr latch() PURE;
93
};
94

            
95
/**
96
 * Base interface for attaching LbPolicy-specific data to individual hosts.
97
 * This allows LbPolicy implementations to store per-host data that is used
98
 * to make load balancing decisions.
99
 */
100
class HostLbPolicyData {
101
public:
102
89
  virtual ~HostLbPolicyData() = default;
103

            
104
  /**
105
   * Invoked when a new orca report is received for this upstream host to
106
   * update the host lb policy data.
107
   * NOTE: this method may be called concurrently from multiple threads.
108
   * Please ensure that the implementation is thread-safe.
109
   *
110
   * @param report supplies the ORCA load report of this upstream host.
111
   * @param stream_info supplies the downstream stream info.
112
   */
113
  virtual absl::Status onOrcaLoadReport(const OrcaLoadReport& /*report*/,
114
                                        const StreamInfo::StreamInfo& /*stream_info*/) {
115
    return absl::OkStatus();
116
  }
117
};
118

            
119
using HostLbPolicyDataPtr = std::unique_ptr<HostLbPolicyData>;
120

            
121
class ClusterInfo;
122

            
123
/**
124
 * A description of an upstream host.
125
 */
126
class HostDescription {
127
public:
128
  using AddressVector = std::vector<Network::Address::InstanceConstSharedPtr>;
129
  using SharedConstAddressVector = std::shared_ptr<const AddressVector>;
130

            
131
201532
  virtual ~HostDescription() = default;
132

            
133
  /**
134
   * @return whether the host is a canary.
135
   */
136
  virtual bool canary() const PURE;
137

            
138
  /**
139
   * Update the canary status of the host.
140
   */
141
  virtual void canary(bool is_canary) PURE;
142

            
143
  /**
144
   * @return the metadata associated with this host
145
   */
146
  virtual MetadataConstSharedPtr metadata() const PURE;
147

            
148
  /**
149
   * @return the cached hash of the metadata associated with this host, or 0 if no metadata.
150
   */
151
  virtual std::size_t metadataHash() const PURE;
152

            
153
  /**
154
   * Set the current metadata.
155
   */
156
  virtual void metadata(MetadataConstSharedPtr new_metadata) PURE;
157

            
158
  /**
159
   * @return the cluster the host is a member of.
160
   */
161
  virtual const ClusterInfo& cluster() const PURE;
162

            
163
  /**
164
   * @return true if the cluster can create a connection for this priority, false otherwise.
165
   * @param priority the priority the connection would have.
166
   */
167
  virtual bool canCreateConnection(Upstream::ResourcePriority priority) const PURE;
168

            
169
  /**
170
   * @return the host's outlier detection monitor.
171
   */
172
  virtual Outlier::DetectorHostMonitor& outlierDetector() const PURE;
173

            
174
  /**
175
   * Set the host's outlier detector monitor. Outlier detector monitors are assumed to be thread
176
   * safe, however a new outlier detector monitor must be installed before the host is used across
177
   * threads. Thus, this routine should only be called on the main thread before the host is used
178
   * across threads.
179
   */
180
  virtual void setOutlierDetector(Outlier::DetectorHostMonitorPtr&& outlier_detector) PURE;
181

            
182
  /**
183
   * @return the host's health checker monitor.
184
   */
185
  virtual HealthCheckHostMonitor& healthChecker() const PURE;
186

            
187
  /**
188
   * Set the host's health checker monitor. Monitors are assumed to be thread safe, however
189
   * a new monitor must be installed before the host is used across threads. Thus,
190
   * this routine should only be called on the main thread before the host is used across threads.
191
   */
192
  virtual void setHealthChecker(HealthCheckHostMonitorPtr&& health_checker) PURE;
193

            
194
  /**
195
   * @return The hostname used as the host header for health checking.
196
   */
197
  virtual const std::string& hostnameForHealthChecks() const PURE;
198

            
199
  /**
200
   * @return the hostname associated with the host if any.
201
   * Empty string "" indicates that hostname is not a DNS name.
202
   */
203
  virtual const std::string& hostname() const PURE;
204

            
205
  /**
206
   * @return the transport socket factory responsible for this host.
207
   */
208
  virtual Network::UpstreamTransportSocketFactory& transportSocketFactory() const PURE;
209

            
210
  /**
211
   * @return the address used to connect to the host.
212
   */
213
  virtual Network::Address::InstanceConstSharedPtr address() const PURE;
214

            
215
  /**
216
   * @return nullptr, or a optional list of additional addresses which the host
217
   *         resolved to. These addresses may be used to create upstream
218
   *         connections if the primary address is unreachable.
219
   *
220
   * The address-list is returned as a shared_ptr<const vector<...>> because in
221
   * some implements of HostDescription, the address-list can be mutated
222
   * asynchronously. Those implementations must use a lock to ensure this is
223
   * safe. However this is not sufficient when returning the addressList by
224
   * reference.
225
   *
226
   * Caller must check return-value for nullptr before accessing the vector.
227
   */
228
  virtual SharedConstAddressVector addressListOrNull() const PURE;
229

            
230
  /**
231
   * @return host specific stats.
232
   */
233
  virtual HostStats& stats() const PURE;
234

            
235
  /**
236
   * @return custom stats for multi-dimensional load balancing.
237
   */
238
  virtual LoadMetricStats& loadMetricStats() const PURE;
239

            
240
  /**
241
   * @return the locality of the host (deployment specific). This will be the default instance if
242
   *         unknown.
243
   */
244
  virtual const envoy::config::core::v3::Locality& locality() const PURE;
245

            
246
  /**
247
   * @return the metadata associated with the locality endpoints the host belongs to.
248
   */
249
  virtual const MetadataConstSharedPtr localityMetadata() const PURE;
250

            
251
  /**
252
   * @return the human readable name of the host's locality zone as a StatName.
253
   */
254
  virtual Stats::StatName localityZoneStatName() const PURE;
255

            
256
  /**
257
   * @return the address used to health check the host.
258
   */
259
  virtual Network::Address::InstanceConstSharedPtr healthCheckAddress() const PURE;
260

            
261
  /**
262
   * @return the priority of the host.
263
   */
264
  virtual uint32_t priority() const PURE;
265

            
266
  /**
267
   * Set the current priority.
268
   */
269
  virtual void priority(uint32_t) PURE;
270

            
271
  /**
272
   * @return timestamp of when host has transitioned from unhealthy to
273
   *         healthy state via an active healthchecking.
274
   */
275
  virtual absl::optional<MonotonicTime> lastHcPassTime() const PURE;
276

            
277
  /**
278
   * Set the timestamp of when the host has transitioned from unhealthy to healthy state via an
279
   * active health checking.
280
   */
281
  virtual void setLastHcPassTime(MonotonicTime last_hc_pass_time) PURE;
282

            
283
  /**
284
   * Resolve the transport socket factory to use for connections to this host.
285
   * @param dest_address the destination address for the connection.
286
   * @param metadata optional endpoint metadata for matching.
287
   * @param transport_socket_options optional transport socket options containing
288
   *        filter state shared from downstream for per-connection matching.
289
   * @return the resolved transport socket factory.
290
   */
291
  virtual Network::UpstreamTransportSocketFactory& resolveTransportSocketFactory(
292
      const Network::Address::InstanceConstSharedPtr& dest_address,
293
      const envoy::config::core::v3::Metadata* metadata,
294
      Network::TransportSocketOptionsConstSharedPtr transport_socket_options = nullptr) const PURE;
295

            
296
  /**
297
   * Set load balancing policy related data to the host.
298
   * NOTE: this method should only be called at main thread before the host is used
299
   * across worker threads.
300
   */
301
  virtual void setLbPolicyData(HostLbPolicyDataPtr lb_policy_data) PURE;
302

            
303
  /**
304
   * Get the load balancing policy related data of the host.
305
   * @return the optional reference to the load balancing policy related data of the host.
306
   * Non-const reference is returned to allow the caller to modify the data if needed.
307
   * NOTE: the update to the data may be done at multiple threads concurrently and the caller
308
   * should ensure the thread safety of the data.
309
   */
310
  virtual OptRef<HostLbPolicyData> lbPolicyData() const PURE;
311

            
312
  /**
313
   * Get the typed load balancing policy related data of the host.
314
   * @return the optional reference to the typed load balancing policy related data of the host.
315
   */
316
433
  template <class HostLbPolicyDataType> OptRef<HostLbPolicyDataType> typedLbPolicyData() const {
317
433
    return makeOptRefFromPtr(dynamic_cast<HostLbPolicyDataType*>(lbPolicyData().ptr()));
318
433
  }
319
};
320

            
321
using HostDescriptionConstSharedPtr = std::shared_ptr<const HostDescription>;
322
using HostDescriptionOptConstRef = OptRef<const Upstream::HostDescription>;
323

            
324
246553
#define ALL_TRANSPORT_SOCKET_MATCH_STATS(COUNTER) COUNTER(total_match_count)
325

            
326
/**
327
 * The stats for transport socket match.
328
 */
329
struct TransportSocketMatchStats {
330
  ALL_TRANSPORT_SOCKET_MATCH_STATS(GENERATE_COUNTER_STRUCT)
331
};
332

            
333
/**
334
 * Library to determine what transport socket configuration to use for a given host.
335
 */
336
class TransportSocketMatcher {
337
public:
338
  struct MatchData {
339
    MatchData(Network::UpstreamTransportSocketFactory& factory, TransportSocketMatchStats& stats,
340
              std::string name)
341
247489
        : factory_(factory), stats_(stats), name_(std::move(name)) {}
342
    Network::UpstreamTransportSocketFactory& factory_;
343
    TransportSocketMatchStats& stats_;
344
    std::string name_;
345
  };
346
246512
  virtual ~TransportSocketMatcher() = default;
347

            
348
  /**
349
   * Resolve the transport socket configuration for a particular host.
350
   * @param endpoint_metadata the metadata of the given host.
351
   * @param locality_metadata the metadata of the host's locality.
352
   * @param transport_socket_options optional transport socket options from downstream connection
353
   *        that may contain SNI, ALPN, filter state, and other connection-specific data for
354
   *        transport socket selection.
355
   * @return the match information of the transport socket selected.
356
   */
357
  virtual MatchData resolve(
358
      const envoy::config::core::v3::Metadata* endpoint_metadata,
359
      const envoy::config::core::v3::Metadata* locality_metadata,
360
      Network::TransportSocketOptionsConstSharedPtr transport_socket_options = nullptr) const PURE;
361

            
362
  /**
363
   * @return true if all matches support ALPN, false otherwise.
364
   */
365
  virtual bool allMatchesSupportAlpn() const PURE;
366

            
367
  /**
368
   * @return true if the matcher uses filter state for transport socket selection. When true,
369
   *         transport socket resolution must be done per-connection with transport_socket_options.
370
   */
371
  virtual bool usesFilterState() const PURE;
372
};
373

            
374
using TransportSocketMatcherPtr = std::unique_ptr<TransportSocketMatcher>;
375

            
376
} // namespace Upstream
377
} // namespace Envoy