userver
C++ Async Framework
Toggle main menu visibility
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
<
limits
>
7
8
#
include
<
fmt
/
format
.
h
>
9
#
include
<
google
/
protobuf
/
message
.
h
>
10
#
include
<
grpcpp
/
support
/
status
.
h
>
11
12
USERVER_NAMESPACE_BEGIN
13
14
namespace
ugrpc {
15
16
inline
constexpr
std::size_t kDefaultLoggingStringLimit = 1024;
17
18
/// @brief Convert protobuf message to a limited JSON string for logging.
19
///
20
/// The message is serialized to [ProtoJSON](https://protobuf.dev/programming-guides/json/) with the following
21
/// debugging tweaks:
22
/// - Fields marked with the `[debug_redact]` option are hidden: their value is replaced with a `[REDACTED]` marker.
23
/// - A `google.protobuf.Any` that cannot be expanded is written without its raw value, so those bytes cannot bypass
24
/// `[debug_redact]`. An unknown payload type becomes `{"@type":"<type_url>","@error":"unresolved_any_type"}`.
25
/// A payload that fails to parse becomes `{"@type":"<type_url>","@error":"invalid_payload"}`. The rest of the
26
/// message is still serialized.
27
/// - Serialization stops early once `limit` bytes have been produced instead of serializing the whole message and
28
/// only then truncating, which saves CPU on large messages. The already-open JSON containers are closed, so the
29
/// truncated part before the marker stays a well-formed JSON document.
30
/// - When truncated, the string ends with a `...(truncated)` marker to indicate that the output was cut off.
31
///
32
/// @param message The protobuf message to convert.
33
/// @param limit Maximum size of the resulting string (excluding the truncation marker).
34
/// Avoid setting this to very large values as it may cause OOM (Out of Memory) issues.
35
/// @returns JSON representation of the message, truncated if necessary.
36
///
37
/// @warning This is a debug representation of protobuf that is unstable and should only be used for diagnostics.
38
/// The order of keys in maps is unstable; the format itself can change even within a single run.
39
/// You CANNOT parse back from this (possibly truncated) representation.
40
/// You CANNOT use it for equality match with reference values in gtest.
41
///
42
/// @note This function is `noexcept` and is safe to call from logging code and other no-throw contexts. If @a message
43
/// cannot be serialized to ProtoJSON, the error is not propagated: the returned string instead has the form
44
/// `serialization failed: <error description>`.
45
std::string
ToLimitedLoggingString
(
46
const
google::protobuf::Message& message,
47
std::size_t limit = kDefaultLoggingStringLimit
48
)
noexcept
;
49
50
/// @brief Convert protobuf message to an unlimited JSON string for logging.
51
///
52
/// Convenience overload equivalent to calling @ref ToLimitedLoggingString with no effective size limit: the whole
53
/// message is serialized and the result never carries a `...(truncated)` marker. See @ref ToLimitedLoggingString for
54
/// the exact serialization behavior, the `noexcept` guarantee and the error-handling contract.
55
///
56
/// @param message The protobuf message to convert.
57
/// @returns JSON representation of the whole message.
58
///
59
/// @warning Serializes the entire message, so avoid this overload on unbounded input; prefer @ref
60
/// ToLimitedLoggingString for logging.
61
inline
std::string
ToUnlimitedLoggingString
(
const
google::protobuf::Message& message)
noexcept
{
62
return
ToLimitedLoggingString
(
message
,
/*limit*/
std::numeric_limits<std::size_t>::max()
)
;
63
}
64
65
/// @brief Get error details from `grpc::Status` for logging with size limit.
66
/// @param status The `grpc::Status` to extract details from.
67
/// @param limit Maximum size of the `"details"` part: forwarded as-is to the nested @ref ToLimitedLoggingString
68
/// call for the attached `google.rpc.Status`. `code`/`message` are not size-limited.
69
/// Avoid setting this to very large values as it may cause OOM (Out of Memory) issues.
70
/// @returns JSON object with a `"code"` key (always present, e.g. `{"code":"OK"}`), plus a `"message"` key when
71
/// `status.error_message()` is non-empty, plus a `"details"` key when `status` carries a parseable
72
/// `google.rpc.Status`, holding the JSON produced by
73
/// @ref ToLimitedLoggingString(const google::protobuf::Message&, std::size_t) for that attached status. For an OK
74
/// status both `message` and `details` are normally absent, so the result is just `{"code":"OK"}`.
75
///
76
/// @warning This is a debug representation of protobuf that is unstable and should only be used for diagnostics.
77
/// The order of keys in maps is unstable; the format itself can change even within a single run.
78
/// You CANNOT parse back from this representation.
79
/// You CANNOT use it for equality match with reference values in gtest.
80
/// @warning If `<details>` ends up truncated (or its own serialization fails), the `...(truncated)` marker (or a
81
/// `serialization failed: ...` message) is embedded as raw, unquoted text in place of the `"details"` value, which
82
/// makes the overall result invalid JSON in that case. `code` and `message` are always properly JSON-escaped and
83
/// cannot break the surrounding JSON.
84
///
85
/// @note This function does not itself catch exceptions; its `noexcept` guarantee relies on
86
/// `formats::json::StringBuilder` and the nested
87
/// @ref ToLimitedLoggingString(const google::protobuf::Message&, std::size_t) call (used to produce `<details>`)
88
/// never throwing.
89
std::string
ToLimitedLoggingString
(
const
grpc::Status& status, std::size_t limit = kDefaultLoggingStringLimit)
noexcept
;
90
91
/// @brief Get error details from `grpc::Status` for logging without size limit.
92
///
93
/// Convenience overload equivalent to calling @ref ToLimitedLoggingString with no effective size limit: the whole
94
/// details part is serialized and never carries a `...(truncated)` marker. See @ref ToLimitedLoggingString for the
95
/// output format, the `noexcept` guarantee and the error-handling contract.
96
///
97
/// @param status The `grpc::Status` to extract details from.
98
/// @returns JSON representation of the status with its full details.
99
///
100
/// @warning Serializes the entire details part, so avoid this overload on unbounded input; prefer @ref
101
/// ToLimitedLoggingString for logging.
102
inline
std::string
ToUnlimitedLoggingString
(
const
grpc::Status& status)
noexcept
{
103
return
ToLimitedLoggingString
(
status
,
/*limit=*/
std::numeric_limits<std::size_t>::max()
)
;
104
}
105
106
}
// namespace ugrpc
107
108
USERVER_NAMESPACE_END
109
110
namespace
fmt
{
111
112
/// @brief `fmt::format` support for protobuf messages
113
template
<
typename
T
>
114
requires
std
::
is_base_of_v
<
google
::
protobuf
::
Message
,
std
::
decay_t
<
T
>>
115
struct
formatter
<
T
> {
116
constexpr
auto
parse
(
format_parse_context
&
ctx
) {
return
ctx
.
begin
(); }
117
118
template
<
typename
FormatContext
>
119
auto
format
(
const
T
&
message
,
FormatContext
&
ctx
)
const
{
120
return
fmt
::
format_to
(
ctx
.
out
(),
"{}"
, USERVER_NAMESPACE::
ugrpc
::
ToLimitedLoggingString
(
message
));
121
}
122
};
123
124
}
// namespace fmt
userver
ugrpc
protobuf_logging.hpp
Generated on
for userver by
Doxygen
1.17.0