Support RTC_LOG for types that implement both AbslStringify and ToLogString

To support libraries and dependencies compatible with absl way of debug printing custom types.
In particular gtest can use AbslStringify to produce nice output when unit types are compared with EXPECT macros.

Bug: None
Change-Id: Ie78293a225f61977f256f0234e07d166b1977e2d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/364162
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43164}
This commit is contained in:
Danil Chapovalov 2024-10-03 11:45:27 +02:00 committed by WebRTC LUCI CQ
parent 4f6f92a986
commit f75ab82b46
12 changed files with 79 additions and 21 deletions

View File

@ -22,6 +22,7 @@ rtc_library("data_rate") {
"..:array_view",
"../../rtc_base:checks",
"../../rtc_base:stringutils",
"../../rtc_base/system:rtc_export",
"../../rtc_base/units:unit_base",
]
}
@ -37,6 +38,7 @@ rtc_library("data_size") {
"..:array_view",
"../../rtc_base:checks",
"../../rtc_base:stringutils",
"../../rtc_base/system:rtc_export",
"../../rtc_base/units:unit_base",
]
}
@ -52,6 +54,7 @@ rtc_library("time_delta") {
"..:array_view",
"../../rtc_base:checks",
"../../rtc_base:stringutils",
"../../rtc_base/system:rtc_export",
"../../rtc_base/units:unit_base",
]
}
@ -68,6 +71,7 @@ rtc_library("frequency") {
"..:array_view",
"../../rtc_base:checks",
"../../rtc_base:stringutils",
"../../rtc_base/system:rtc_export",
"../../rtc_base/units:unit_base",
]
}
@ -84,6 +88,7 @@ rtc_library("timestamp") {
"..:array_view",
"../../rtc_base:checks",
"../../rtc_base:stringutils",
"../../rtc_base/system:rtc_export",
"../../rtc_base/units:unit_base",
]
}

View File

