/proc/self/cwd/source/common/formatter/http_specific_formatter.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "source/common/formatter/http_specific_formatter.h" |
2 | | |
3 | | #include "source/common/common/assert.h" |
4 | | #include "source/common/common/empty_string.h" |
5 | | #include "source/common/common/fmt.h" |
6 | | #include "source/common/common/thread.h" |
7 | | #include "source/common/common/utility.h" |
8 | | #include "source/common/config/metadata.h" |
9 | | #include "source/common/formatter/substitution_formatter.h" |
10 | | #include "source/common/grpc/common.h" |
11 | | #include "source/common/grpc/status.h" |
12 | | #include "source/common/http/header_map_impl.h" |
13 | | #include "source/common/http/utility.h" |
14 | | #include "source/common/protobuf/message_validator_impl.h" |
15 | | #include "source/common/protobuf/utility.h" |
16 | | #include "source/common/runtime/runtime_features.h" |
17 | | #include "source/common/stream_info/utility.h" |
18 | | |
19 | | namespace Envoy { |
20 | | namespace Formatter { |
21 | | |
22 | | HttpFormatterContext::HttpFormatterContext(const Http::RequestHeaderMap* request_headers, |
23 | | const Http::ResponseHeaderMap* response_headers, |
24 | | const Http::ResponseTrailerMap* response_trailers, |
25 | | absl::string_view local_reply_body, |
26 | | AccessLog::AccessLogType log_type) |
27 | | : request_headers_(request_headers), response_headers_(response_headers), |
28 | | response_trailers_(response_trailers), local_reply_body_(local_reply_body), |
29 | 333k | log_type_(log_type) {} |
30 | | |
31 | 41.9k | const Http::RequestHeaderMap& HttpFormatterContext::requestHeaders() const { |
32 | 41.9k | return request_headers_ != nullptr ? *request_headers_ |
33 | 41.9k | : *Http::StaticEmptyHeaders::get().request_headers; |
34 | 41.9k | } |
35 | 8.77k | const Http::ResponseHeaderMap& HttpFormatterContext::responseHeaders() const { |
36 | 8.77k | return response_headers_ != nullptr ? *response_headers_ |
37 | 8.77k | : *Http::StaticEmptyHeaders::get().response_headers; |
38 | 8.77k | } |
39 | 5.88k | const Http::ResponseTrailerMap& HttpFormatterContext::responseTrailers() const { |
40 | 5.88k | return response_trailers_ != nullptr ? *response_trailers_ |
41 | 5.88k | : *Http::StaticEmptyHeaders::get().response_trailers; |
42 | 5.88k | } |
43 | | |
44 | 113k | absl::string_view HttpFormatterContext::localReplyBody() const { return local_reply_body_; } |
45 | 405 | AccessLog::AccessLogType HttpFormatterContext::accessLogType() const { return log_type_; } |
46 | | |
47 | | absl::optional<std::string> |
48 | | LocalReplyBodyFormatter::formatWithContext(const HttpFormatterContext& context, |
49 | 113k | const StreamInfo::StreamInfo&) const { |
50 | 113k | return std::string(context.localReplyBody()); |
51 | 113k | } |
52 | | |
53 | | ProtobufWkt::Value |
54 | | LocalReplyBodyFormatter::formatValueWithContext(const HttpFormatterContext& context, |
55 | 0 | const StreamInfo::StreamInfo&) const { |
56 | 0 | return ValueUtil::stringValue(std::string(context.localReplyBody())); |
57 | 0 | } |
58 | | |
59 | | absl::optional<std::string> |
60 | | AccessLogTypeFormatter::formatWithContext(const HttpFormatterContext& context, |
61 | 154 | const StreamInfo::StreamInfo&) const { |
62 | 154 | return AccessLogType_Name(context.accessLogType()); |
63 | 154 | } |
64 | | |
65 | | ProtobufWkt::Value |
66 | | AccessLogTypeFormatter::formatValueWithContext(const HttpFormatterContext& context, |
67 | 0 | const StreamInfo::StreamInfo&) const { |
68 | 0 | return ValueUtil::stringValue(AccessLogType_Name(context.accessLogType())); |
69 | 0 | } |
70 | | |
71 | | HeaderFormatter::HeaderFormatter(const std::string& main_header, |
72 | | const std::string& alternative_header, |
73 | | absl::optional<size_t> max_length) |
74 | 65.5k | : main_header_(main_header), alternative_header_(alternative_header), max_length_(max_length) {} |
75 | | |
76 | 48.9k | const Http::HeaderEntry* HeaderFormatter::findHeader(const Http::HeaderMap& headers) const { |
77 | 48.9k | const auto header = headers.get(main_header_); |
78 | | |
79 | 48.9k | if (header.empty() && !alternative_header_.get().empty()) { |
80 | 8.81k | const auto alternate_header = headers.get(alternative_header_); |
81 | | // TODO(https://github.com/envoyproxy/envoy/issues/13454): Potentially log all header values. |
82 | 8.81k | return alternate_header.empty() ? nullptr : alternate_header[0]; |
83 | 8.81k | } |
84 | | |
85 | 40.1k | return header.empty() ? nullptr : header[0]; |
86 | 48.9k | } |
87 | | |
88 | 48.9k | absl::optional<std::string> HeaderFormatter::format(const Http::HeaderMap& headers) const { |
89 | 48.9k | const Http::HeaderEntry* header = findHeader(headers); |
90 | 48.9k | if (!header) { |
91 | 31.3k | return absl::nullopt; |
92 | 31.3k | } |
93 | | |
94 | 17.6k | std::string val = std::string(header->value().getStringView()); |
95 | 17.6k | SubstitutionFormatUtils::truncate(val, max_length_); |
96 | 17.6k | return val; |
97 | 48.9k | } |
98 | | |
99 | 0 | ProtobufWkt::Value HeaderFormatter::formatValue(const Http::HeaderMap& headers) const { |
100 | 0 | const Http::HeaderEntry* header = findHeader(headers); |
101 | 0 | if (!header) { |
102 | 0 | return SubstitutionFormatUtils::unspecifiedValue(); |
103 | 0 | } |
104 | | |
105 | 0 | std::string val = std::string(header->value().getStringView()); |
106 | 0 | SubstitutionFormatUtils::truncate(val, max_length_); |
107 | 0 | return ValueUtil::stringValue(val); |
108 | 0 | } |
109 | | |
110 | | ResponseHeaderFormatter::ResponseHeaderFormatter(const std::string& main_header, |
111 | | const std::string& alternative_header, |
112 | | absl::optional<size_t> max_length) |
113 | 9.24k | : HeaderFormatter(main_header, alternative_header, max_length) {} |
114 | | |
115 | | absl::optional<std::string> |
116 | | ResponseHeaderFormatter::formatWithContext(const HttpFormatterContext& context, |
117 | 6.94k | const StreamInfo::StreamInfo&) const { |
118 | 6.94k | return HeaderFormatter::format(context.responseHeaders()); |
119 | 6.94k | } |
120 | | |
121 | | ProtobufWkt::Value |
122 | | ResponseHeaderFormatter::formatValueWithContext(const HttpFormatterContext& context, |
123 | 0 | const StreamInfo::StreamInfo&) const { |
124 | 0 | return HeaderFormatter::formatValue(context.responseHeaders()); |
125 | 0 | } |
126 | | |
127 | | RequestHeaderFormatter::RequestHeaderFormatter(const std::string& main_header, |
128 | | const std::string& alternative_header, |
129 | | absl::optional<size_t> max_length) |
130 | 47.7k | : HeaderFormatter(main_header, alternative_header, max_length) {} |
131 | | |
132 | | absl::optional<std::string> |
133 | | RequestHeaderFormatter::formatWithContext(const HttpFormatterContext& context, |
134 | 37.9k | const StreamInfo::StreamInfo&) const { |
135 | 37.9k | return HeaderFormatter::format(context.requestHeaders()); |
136 | 37.9k | } |
137 | | |
138 | | ProtobufWkt::Value |
139 | | RequestHeaderFormatter::formatValueWithContext(const HttpFormatterContext& context, |
140 | 0 | const StreamInfo::StreamInfo&) const { |
141 | 0 | return HeaderFormatter::formatValue(context.requestHeaders()); |
142 | 0 | } |
143 | | |
144 | | ResponseTrailerFormatter::ResponseTrailerFormatter(const std::string& main_header, |
145 | | const std::string& alternative_header, |
146 | | absl::optional<size_t> max_length) |
147 | 5.50k | : HeaderFormatter(main_header, alternative_header, max_length) {} |
148 | | |
149 | | absl::optional<std::string> |
150 | | ResponseTrailerFormatter::formatWithContext(const HttpFormatterContext& context, |
151 | 4.05k | const StreamInfo::StreamInfo&) const { |
152 | 4.05k | return HeaderFormatter::format(context.responseTrailers()); |
153 | 4.05k | } |
154 | | |
155 | | ProtobufWkt::Value |
156 | | ResponseTrailerFormatter::formatValueWithContext(const HttpFormatterContext& context, |
157 | 0 | const StreamInfo::StreamInfo&) const { |
158 | 0 | return HeaderFormatter::formatValue(context.responseTrailers()); |
159 | 0 | } |
160 | | |
161 | | HeadersByteSizeFormatter::HeadersByteSizeFormatter(const HeaderType header_type) |
162 | 1.12k | : header_type_(header_type) {} |
163 | | |
164 | | uint64_t HeadersByteSizeFormatter::extractHeadersByteSize( |
165 | | const Http::RequestHeaderMap& request_headers, const Http::ResponseHeaderMap& response_headers, |
166 | 1.03k | const Http::ResponseTrailerMap& response_trailers) const { |
167 | 1.03k | switch (header_type_) { |
168 | 154 | case HeaderType::RequestHeaders: |
169 | 154 | return request_headers.byteSize(); |
170 | 674 | case HeaderType::ResponseHeaders: |
171 | 674 | return response_headers.byteSize(); |
172 | 210 | case HeaderType::ResponseTrailers: |
173 | 210 | return response_trailers.byteSize(); |
174 | 1.03k | } |
175 | 0 | PANIC_DUE_TO_CORRUPT_ENUM; |
176 | 0 | } |
177 | | |
178 | | absl::optional<std::string> |
179 | | HeadersByteSizeFormatter::formatWithContext(const HttpFormatterContext& context, |
180 | 1.03k | const StreamInfo::StreamInfo&) const { |
181 | 1.03k | return absl::StrCat(extractHeadersByteSize(context.requestHeaders(), context.responseHeaders(), |
182 | 1.03k | context.responseTrailers())); |
183 | 1.03k | } |
184 | | |
185 | | ProtobufWkt::Value |
186 | | HeadersByteSizeFormatter::formatValueWithContext(const HttpFormatterContext& context, |
187 | 0 | const StreamInfo::StreamInfo&) const { |
188 | 0 | return ValueUtil::numberValue(extractHeadersByteSize( |
189 | 0 | context.requestHeaders(), context.responseHeaders(), context.responseTrailers())); |
190 | 0 | } |
191 | | |
192 | 2.13k | GrpcStatusFormatter::Format GrpcStatusFormatter::parseFormat(absl::string_view format) { |
193 | 2.13k | if (format.empty() || format == "CAMEL_STRING") { |
194 | 1.83k | return GrpcStatusFormatter::CamelString; |
195 | 1.83k | } |
196 | | |
197 | 300 | if (format == "SNAKE_STRING") { |
198 | 111 | return GrpcStatusFormatter::SnakeString; |
199 | 111 | } |
200 | 189 | if (format == "NUMBER") { |
201 | 139 | return GrpcStatusFormatter::Number; |
202 | 139 | } |
203 | | |
204 | 189 | throwEnvoyExceptionOrPanic( |
205 | 189 | "GrpcStatusFormatter only supports CAMEL_STRING, SNAKE_STRING or NUMBER."); |
206 | 189 | } |
207 | | |
208 | | GrpcStatusFormatter::GrpcStatusFormatter(const std::string& main_header, |
209 | | const std::string& alternative_header, |
210 | | absl::optional<size_t> max_length, Format format) |
211 | 3.02k | : HeaderFormatter(main_header, alternative_header, max_length), format_(format) {} |
212 | | |
213 | | absl::optional<std::string> |
214 | | GrpcStatusFormatter::formatWithContext(const HttpFormatterContext& context, |
215 | 2.49k | const StreamInfo::StreamInfo& info) const { |
216 | 2.49k | if (Runtime::runtimeFeatureEnabled( |
217 | 2.49k | "envoy.reloadable_features.validate_grpc_header_before_log_grpc_status")) { |
218 | 2.49k | if (!Grpc::Common::isGrpcRequestHeaders(context.requestHeaders())) { |
219 | 2.49k | return absl::nullopt; |
220 | 2.49k | } |
221 | 2.49k | } |
222 | 0 | const auto grpc_status = Grpc::Common::getGrpcStatus(context.responseTrailers(), |
223 | 0 | context.responseHeaders(), info, true); |
224 | 0 | if (!grpc_status.has_value()) { |
225 | 0 | return absl::nullopt; |
226 | 0 | } |
227 | 0 | switch (format_) { |
228 | 0 | case CamelString: { |
229 | 0 | const auto grpc_status_message = Grpc::Utility::grpcStatusToString(grpc_status.value()); |
230 | 0 | if (grpc_status_message == EMPTY_STRING || grpc_status_message == "InvalidCode") { |
231 | 0 | return std::to_string(grpc_status.value()); |
232 | 0 | } |
233 | 0 | return grpc_status_message; |
234 | 0 | } |
235 | 0 | case SnakeString: { |
236 | 0 | const auto grpc_status_message = |
237 | 0 | absl::StatusCodeToString(static_cast<absl::StatusCode>(grpc_status.value())); |
238 | 0 | if (grpc_status_message == EMPTY_STRING) { |
239 | 0 | return std::to_string(grpc_status.value()); |
240 | 0 | } |
241 | 0 | return grpc_status_message; |
242 | 0 | } |
243 | 0 | case Number: { |
244 | 0 | return std::to_string(grpc_status.value()); |
245 | 0 | } |
246 | 0 | } |
247 | 0 | PANIC_DUE_TO_CORRUPT_ENUM; |
248 | 0 | } |
249 | | |
250 | | ProtobufWkt::Value |
251 | | GrpcStatusFormatter::formatValueWithContext(const HttpFormatterContext& context, |
252 | 0 | const StreamInfo::StreamInfo& info) const { |
253 | 0 | if (Runtime::runtimeFeatureEnabled( |
254 | 0 | "envoy.reloadable_features.validate_grpc_header_before_log_grpc_status")) { |
255 | 0 | if (!Grpc::Common::isGrpcRequestHeaders(context.requestHeaders())) { |
256 | 0 | return SubstitutionFormatUtils::unspecifiedValue(); |
257 | 0 | } |
258 | 0 | } |
259 | 0 | const auto grpc_status = Grpc::Common::getGrpcStatus(context.responseTrailers(), |
260 | 0 | context.responseHeaders(), info, true); |
261 | 0 | if (!grpc_status.has_value()) { |
262 | 0 | return SubstitutionFormatUtils::unspecifiedValue(); |
263 | 0 | } |
264 | | |
265 | 0 | switch (format_) { |
266 | 0 | case CamelString: { |
267 | 0 | const auto grpc_status_message = Grpc::Utility::grpcStatusToString(grpc_status.value()); |
268 | 0 | if (grpc_status_message == EMPTY_STRING || grpc_status_message == "InvalidCode") { |
269 | 0 | return ValueUtil::stringValue(std::to_string(grpc_status.value())); |
270 | 0 | } |
271 | 0 | return ValueUtil::stringValue(grpc_status_message); |
272 | 0 | } |
273 | 0 | case SnakeString: { |
274 | 0 | const auto grpc_status_message = |
275 | 0 | absl::StatusCodeToString(static_cast<absl::StatusCode>(grpc_status.value())); |
276 | 0 | if (grpc_status_message == EMPTY_STRING) { |
277 | 0 | return ValueUtil::stringValue(std::to_string(grpc_status.value())); |
278 | 0 | } |
279 | 0 | return ValueUtil::stringValue(grpc_status_message); |
280 | 0 | } |
281 | 0 | case Number: { |
282 | 0 | return ValueUtil::numberValue(grpc_status.value()); |
283 | 0 | } |
284 | 0 | } |
285 | 0 | PANIC_DUE_TO_CORRUPT_ENUM; |
286 | 0 | } |
287 | | |
288 | | StreamInfoRequestHeaderFormatter::StreamInfoRequestHeaderFormatter( |
289 | | const std::string& main_header, const std::string& alternative_header, |
290 | | absl::optional<size_t> max_length) |
291 | 0 | : HeaderFormatter(main_header, alternative_header, max_length) {} |
292 | | |
293 | | absl::optional<std::string> StreamInfoRequestHeaderFormatter::formatWithContext( |
294 | 0 | const HttpFormatterContext&, const StreamInfo::StreamInfo& stream_info) const { |
295 | 0 | return HeaderFormatter::format(*stream_info.getRequestHeaders()); |
296 | 0 | } |
297 | | |
298 | | ProtobufWkt::Value StreamInfoRequestHeaderFormatter::formatValueWithContext( |
299 | 0 | const HttpFormatterContext&, const StreamInfo::StreamInfo& stream_info) const { |
300 | 0 | return HeaderFormatter::formatValue(*stream_info.getRequestHeaders()); |
301 | 0 | } |
302 | | |
303 | | const HttpBuiltInCommandParser::FormatterProviderLookupTbl& |
304 | 359k | HttpBuiltInCommandParser::getKnownFormatters() { |
305 | 359k | CONSTRUCT_ON_FIRST_USE( |
306 | 359k | FormatterProviderLookupTbl, |
307 | 359k | {{"REQ", |
308 | 359k | {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, |
309 | 359k | [](const std::string& format, absl::optional<size_t>& max_length) { |
310 | 359k | std::string main_header, alternative_header; |
311 | | |
312 | 359k | SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header, alternative_header); |
313 | | |
314 | 359k | return std::make_unique<RequestHeaderFormatter>(main_header, alternative_header, |
315 | 359k | max_length); |
316 | 359k | }}}, |
317 | 359k | {"RESP", |
318 | 359k | {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, |
319 | 359k | [](const std::string& format, absl::optional<size_t>& max_length) { |
320 | 359k | std::string main_header, alternative_header; |
321 | | |
322 | 359k | SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header, alternative_header); |
323 | | |
324 | 359k | return std::make_unique<ResponseHeaderFormatter>(main_header, alternative_header, |
325 | 359k | max_length); |
326 | 359k | }}}, |
327 | 359k | {"TRAILER", |
328 | 359k | {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, |
329 | 359k | [](const std::string& format, absl::optional<size_t>& max_length) { |
330 | 359k | std::string main_header, alternative_header; |
331 | | |
332 | 359k | SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header, alternative_header); |
333 | | |
334 | 359k | return std::make_unique<ResponseTrailerFormatter>(main_header, alternative_header, |
335 | 359k | max_length); |
336 | 359k | }}}, |
337 | 359k | {"LOCAL_REPLY_BODY", |
338 | 359k | {CommandSyntaxChecker::COMMAND_ONLY, |
339 | 359k | [](const std::string&, absl::optional<size_t>&) { |
340 | 359k | return std::make_unique<LocalReplyBodyFormatter>(); |
341 | 359k | }}}, |
342 | 359k | {"ACCESS_LOG_TYPE", |
343 | 359k | {CommandSyntaxChecker::COMMAND_ONLY, |
344 | 359k | [](const std::string&, absl::optional<size_t>&) { |
345 | 359k | return std::make_unique<AccessLogTypeFormatter>(); |
346 | 359k | }}}, |
347 | 359k | {"GRPC_STATUS", |
348 | 359k | {CommandSyntaxChecker::PARAMS_OPTIONAL, |
349 | 359k | [](const std::string& format, const absl::optional<size_t>&) { |
350 | 359k | return std::make_unique<GrpcStatusFormatter>("grpc-status", "", absl::optional<size_t>(), |
351 | 359k | GrpcStatusFormatter::parseFormat(format)); |
352 | 359k | }}}, |
353 | 359k | {"GRPC_STATUS_NUMBER", |
354 | 359k | {CommandSyntaxChecker::COMMAND_ONLY, |
355 | 359k | [](const std::string&, const absl::optional<size_t>&) { |
356 | 359k | return std::make_unique<GrpcStatusFormatter>("grpc-status", "", absl::optional<size_t>(), |
357 | 359k | GrpcStatusFormatter::Number); |
358 | 359k | }}}, |
359 | 359k | {"REQUEST_HEADERS_BYTES", |
360 | 359k | {CommandSyntaxChecker::COMMAND_ONLY, |
361 | 359k | [](const std::string&, absl::optional<size_t>&) { |
362 | 359k | return std::make_unique<HeadersByteSizeFormatter>( |
363 | 359k | HeadersByteSizeFormatter::HeaderType::RequestHeaders); |
364 | 359k | }}}, |
365 | 359k | {"RESPONSE_HEADERS_BYTES", |
366 | 359k | {CommandSyntaxChecker::COMMAND_ONLY, |
367 | 359k | [](const std::string&, absl::optional<size_t>&) { |
368 | 359k | return std::make_unique<HeadersByteSizeFormatter>( |
369 | 359k | HeadersByteSizeFormatter::HeaderType::ResponseHeaders); |
370 | 359k | }}}, |
371 | 359k | {"RESPONSE_TRAILERS_BYTES", |
372 | 359k | {CommandSyntaxChecker::COMMAND_ONLY, |
373 | 359k | [](const std::string&, absl::optional<size_t>&) { |
374 | 359k | return std::make_unique<HeadersByteSizeFormatter>( |
375 | 359k | HeadersByteSizeFormatter::HeaderType::ResponseTrailers); |
376 | 359k | }}}, |
377 | 359k | {"STREAM_INFO_REQ", |
378 | 359k | {CommandSyntaxChecker::PARAMS_REQUIRED | CommandSyntaxChecker::LENGTH_ALLOWED, |
379 | 359k | [](const std::string& format, absl::optional<size_t>& max_length) { |
380 | 359k | std::string main_header, alternative_header; |
381 | 359k | SubstitutionFormatUtils::parseSubcommandHeaders(format, main_header, alternative_header); |
382 | | |
383 | 359k | return std::make_unique<RequestHeaderFormatter>(main_header, alternative_header, |
384 | 359k | max_length); |
385 | 359k | }}}}); |
386 | 359k | } |
387 | | |
388 | | FormatterProviderPtr HttpBuiltInCommandParser::parse(const std::string& command, |
389 | | const std::string& subcommand, |
390 | 359k | absl::optional<size_t>& max_length) const { |
391 | 359k | const FormatterProviderLookupTbl& providers = getKnownFormatters(); |
392 | | |
393 | 359k | auto it = providers.find(command); |
394 | | |
395 | 359k | if (it == providers.end()) { |
396 | 275k | return nullptr; |
397 | 275k | } |
398 | | |
399 | | // Check flags for the command. |
400 | 84.0k | CommandSyntaxChecker::verifySyntax((*it).second.first, command, subcommand, max_length); |
401 | | |
402 | | // Create a pointer to the formatter by calling a function |
403 | | // associated with formatter's name. |
404 | 84.0k | return (*it).second.second(subcommand, max_length); |
405 | 359k | } |
406 | | |
407 | | REGISTER_BUILT_IN_COMMAND_PARSER(HttpFormatterContext, HttpBuiltInCommandParser); |
408 | | |
409 | | static const std::string DEFAULT_FORMAT = |
410 | | "[%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" " |
411 | | "%RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% " |
412 | | "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% " |
413 | | "\"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" " |
414 | | "\"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\"\n"; |
415 | | |
416 | 5.43k | FormatterPtr HttpSubstitutionFormatUtils::defaultSubstitutionFormatter() { |
417 | 5.43k | return std::make_unique<Envoy::Formatter::FormatterImpl>(DEFAULT_FORMAT, false); |
418 | 5.43k | } |
419 | | |
420 | | } // namespace Formatter |
421 | | } // namespace Envoy |