userver: userver/ugrpc/protobuf_logging.hpp Source File
Loading...
Searching...
No Matches
protobuf_logging.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// @brief Public API for protobuf logging utilities.
5
6#include <fmt/format.h>
7#include <google/protobuf/message.h>
8#include <grpcpp/support/status.h>
9
10USERVER_NAMESPACE_BEGIN
11
12namespace ugrpc {
13
14inline constexpr std::size_t kDefaultDebugStringLimit = 1024;
15
16/// @brief Convert protobuf message to limited debug string for logging.
17///
18/// Differences from built-in `DebugString`:
19/// - Fields marked with `[debug_redact]` option are hidden (`DebugString` only does so since Protobuf v30).
20/// - When the character limit is reached, serialization stops immediately (`DebugString` still wastes CPU on
21/// serializing the entire message regardless).
22/// - When truncated, the string ends with `...(truncated)` marker to indicate that the output was cut off.
23///
24/// @param message The protobuf message to convert.
25/// @param limit Maximum size of the resulting string.
26/// Avoid setting this to very large values as it may cause OOM (Out of Memory) issues.
27/// @returns String representation of the message, truncated if necessary.
28///
29/// @warning This is a debug representation of protobuf that is unstable and should only be used for diagnostics.
30/// The order of keys in maps is unstable; the format itself can change even within a single run.
31/// You CANNOT parse back from this debug text representation.
32/// You CANNOT use it for equality match with reference values in gtest.
33std::string ToLimitedDebugString(const google::protobuf::Message& message, std::size_t limit);
34
35/// @brief Convert protobuf message to unlimited debug string for logging.
36///
37/// Differences from built-in `DebugString`:
38/// - Fields marked with `[debug_redact]` option are hidden (`DebugString` only does so since Protobuf v30).
39///
40/// @param message The protobuf message to convert.
41/// @returns String representation of the message.
42///
43/// @warning This is a debug representation of protobuf that is unstable and should only be used for diagnostics.
44/// The order of keys in maps is unstable; the format itself can change even within a single run.
45/// You CANNOT parse back from this debug text representation.
46/// You CANNOT use it for equality match with reference values in gtest.
47std::string ToUnlimitedDebugString(const google::protobuf::Message& message);
48
49/// @brief Get error details from `grpc::Status` for logging with size limit.
50/// @param status The `grpc::Status` to extract details from.
51/// @param max_size Maximum size of the error details part.
52/// Avoid setting this to very large values as it may cause OOM (Out of Memory) issues.
53/// @returns String representation of error details, formatted as "code: {code}, error message: {message}\nerror
54/// details:\n{details}". The error details part may be truncated if it exceeds max_size, in which case it ends with
55/// `...(truncated)` marker.
56///
57/// @warning This is a debug representation of protobuf that is unstable and should only be used for diagnostics.
58/// The order of keys in maps is unstable; the format itself can change even within a single run.
59/// You CANNOT parse back from this debug text representation.
60/// You CANNOT use it for equality match with reference values in gtest.
61std::string ToLimitedDebugString(const grpc::Status& status, std::size_t max_size = kDefaultDebugStringLimit);
62
63/// @brief Get error details from `grpc::Status` for logging without size limit.
64/// @param status The `grpc::Status` to extract details from.
65/// @returns String representation of error details.
66///
67/// @warning This is a debug representation of protobuf that is unstable and should only be used for diagnostics.
68/// The order of keys in maps is unstable; the format itself can change even within a single run.
69/// You CANNOT parse back from this debug text representation.
70/// You CANNOT use it for equality match with reference values in gtest.
71std::string ToUnlimitedDebugString(const grpc::Status& status);
72
73} // namespace ugrpc
74
75USERVER_NAMESPACE_END
76
77namespace fmt {
78
79/// @brief `fmt::format` support for protobuf messages
80template <typename T>
81struct formatter<T, typename std::enable_if_t<std::is_base_of_v<google::protobuf::Message, std::decay_t<T>>, char>> {
82 constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
83
84 template <typename FormatContext>
85 auto format(const T& message, FormatContext& ctx) const {
86 return fmt::format_to(
87 ctx.out(),
88 "{}",
89 USERVER_NAMESPACE::ugrpc::ToLimitedDebugString(message, USERVER_NAMESPACE::ugrpc::kDefaultDebugStringLimit)
90 );
91 }
92};
93
94} // namespace fmt