@ -20,6 +20,7 @@
#include "api/units/frequency.h"
#include "api/units/time_delta.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
namespace webrtc {
@ -47,6 +48,9 @@ class DataRate final : public rtc_units_impl::RelativeUnit<DataRate> {
DataRate() = delete;
template <typename Sink>
friend void AbslStringify(Sink& sink, DataRate value);
template <typename T = int64_t>
constexpr T bps() const {
return ToValue<T>();
@ -134,11 +138,16 @@ inline constexpr DataRate operator*(const Frequency frequency,
return size * frequency;
}
std::string ToString(DataRate value);
RTC_EXPORT std::string ToString(DataRate value);
inline std::string ToLogString(DataRate value) {
return ToString(value);
}
template <typename Sink>
void AbslStringify(Sink& sink, DataRate value) {
sink.Append(ToString(value));
}
} // namespace webrtc
#endif // API_UNITS_DATA_RATE_H_

View File

@ -15,6 +15,7 @@
#include <string>
#include <type_traits>
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
namespace webrtc {
@ -30,6 +31,9 @@ class DataSize final : public rtc_units_impl::RelativeUnit<DataSize> {
DataSize() = delete;
template <typename Sink>
friend void AbslStringify(Sink& sink, DataSize value);
template <typename T = int64_t>
constexpr T bytes() const {
return ToValue<T>();
@ -45,11 +49,16 @@ class DataSize final : public rtc_units_impl::RelativeUnit<DataSize> {
static constexpr bool one_sided = true;
};
std::string ToString(DataSize value);
RTC_EXPORT std::string ToString(DataSize value);
inline std::string ToLogString(DataSize value) {
return ToString(value);
}
template <typename Sink>
void AbslStringify(Sink& sink, DataSize value) {
sink.Append(ToString(value));
}
} // namespace webrtc
#endif // API_UNITS_DATA_SIZE_H_

View File

@ -18,6 +18,7 @@
#include "api/units/time_delta.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
namespace webrtc {
@ -42,6 +43,9 @@ class Frequency final : public rtc_units_impl::RelativeUnit<Frequency> {
Frequency() = delete;
template <typename Sink>
friend void AbslStringify(Sink& sink, Frequency value);
template <typename T = int64_t>
constexpr T hertz() const {
return ToFraction<1000, T>();
@ -82,10 +86,15 @@ inline constexpr double operator*(TimeDelta time_delta, Frequency frequency) {
return frequency * time_delta;
}
std::string ToString(Frequency value);
RTC_EXPORT std::string ToString(Frequency value);
inline std::string ToLogString(Frequency value) {
return ToString(value);
}
template <typename Sink>
void AbslStringify(Sink& sink, Frequency value) {
sink.Append(ToString(value));
}
} // namespace webrtc
#endif // API_UNITS_FREQUENCY_H_

View File

@ -16,6 +16,7 @@
#include <string>
#include <type_traits>
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
namespace webrtc {
@ -52,6 +53,9 @@ class TimeDelta final : public rtc_units_impl::RelativeUnit<TimeDelta> {
TimeDelta() = delete;
template <typename Sink>
friend void AbslStringify(Sink& sink, TimeDelta value);
template <typename T = int64_t>
constexpr T seconds() const {
return ToFraction<1000000, T>();
@ -89,11 +93,16 @@ class TimeDelta final : public rtc_units_impl::RelativeUnit<TimeDelta> {
static constexpr bool one_sided = false;
};
std::string ToString(TimeDelta value);
RTC_EXPORT std::string ToString(TimeDelta value);
inline std::string ToLogString(TimeDelta value) {
return ToString(value);
}
template <typename Sink>
void AbslStringify(Sink& sink, TimeDelta value) {
sink.Append(ToString(value));
}
} // namespace webrtc
#endif // API_UNITS_TIME_DELTA_H_

View File

@ -17,6 +17,7 @@
#include "api/units/time_delta.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/units/unit_base.h" // IWYU pragma: export
namespace webrtc {
@ -44,6 +45,9 @@ class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> {
Timestamp() = delete;
template <typename Sink>
friend void AbslStringify(Sink& sink, Timestamp value);
template <typename T = int64_t>
constexpr T seconds() const {
return ToFraction<1000000, T>();
@ -118,11 +122,16 @@ class Timestamp final : public rtc_units_impl::UnitBase<Timestamp> {
static constexpr bool one_sided = true;
};
std::string ToString(Timestamp value);
RTC_EXPORT std::string ToString(Timestamp value);
inline std::string ToLogString(Timestamp value) {
return ToString(value);
}
template <typename Sink>
void AbslStringify(Sink& sink, Timestamp value) {
sink.Append(ToString(value));
}
} // namespace webrtc
#endif // API_UNITS_TIMESTAMP_H_

View File

@ -310,9 +310,9 @@ TimeDelta PacingController::UpdateTimeAndGetElapsed(Timestamp now) {
TimeDelta elapsed_time = now - last_process_time_;
last_process_time_ = now;
if (elapsed_time > kMaxElapsedTime) {
RTC_LOG(LS_WARNING) << "Elapsed time (" << ToLogString(elapsed_time)
RTC_LOG(LS_WARNING) << "Elapsed time (" << elapsed_time
<< ") longer than expected, limiting to "
<< ToLogString(kMaxElapsedTime);
<< kMaxElapsedTime;
elapsed_time = kMaxElapsedTime;
}
return elapsed_time;

View File

@ -582,9 +582,8 @@ bool TransportFeedback::IsConsistent() const {
return false;
}
if (timestamp != last_timestamp_) {
RTC_LOG(LS_ERROR) << "Last timestamp mismatch. Calculated: "
<< ToLogString(timestamp)
<< ". Saved: " << ToLogString(last_timestamp_);
RTC_LOG(LS_ERROR) << "Last timestamp mismatch. Calculated: " << timestamp
<< ". Saved: " << last_timestamp_;
return false;
}
if (size_bytes_ != packet_size) {

View File

@ -437,6 +437,7 @@ rtc_library("logging") {
":platform_thread_types",
":stringutils",
":timeutils",
":type_traits",
"../api/units:timestamp",
"synchronization:mutex",
"//third_party/abseil-cpp/absl/base:core_headers",
@ -486,6 +487,7 @@ rtc_library("checks") {
]
deps = [
":safe_compare",
":type_traits",
"../api:scoped_refptr",
"system:inline",
"system:rtc_export",

View File

@ -62,6 +62,7 @@ RTC_NORETURN void rtc_FatalMessage(const char* file, int line, const char* msg);
#include "rtc_base/numerics/safe_compare.h"
#include "rtc_base/system/inline.h"
#include "rtc_base/system/rtc_export.h"
#include "rtc_base/type_traits.h"
// The macros here print a message to stderr and abort under various
// conditions. All will accept additional stream messages. For example:
@ -217,13 +218,14 @@ inline decltype(MakeVal(std::declval<absl::underlying_type_t<T>>())) MakeVal(
return {static_cast<absl::underlying_type_t<T>>(x)};
}
template <typename T, decltype(ToLogString(std::declval<T>()))* = nullptr>
template <typename T, std::enable_if_t<has_to_log_string_v<T>>* = nullptr>
ToStringVal MakeVal(const T& x) {
return {ToLogString(x)};
}
template <typename T,
std::enable_if_t<absl::HasAbslStringify<T>::value>* = nullptr>
std::enable_if_t<absl::HasAbslStringify<T>::value &&
!has_to_log_string_v<T>>* = nullptr>
ToStringVal MakeVal(const T& x) {
return {absl::StrCat(x)};
}

View File

@ -66,6 +66,7 @@
#include "rtc_base/platform_thread_types.h"
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/system/inline.h"
#include "rtc_base/type_traits.h"
#if !defined(NDEBUG) || defined(DLOG_ALWAYS_ON)
#define RTC_DLOG_IS_ON 1
@ -330,21 +331,14 @@ inline Val<LogArgType::kLogMetadataTag, LogMetadataTag> MakeVal(
}
#endif
template <typename T, class = void>
struct has_to_log_string : std::false_type {};
template <typename T>
struct has_to_log_string<T,
absl::enable_if_t<std::is_convertible<
decltype(ToLogString(std::declval<T>())),
std::string>::value>> : std::true_type {};
template <typename T, absl::enable_if_t<has_to_log_string<T>::value>* = nullptr>
ToStringVal MakeVal(const T& x) {
return {ToLogString(x)};
}
template <typename T,
std::enable_if_t<absl::HasAbslStringify<T>::value>* = nullptr>
std::enable_if_t<absl::HasAbslStringify<T>::value &&
!has_to_log_string<T>::value>* = nullptr>
ToStringVal MakeVal(const T& x) {
return {absl::StrCat(x)};
}

View File

@ -12,6 +12,7 @@
#define RTC_BASE_TYPE_TRAITS_H_
#include <cstddef>
#include <string>
#include <type_traits>
namespace rtc {
@ -36,6 +37,16 @@ class HasDataAndSize {
static constexpr bool value = std::is_same<decltype(Test<DS>(0)), int>::value;
};
template <typename T, typename = void>
struct has_to_log_string : std::false_type {};
template <typename T>
struct has_to_log_string<T,
std::enable_if_t<std::is_convertible_v<
decltype(ToLogString(std::declval<T>())),
std::string>>> : std::true_type {};
template <typename T>
constexpr bool has_to_log_string_v = has_to_log_string<T>::value;
namespace test_has_data_and_size {
template <typename DR, typename SR>