|
1 |
| -#include <ugrpc/impl/protobuf_utils.hpp> |
2 |
| - |
3 |
| -#include <exception> |
4 |
| -#include <memory> |
5 |
| -#include <unordered_set> |
| 1 | +#include <userver/ugrpc/protobuf_logging.hpp> |
6 | 2 |
|
7 | 3 | #include <google/protobuf/descriptor.pb.h>
|
8 |
| -#include <google/protobuf/io/zero_copy_stream_impl_lite.h> |
9 | 4 | #include <google/protobuf/text_format.h>
|
10 |
| -#include <grpcpp/support/config.h> |
11 | 5 | #include <boost/container/small_vector.hpp>
|
12 | 6 |
|
13 | 7 | #include <userver/compiler/thread_local.hpp>
|
| 8 | +#include <userver/ugrpc/status_codes.hpp> |
| 9 | +#include <userver/ugrpc/status_utils.hpp> |
14 | 10 | #include <userver/utils/assert.hpp>
|
15 | 11 | #include <userver/utils/numeric_cast.hpp>
|
16 | 12 |
|
@@ -189,31 +185,89 @@ compiler::ThreadLocal kDebugStringPrinter = [] { return DebugStringPrinter{}; };
|
189 | 185 |
|
190 | 186 | } // namespace
|
191 | 187 |
|
| 188 | +void Print(const google::protobuf::Message& message, google::protobuf::io::ZeroCopyOutputStream& output_stream) { |
| 189 | + auto printer = kDebugStringPrinter.Use(); |
| 190 | + printer->RegisterDebugRedactPrinters(*message.GetDescriptor()); |
| 191 | + printer->Print(message, output_stream); |
| 192 | +} |
| 193 | + |
| 194 | +} // namespace ugrpc::impl |
| 195 | + |
| 196 | +namespace ugrpc { |
| 197 | + |
192 | 198 | std::string ToLimitedDebugString(const google::protobuf::Message& message, std::size_t limit) {
|
193 | 199 | boost::container::small_vector<char, 1024> output_buffer{limit, boost::container::default_init};
|
194 | 200 | google::protobuf::io::ArrayOutputStream output_stream{output_buffer.data(), utils::numeric_cast<int>(limit)};
|
195 | 201 |
|
196 |
| - auto printer = kDebugStringPrinter.Use(); |
| 202 | + auto printer = impl::kDebugStringPrinter.Use(); |
197 | 203 | printer->RegisterDebugRedactPrinters(*message.GetDescriptor());
|
198 | 204 |
|
199 | 205 | #if defined(ARCADIA_ROOT) || GOOGLE_PROTOBUF_VERSION >= 6031002
|
200 | 206 | // Throw `LimitReachedException` on limit reached to stop printing immediately, otherwise TextFormat will continue
|
201 | 207 | // to walk the whole message and apply noop printing.
|
202 |
| - LimitingOutputStream limiting_output_stream{output_stream}; |
| 208 | + impl::LimitingOutputStream limiting_output_stream{output_stream}; |
203 | 209 | try {
|
204 |
| - printer->Print(message, limiting_output_stream); |
205 |
| - } catch (const LimitingOutputStream::LimitReachedException& /*ex*/) { |
| 210 | + impl::Print(message, limiting_output_stream); |
| 211 | + } catch (const impl::LimitingOutputStream::LimitReachedException& /*ex*/) { |
206 | 212 | // Buffer limit has been reached.
|
207 | 213 | }
|
208 | 214 | #else
|
209 | 215 | // For old protobuf, we cannot apply hard limits when printing messages, because its TextFormat is not
|
210 | 216 | // exception-safe. https://github.com/protocolbuffers/protobuf/commit/be875d0aaf37dbe6948717ea621278e75e89c9c7
|
211 |
| - printer->Print(message, output_stream); |
| 217 | + impl::Print(message, output_stream); |
212 | 218 | #endif
|
| 219 | + std::string returned_str = std::string{output_buffer.data(), static_cast<std::size_t>(output_stream.ByteCount())}; |
| 220 | + if (returned_str.empty() && limit >= 7) return "<EMPTY>"; |
| 221 | + return returned_str; |
| 222 | +} |
213 | 223 |
|
214 |
| - return std::string{output_buffer.data(), static_cast<std::size_t>(output_stream.ByteCount())}; |
| 224 | +std::string ToUnlimitedDebugString(const google::protobuf::Message& message) { |
| 225 | + grpc::string result; |
| 226 | + google::protobuf::io::StringOutputStream output_stream(&result); |
| 227 | + impl::Print(message, output_stream); |
| 228 | + std::string returned_str = std::string(result); |
| 229 | + if (returned_str.empty()) return "<EMPTY>"; |
| 230 | + return returned_str; |
215 | 231 | }
|
216 | 232 |
|
217 |
| -} // namespace ugrpc::impl |
| 233 | +std::string ToLimitedDebugString(const grpc::Status& status, std::size_t max_size) { |
| 234 | + if (status.ok()) { |
| 235 | + return "OK"; |
| 236 | + } |
| 237 | + |
| 238 | + const auto gstatus = ugrpc::ToGoogleRpcStatus(status); |
| 239 | + if (gstatus.has_value()) { |
| 240 | + const std::string details_string = ugrpc::ToLimitedDebugString(*gstatus, max_size); |
| 241 | + return fmt::format( |
| 242 | + "code: {}, error message: {}\nerror details:\n{}", |
| 243 | + ugrpc::ToString(status.error_code()), |
| 244 | + status.error_message(), |
| 245 | + details_string |
| 246 | + ); |
| 247 | + } else { |
| 248 | + return fmt::format("code: {}, error message: {}", ugrpc::ToString(status.error_code()), status.error_message()); |
| 249 | + } |
| 250 | +} |
| 251 | + |
| 252 | +std::string ToUnlimitedDebugString(const grpc::Status& status) { |
| 253 | + if (status.ok()) { |
| 254 | + return "OK"; |
| 255 | + } |
| 256 | + |
| 257 | + const auto gstatus = ugrpc::ToGoogleRpcStatus(status); |
| 258 | + if (gstatus.has_value()) { |
| 259 | + const std::string details_string = ugrpc::ToUnlimitedDebugString(*gstatus); |
| 260 | + return fmt::format( |
| 261 | + "code: {}, error message: {}\nerror details:\n{}", |
| 262 | + ugrpc::ToString(status.error_code()), |
| 263 | + status.error_message(), |
| 264 | + details_string |
| 265 | + ); |
| 266 | + } else { |
| 267 | + return fmt::format("code: {}, error message: {}", ugrpc::ToString(status.error_code()), status.error_message()); |
| 268 | + } |
| 269 | +} |
| 270 | + |
| 271 | +} // namespace ugrpc |
218 | 272 |
|
219 | 273 | USERVER_NAMESPACE_END
|
0 commit comments