13#include <system_error> 
   16#include <userver/formats/common/meta.hpp> 
   17#include <userver/logging/fwd.hpp> 
   18#include <userver/logging/level.hpp> 
   19#include <userver/logging/log_extra.hpp> 
   20#include <userver/utils/impl/source_location.hpp> 
   21#include <userver/utils/meta.hpp> 
   23USERVER_NAMESPACE_BEGIN
 
   36  template <
typename Unsigned,
 
   37            typename = std::enable_if_t<std::is_unsigned_v<Unsigned>>>
 
   38  explicit constexpr HexBase(Unsigned value) 
noexcept : value(value) {
 
   39    static_assert(
sizeof(Unsigned) <= 
sizeof(value));
 
   43  explicit HexBase(T* pointer) 
noexcept 
   44      : HexBase(
reinterpret_cast<std::uintptr_t>(pointer)) {
 
   45    static_assert(
sizeof(std::uintptr_t) <= 
sizeof(value));
 
   52struct Hex 
final : impl::HexBase {
 
   53  using impl::HexBase::HexBase;
 
   58struct HexShort 
final : impl::HexBase {
 
   59  using impl::HexBase::HexBase;
 
   64  std::string_view string;
 
   72class LogHelper 
final {
 
   79            const utils::impl::SourceLocation& location =
 
   87            const utils::impl::SourceLocation& location =
 
   92  LogHelper(LogHelper&&) = 
delete;
 
   93  LogHelper(
const LogHelper&) = 
delete;
 
   94  LogHelper& operator=(LogHelper&&) = 
delete;
 
   95  LogHelper& operator=(
const LogHelper&) = 
delete;
 
   98  LogHelper& AsLvalue() 
noexcept { 
return *
this; }
 
  100  bool IsLimitReached() 
const noexcept;
 
  102  template <
typename T>
 
  103  LogHelper& operator<<(
const T& value) {
 
  104    if constexpr (std::is_constructible_v<std::string_view, T>) {
 
  106      *
this << std::string_view{value};
 
  107    } 
else if constexpr (std::is_signed_v<T>) {
 
  108      using LongLong = 
long long;
 
  109      *
this << LongLong{value};
 
  110    } 
else if constexpr (std::is_unsigned_v<T>) {
 
  111      using UnsignedLongLong = 
unsigned long long;
 
  112      *
this << UnsignedLongLong{value};
 
  113    } 
else if constexpr (std::is_base_of_v<std::exception, T>) {
 
  114      *
this << 
static_cast<
const std::exception&>(value);
 
  115    } 
else if constexpr (meta::kIsOstreamWritable<T>) {
 
  119    } 
else if constexpr (meta::kIsRange<T> &&
 
  120                         !formats::
common::kIsFormatValue<T>) {
 
  124      static_assert(!
sizeof(T),
 
  125                    "Please implement logging for your type: " 
  126                    "logging::LogHelper& operator<<(logging::LogHelper& lh, " 
  133  LogHelper& operator<<(
char value) 
noexcept;
 
  134  LogHelper& operator<<(std::string_view value) 
noexcept;
 
  135  LogHelper& operator<<(
float value) 
noexcept;
 
  136  LogHelper& operator<<(
double value) 
noexcept;
 
  137  LogHelper& operator<<(
long double value) 
noexcept;
 
  138  LogHelper& operator<<(
unsigned long long value) 
noexcept;
 
  139  LogHelper& operator<<(
long long value) 
noexcept;
 
  140  LogHelper& operator<<(
bool value) 
noexcept;
 
  141  LogHelper& operator<<(
const std::exception& value) 
noexcept;
 
  144  LogHelper& operator<<(
const LogExtra& extra) 
noexcept;
 
  147  LogHelper& operator<<(LogExtra&& extra) 
noexcept;
 
  149  LogHelper& operator<<(
const LogExtra::Value& value) 
noexcept;
 
  151  LogHelper& operator<<(Hex hex) 
noexcept;
 
  153  LogHelper& operator<<(HexShort hex) 
noexcept;
 
  155  LogHelper& operator<<(Quoted value) 
noexcept;
 
  159  operator impl::Noop() 
const noexcept { 
return {}; }
 
  164  impl::TagWriter GetTagWriterAfterText(InternalTag);
 
  168  friend class impl::TagWriter;
 
  172  void DoLog() 
noexcept;
 
  174  void InternalLoggingError(std::string_view message) 
noexcept;
 
  176  impl::TagWriter GetTagWriter();
 
  178  void PutFloatingPoint(
float value);
 
  179  void PutFloatingPoint(
double value);
 
  180  void PutFloatingPoint(
long double value);
 
  181  void PutUnsigned(
unsigned long long value);
 
  182  void PutSigned(
long long value);
 
  183  void PutBoolean(
bool value);
 
  184  void Put(std::string_view value);
 
  185  void Put(
char value);
 
  187  void PutRaw(std::string_view value_needs_no_escaping);
 
  188  void PutException(
const std::exception& ex);
 
  189  void PutQuoted(std::string_view value);
 
  191  template <
typename T>
 
  192  void PutRangeElement(
const T& value);
 
  194  template <
typename T, 
typename U>
 
  195  void PutMapElement(
const std::pair<
const T, U>& value);
 
  197  template <
typename T>
 
  198  void PutRange(
const T& range);
 
  200  std::ostream& Stream();
 
  204  std::unique_ptr<Impl> pimpl_;
 
  207inline LogHelper& operator<<(LogHelper& lh, std::error_code ec) {
 
  208  lh << ec.category().name() << 
':' << ec.value() << 
" (" << ec.message()
 
  214LogHelper& operator<<(LogHelper& lh, 
const std::atomic<T>& value) {
 
  215  return lh << value.load();
 
  219LogHelper& operator<<(LogHelper& lh, 
const T* value) 
noexcept {
 
  220  if (value == 
nullptr) {
 
  221    lh << std::string_view{
"(null)"};
 
  222  } 
else if constexpr (std::is_same_v<T, 
char>) {
 
  223    lh << std::string_view{value};
 
  231LogHelper& operator<<(LogHelper& lh, T* value) {
 
  232  return lh << 
static_cast<
const T*>(value);
 
  236LogHelper& operator<<(LogHelper& lh, 
const std::optional<T>& value) {
 
  244template <
class Result, 
class... Args>
 
  245LogHelper& operator<<(LogHelper& lh, Result (*)(Args...)) {
 
  246  static_assert(!
sizeof(Result),
 
  247                "Outputting functions or std::ostream formatters is forbidden");
 
  251LogHelper& operator<<(LogHelper& lh, std::chrono::system_clock::time_point tp);
 
  252LogHelper& operator<<(LogHelper& lh, std::chrono::seconds value);
 
  253LogHelper& operator<<(LogHelper& lh, std::chrono::milliseconds value);
 
  254LogHelper& operator<<(LogHelper& lh, std::chrono::microseconds value);
 
  255LogHelper& operator<<(LogHelper& lh, std::chrono::nanoseconds value);
 
  256LogHelper& operator<<(LogHelper& lh, std::chrono::minutes value);
 
  257LogHelper& operator<<(LogHelper& lh, std::chrono::nanoseconds value);
 
  258LogHelper& operator<<(LogHelper& lh, std::chrono::hours value);
 
  261void LogHelper::PutRangeElement(
const T& value) {
 
  262  if constexpr (std::is_constructible_v<std::string_view, T>) {
 
  263    *
this << Quoted{value};
 
  269template <
typename T, 
typename U>
 
  270void LogHelper::PutMapElement(
const std::pair<
const T, U>& value) {
 
  271  PutRangeElement(value.first);
 
  273  PutRangeElement(value.second);
 
  277void LogHelper::PutRange(
const T& range) {
 
  278  static_assert(meta::kIsRange<T>);
 
  282  constexpr std::string_view kSeparator = 
", ";
 
  285  bool is_first = 
true;
 
  286  auto curr = begin(range);
 
  287  const auto end_iter = end(range);
 
  289  while (curr != end_iter) {
 
  290    if (IsLimitReached()) {
 
  299    if constexpr (meta::kIsMap<T>) {
 
  300      PutMapElement(*curr);
 
  302      PutRangeElement(*curr);
 
  307  const auto extra_elements = std::distance(curr, end_iter);
 
  309  if (extra_elements != 0) {
 
  313    *
this << 
"..." << extra_elements << 
" more";