Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/common/stream_info/utility.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include <chrono>
4
#include <cstdint>
5
6
#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.pb.h"
7
#include "envoy/http/codes.h"
8
#include "envoy/stream_info/stream_info.h"
9
10
#include "absl/container/node_hash_map.h"
11
12
namespace Envoy {
13
namespace StreamInfo {
14
15
class CustomResponseFlag {
16
public:
17
  CustomResponseFlag(absl::string_view flag, absl::string_view flag_long);
18
0
  ResponseFlag flag() const { return flag_; }
19
20
private:
21
  ResponseFlag flag_;
22
};
23
24
// Register a custom response flag by specifying the flag and the long name of the flag.
25
// This macro should only be used in source files to register a flag.
26
#define REGISTER_CUSTOM_RESPONSE_FLAG(flag_short_string, flag_long_string)                         \
27
  static CustomResponseFlag /* NOLINT(fuchsia-statically-constructed-objects) */                   \
28
      registered_##flag_short_string{#flag_short_string, #flag_long_string};
29
30
// Get the registered flag value. This macro should only be used when calling the
31
// 'setResponseFlag' method in the StreamInfo class.
32
// NOTE: Never use this macro to initialize another static variable.
33
// Basically, this macro should only be used in the same source file where the flag is
34
// registered.
35
// If you want to use one flag in multiple files, you can declare a static function in
36
// the header file and define it in the source file to return the flag value. Here is an
37
// example (NOTE: this function should obey the same rule as the CUSTOM_RESPONSE_FLAG
38
// macro and cannot be used to initialize another static variable):
39
//
40
// // header.h
41
// ResponseFlag getRegisteredFlag();
42
// // source.cc
43
// REGISTER_CUSTOM_RESPONSE_FLAG(CF, CustomFlag);
44
// ResponseFlag getRegisteredFlag() { return CUSTOM_RESPONSE_FLAG(CF); }
45
#define CUSTOM_RESPONSE_FLAG(flag_short_string) registered_##flag_short_string.flag()
46
47
/**
48
 * Util class for ResponseFlags.
49
 */
50
class ResponseFlagUtils {
51
public:
52
  static const std::string toString(const StreamInfo& stream_info);
53
  static const std::string toShortString(const StreamInfo& stream_info);
54
  static absl::optional<ResponseFlag> toResponseFlag(absl::string_view response_flag);
55
56
  struct FlagStrings {
57
    absl::string_view short_string_;
58
    absl::string_view long_string_; // PascalCase string
59
    ResponseFlag flag_;
60
  };
61
62
  struct FlagLongString {
63
    ResponseFlag flag_;
64
    std::string long_string_; // PascalCase string
65
  };
66
67
  using ResponseFlagsVecType = std::vector<FlagStrings>;
68
  // Node hash map is used to avoid the key/value pair pointer change of the string_view when the
69
  // map is resized. And the performance is not a concern here because the map is only used when
70
  // loading the config.
71
  using ResponseFlagsMapType = absl::node_hash_map<std::string, FlagLongString>;
72
  static const ResponseFlagsVecType& responseFlagsVec();
73
  static const ResponseFlagsMapType& responseFlagsMap();
74
75
  // When adding a new flag, it's required to update the access log docs and the string
76
  // mapping below - ``CORE_RESPONSE_FLAGS``.
77
  constexpr static absl::string_view NONE = "-";
78
  constexpr static absl::string_view DOWNSTREAM_CONNECTION_TERMINATION = "DC";
79
  constexpr static absl::string_view FAILED_LOCAL_HEALTH_CHECK = "LH";
80
  constexpr static absl::string_view NO_HEALTHY_UPSTREAM = "UH";
81
  constexpr static absl::string_view UPSTREAM_REQUEST_TIMEOUT = "UT";
82
  constexpr static absl::string_view LOCAL_RESET = "LR";
83
  constexpr static absl::string_view UPSTREAM_REMOTE_RESET = "UR";
84
  constexpr static absl::string_view UPSTREAM_CONNECTION_FAILURE = "UF";
85
  constexpr static absl::string_view UPSTREAM_CONNECTION_TERMINATION = "UC";
86
  constexpr static absl::string_view UPSTREAM_OVERFLOW = "UO";
87
  constexpr static absl::string_view UPSTREAM_RETRY_LIMIT_EXCEEDED = "URX";
88
  constexpr static absl::string_view NO_ROUTE_FOUND = "NR";
89
  constexpr static absl::string_view DELAY_INJECTED = "DI";
90
  constexpr static absl::string_view FAULT_INJECTED = "FI";
91
  constexpr static absl::string_view RATE_LIMITED = "RL";
92
  constexpr static absl::string_view UNAUTHORIZED_EXTERNAL_SERVICE = "UAEX";
93
  constexpr static absl::string_view RATELIMIT_SERVICE_ERROR = "RLSE";
94
  constexpr static absl::string_view STREAM_IDLE_TIMEOUT = "SI";
95
  constexpr static absl::string_view INVALID_ENVOY_REQUEST_HEADERS = "IH";
96
  constexpr static absl::string_view DOWNSTREAM_PROTOCOL_ERROR = "DPE";
97
  constexpr static absl::string_view UPSTREAM_MAX_STREAM_DURATION_REACHED = "UMSDR";
98
  constexpr static absl::string_view RESPONSE_FROM_CACHE_FILTER = "RFCF";
99
  constexpr static absl::string_view NO_FILTER_CONFIG_FOUND = "NFCF";
100
  constexpr static absl::string_view DURATION_TIMEOUT = "DT";
101
  constexpr static absl::string_view UPSTREAM_PROTOCOL_ERROR = "UPE";
102
  constexpr static absl::string_view NO_CLUSTER_FOUND = "NC";
103
  constexpr static absl::string_view OVERLOAD_MANAGER = "OM";
104
  constexpr static absl::string_view DNS_FAIL = "DF";
105
  constexpr static absl::string_view DROP_OVERLOAD = "DO";
106
  constexpr static absl::string_view DOWNSTREAM_REMOTE_RESET = "DR";
107
108
  constexpr static absl::string_view DOWNSTREAM_CONNECTION_TERMINATION_LONG =
109
      "DownstreamConnectionTermination";
110
  constexpr static absl::string_view FAILED_LOCAL_HEALTH_CHECK_LONG = "FailedLocalHealthCheck";
111
  constexpr static absl::string_view NO_HEALTHY_UPSTREAM_LONG = "NoHealthyUpstream";
112
  constexpr static absl::string_view UPSTREAM_REQUEST_TIMEOUT_LONG = "UpstreamRequestTimeout";
113
  constexpr static absl::string_view LOCAL_RESET_LONG = "LocalReset";
114
  constexpr static absl::string_view UPSTREAM_REMOTE_RESET_LONG = "UpstreamRemoteReset";
115
  constexpr static absl::string_view UPSTREAM_CONNECTION_FAILURE_LONG = "UpstreamConnectionFailure";
116
  constexpr static absl::string_view UPSTREAM_CONNECTION_TERMINATION_LONG =
117
      "UpstreamConnectionTermination";
118
  constexpr static absl::string_view UPSTREAM_OVERFLOW_LONG = "UpstreamOverflow";
119
  constexpr static absl::string_view UPSTREAM_RETRY_LIMIT_EXCEEDED_LONG =
120
      "UpstreamRetryLimitExceeded";
121
  constexpr static absl::string_view NO_ROUTE_FOUND_LONG = "NoRouteFound";
122
  constexpr static absl::string_view DELAY_INJECTED_LONG = "DelayInjected";
123
  constexpr static absl::string_view FAULT_INJECTED_LONG = "FaultInjected";
124
  constexpr static absl::string_view RATE_LIMITED_LONG = "RateLimited";
125
  constexpr static absl::string_view UNAUTHORIZED_EXTERNAL_SERVICE_LONG =
126
      "UnauthorizedExternalService";
127
  constexpr static absl::string_view RATELIMIT_SERVICE_ERROR_LONG = "RateLimitServiceError";
128
  constexpr static absl::string_view STREAM_IDLE_TIMEOUT_LONG = "StreamIdleTimeout";
129
  constexpr static absl::string_view INVALID_ENVOY_REQUEST_HEADERS_LONG =
130
      "InvalidEnvoyRequestHeaders";
131
  constexpr static absl::string_view DOWNSTREAM_PROTOCOL_ERROR_LONG = "DownstreamProtocolError";
132
  constexpr static absl::string_view UPSTREAM_MAX_STREAM_DURATION_REACHED_LONG =
133
      "UpstreamMaxStreamDurationReached";
134
  constexpr static absl::string_view RESPONSE_FROM_CACHE_FILTER_LONG = "ResponseFromCacheFilter";
135
  constexpr static absl::string_view NO_FILTER_CONFIG_FOUND_LONG = "NoFilterConfigFound";
136
  constexpr static absl::string_view DURATION_TIMEOUT_LONG = "DurationTimeout";
137
  constexpr static absl::string_view UPSTREAM_PROTOCOL_ERROR_LONG = "UpstreamProtocolError";
138
  constexpr static absl::string_view NO_CLUSTER_FOUND_LONG = "NoClusterFound";
139
  constexpr static absl::string_view OVERLOAD_MANAGER_LONG = "OverloadManagerTerminated";
140
  constexpr static absl::string_view DNS_FAIL_LONG = "DnsResolutionFailed";
141
  constexpr static absl::string_view DROP_OVERLOAD_LONG = "DropOverload";
142
  constexpr static absl::string_view DOWNSTREAM_REMOTE_RESET_LONG = "DownstreamRemoteReset";
143
144
  static constexpr std::array CORE_RESPONSE_FLAGS{
145
      FlagStrings{FAILED_LOCAL_HEALTH_CHECK, FAILED_LOCAL_HEALTH_CHECK_LONG,
146
                  CoreResponseFlag::FailedLocalHealthCheck},
147
      FlagStrings{NO_HEALTHY_UPSTREAM, NO_HEALTHY_UPSTREAM_LONG,
148
                  CoreResponseFlag::NoHealthyUpstream},
149
      FlagStrings{UPSTREAM_REQUEST_TIMEOUT, UPSTREAM_REQUEST_TIMEOUT_LONG,
150
                  CoreResponseFlag::UpstreamRequestTimeout},
151
      FlagStrings{LOCAL_RESET, LOCAL_RESET_LONG, CoreResponseFlag::LocalReset},
152
      FlagStrings{UPSTREAM_REMOTE_RESET, UPSTREAM_REMOTE_RESET_LONG,
153
                  CoreResponseFlag::UpstreamRemoteReset},
154
      FlagStrings{UPSTREAM_CONNECTION_FAILURE, UPSTREAM_CONNECTION_FAILURE_LONG,
155
                  CoreResponseFlag::UpstreamConnectionFailure},
156
      FlagStrings{UPSTREAM_CONNECTION_TERMINATION, UPSTREAM_CONNECTION_TERMINATION_LONG,
157
                  CoreResponseFlag::UpstreamConnectionTermination},
158
      FlagStrings{UPSTREAM_OVERFLOW, UPSTREAM_OVERFLOW_LONG, CoreResponseFlag::UpstreamOverflow},
159
      FlagStrings{NO_ROUTE_FOUND, NO_ROUTE_FOUND_LONG, CoreResponseFlag::NoRouteFound},
160
      FlagStrings{DELAY_INJECTED, DELAY_INJECTED_LONG, CoreResponseFlag::DelayInjected},
161
      FlagStrings{FAULT_INJECTED, FAULT_INJECTED_LONG, CoreResponseFlag::FaultInjected},
162
      FlagStrings{RATE_LIMITED, RATE_LIMITED_LONG, CoreResponseFlag::RateLimited},
163
      FlagStrings{UNAUTHORIZED_EXTERNAL_SERVICE, UNAUTHORIZED_EXTERNAL_SERVICE_LONG,
164
                  CoreResponseFlag::UnauthorizedExternalService},
165
      FlagStrings{RATELIMIT_SERVICE_ERROR, RATELIMIT_SERVICE_ERROR_LONG,
166
                  CoreResponseFlag::RateLimitServiceError},
167
      FlagStrings{DOWNSTREAM_CONNECTION_TERMINATION, DOWNSTREAM_CONNECTION_TERMINATION_LONG,
168
                  CoreResponseFlag::DownstreamConnectionTermination},
169
      FlagStrings{UPSTREAM_RETRY_LIMIT_EXCEEDED, UPSTREAM_RETRY_LIMIT_EXCEEDED_LONG,
170
                  CoreResponseFlag::UpstreamRetryLimitExceeded},
171
      FlagStrings{STREAM_IDLE_TIMEOUT, STREAM_IDLE_TIMEOUT_LONG,
172
                  CoreResponseFlag::StreamIdleTimeout},
173
      FlagStrings{INVALID_ENVOY_REQUEST_HEADERS, INVALID_ENVOY_REQUEST_HEADERS_LONG,
174
                  CoreResponseFlag::InvalidEnvoyRequestHeaders},
175
      FlagStrings{DOWNSTREAM_PROTOCOL_ERROR, DOWNSTREAM_PROTOCOL_ERROR_LONG,
176
                  CoreResponseFlag::DownstreamProtocolError},
177
      FlagStrings{UPSTREAM_MAX_STREAM_DURATION_REACHED, UPSTREAM_MAX_STREAM_DURATION_REACHED_LONG,
178
                  CoreResponseFlag::UpstreamMaxStreamDurationReached},
179
      FlagStrings{RESPONSE_FROM_CACHE_FILTER, RESPONSE_FROM_CACHE_FILTER_LONG,
180
                  CoreResponseFlag::ResponseFromCacheFilter},
181
      FlagStrings{NO_FILTER_CONFIG_FOUND, NO_FILTER_CONFIG_FOUND_LONG,
182
                  CoreResponseFlag::NoFilterConfigFound},
183
      FlagStrings{DURATION_TIMEOUT, DURATION_TIMEOUT_LONG, CoreResponseFlag::DurationTimeout},
184
      FlagStrings{UPSTREAM_PROTOCOL_ERROR, UPSTREAM_PROTOCOL_ERROR_LONG,
185
                  CoreResponseFlag::UpstreamProtocolError},
186
      FlagStrings{NO_CLUSTER_FOUND, NO_CLUSTER_FOUND_LONG, CoreResponseFlag::NoClusterFound},
187
      FlagStrings{OVERLOAD_MANAGER, OVERLOAD_MANAGER_LONG, CoreResponseFlag::OverloadManager},
188
      FlagStrings{DNS_FAIL, DNS_FAIL_LONG, CoreResponseFlag::DnsResolutionFailed},
189
      FlagStrings{DROP_OVERLOAD, DROP_OVERLOAD_LONG, CoreResponseFlag::DropOverLoad},
190
      FlagStrings{DOWNSTREAM_REMOTE_RESET, DOWNSTREAM_REMOTE_RESET_LONG,
191
                  CoreResponseFlag::DownstreamRemoteReset},
192
  };
193
194
private:
195
  friend class CustomResponseFlag;
196
197
  static const std::string toString(const StreamInfo& stream_info, bool use_long_name);
198
199
  /**
200
   * Register a custom response flag.
201
   * @param flag supplies the flag to register. It should be an all upper case string with only
202
   * multiple characters.
203
   * @param flag_long supplies the long name of the flag to register. It should be PascalCase
204
   * string.
205
   * @return uint16_t the flag value.
206
   */
207
  static ResponseFlag registerCustomFlag(absl::string_view flag, absl::string_view flag_long);
208
  static ResponseFlagsMapType& mutableResponseFlagsMap();
209
};
210
211
class TimingUtility {
212
public:
213
54
  TimingUtility(const StreamInfo& info) : stream_info_(info) {}
214
215
  absl::optional<std::chrono::nanoseconds> firstUpstreamTxByteSent();
216
  absl::optional<std::chrono::nanoseconds> lastUpstreamTxByteSent();
217
  absl::optional<std::chrono::nanoseconds> firstUpstreamRxByteReceived();
218
  absl::optional<std::chrono::nanoseconds> lastUpstreamRxByteReceived();
219
  absl::optional<std::chrono::nanoseconds> upstreamHandshakeComplete();
220
  absl::optional<std::chrono::nanoseconds> firstDownstreamTxByteSent();
221
  absl::optional<std::chrono::nanoseconds> lastDownstreamTxByteSent();
222
  absl::optional<std::chrono::nanoseconds> lastDownstreamRxByteReceived();
223
  absl::optional<std::chrono::nanoseconds> downstreamHandshakeComplete();
224
  absl::optional<std::chrono::nanoseconds> lastDownstreamAckReceived();
225
226
private:
227
  const StreamInfo& stream_info_;
228
};
229
230
/**
231
 * Utility class for StreamInfo.
232
 */
233
class Utility {
234
public:
235
  /**
236
   * @param address supplies the downstream address.
237
   * @return a properly formatted address for logs, header expansion, etc.
238
   */
239
  static const std::string&
240
  formatDownstreamAddressNoPort(const Network::Address::Instance& address);
241
242
  /**
243
   * @param address supplies the downstream address.
244
   * @return a port, extracted from the provided downstream address for logs, header expansion, etc.
245
   */
246
  static const std::string
247
  formatDownstreamAddressJustPort(const Network::Address::Instance& address);
248
249
  /**
250
   * @param address supplies the downstream address.
251
   * @return a port, extracted from the provided downstream address for logs, header expansion, etc.
252
   */
253
  static absl::optional<uint32_t>
254
  extractDownstreamAddressJustPort(const Network::Address::Instance& address);
255
};
256
257
// Static utils for creating, consuming, and producing strings from the
258
// Proxy-Status HTTP response header.
259
class ProxyStatusUtils {
260
public:
261
  // Returns a Proxy-Status proxy name string, configured according to |proxy_status_config|.
262
  // If |proxy_status_config| has not been set, defaults to |server_name|.
263
  static const std::string
264
  makeProxyName(absl::string_view node_id, absl::string_view server_name,
265
                const envoy::extensions::filters::network::http_connection_manager::v3::
266
                    HttpConnectionManager::ProxyStatusConfig* proxy_status_config);
267
268
  // Returns a Proxy-Status request header string, of the form:
269
  //
270
  //     <server_name>; error=<error_type>; details=<details>
271
  //
272
  // where:
273
  //   - node_id     is either the method argument, or the name of the proxy
274
  //                 in |node_id|,
275
  //   - error       is the error in |error|,
276
  //   - details     is |stream_info.responseCodeDetails()|, but the field is
277
  //                 present only if configured in |proxy_status_config|.
278
  static const std::string
279
  makeProxyStatusHeader(const StreamInfo& stream_info, ProxyStatusError error,
280
                        absl::string_view proxy_name,
281
                        const envoy::extensions::filters::network::http_connection_manager::v3::
282
                            HttpConnectionManager::ProxyStatusConfig& proxy_status_config);
283
284
  // Returns a view into the string representation of a given ProxyStatusError
285
  // enum.
286
  static const absl::string_view proxyStatusErrorToString(ProxyStatusError proxy_status);
287
288
  // Reads |stream_info.responseFlag| and returns an applicable ProxyStatusError, or nullopt
289
  // if no ProxyStatusError is applicable.
290
  static const absl::optional<ProxyStatusError> fromStreamInfo(const StreamInfo& stream_info);
291
292
  // Returns the recommended HTTP status code for a ProxyStatusError, or nullopt
293
  // if no HTTP status code is applicable.
294
  //
295
  // See
296
  // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-proxy-status-05#section-2.1.1 :
297
  //
298
  // > Each Proxy Error Type has a Recommended HTTP Status Code. When
299
  // > generating a HTTP response containing "error", its HTTP status code
300
  // > SHOULD be set to the Recommended HTTP Status Code.
301
  static const absl::optional<Http::Code>
302
  recommendedHttpStatusCode(const ProxyStatusError proxy_status);
303
304
  constexpr static absl::string_view DNS_TIMEOUT = "dns_timeout";
305
  constexpr static absl::string_view DNS_ERROR = "dns_error";
306
  constexpr static absl::string_view DESTINATION_NOT_FOUND = "destination_not_found";
307
  constexpr static absl::string_view DESTINATION_UNAVAILABLE = "destination_unavailable";
308
  constexpr static absl::string_view DESTINATION_IP_PROHIBITED = "destination_ip_prohibited";
309
  constexpr static absl::string_view DESTINATION_IP_UNROUTABLE = "destination_ip_unroutable";
310
  constexpr static absl::string_view CONNECTION_REFUSED = "connection_refused";
311
  constexpr static absl::string_view CONNECTION_TERMINATED = "connection_terminated";
312
  constexpr static absl::string_view CONNECTION_TIMEOUT = "connection_timeout";
313
  constexpr static absl::string_view CONNECTION_READ_TIMEOUT = "connection_read_timeout";
314
  constexpr static absl::string_view CONNECTION_WRITE_TIMEOUT = "connection_write_timeout";
315
  constexpr static absl::string_view CONNECTION_LIMIT_REACHED = "connection_limit_reached";
316
  constexpr static absl::string_view TLS_PROTOCOL_ERROR = "tls_protocol_error";
317
  constexpr static absl::string_view TLS_CERTIFICATE_ERROR = "tls_certificate_error";
318
  constexpr static absl::string_view TLS_ALERT_RECEIVED = "tls_alert_received";
319
  constexpr static absl::string_view HTTP_REQUEST_ERROR = "http_request_error";
320
  constexpr static absl::string_view HTTP_REQUEST_DENIED = "http_request_denied";
321
  constexpr static absl::string_view HTTP_RESPONSE_INCOMPLETE = "http_response_incomplete";
322
  constexpr static absl::string_view HTTP_RESPONSE_HEADER_SECTION_SIZE =
323
      "http_response_header_section_size";
324
  constexpr static absl::string_view HTTP_RESPONSE_HEADER_SIZE = "http_response_header_size";
325
  constexpr static absl::string_view HTTP_RESPONSE_BODY_SIZE = "http_response_body_size";
326
  constexpr static absl::string_view HTTP_RESPONSE_TRAILER_SECTION_SIZE =
327
      "http_response_trailer_section_size";
328
  constexpr static absl::string_view HTTP_RESPONSE_TRAILER_SIZE = "http_response_trailer_size";
329
  constexpr static absl::string_view HTTP_RESPONSE_TRANSFER_CODING =
330
      "http_response_transfer_coding";
331
  constexpr static absl::string_view HTTP_RESPONSE_CONTENT_CODING = "http_response_content_coding";
332
  constexpr static absl::string_view HTTP_RESPONSE_TIMEOUT = "http_response_timeout";
333
  constexpr static absl::string_view HTTP_UPGRADE_FAILED = "http_upgrade_failed";
334
  constexpr static absl::string_view HTTP_PROTOCOL_ERROR = "http_protocol_error";
335
  constexpr static absl::string_view PROXY_INTERNAL_RESPONSE = "proxy_internal_response";
336
  constexpr static absl::string_view PROXY_INTERNAL_ERROR = "proxy_internal_error";
337
  constexpr static absl::string_view PROXY_CONFIGURATION_ERROR = "proxy_configuration_error";
338
  constexpr static absl::string_view PROXY_LOOP_DETECTED = "proxy_loop_detected";
339
};
340
341
} // namespace StreamInfo
342
} // namespace Envoy