xref: /aosp_15_r20/external/openscreen/util/osp_logging.h (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #ifndef UTIL_OSP_LOGGING_H_
6*3f982cf4SFabien Sanglard #define UTIL_OSP_LOGGING_H_
7*3f982cf4SFabien Sanglard 
8*3f982cf4SFabien Sanglard #include <sstream>
9*3f982cf4SFabien Sanglard #include <utility>
10*3f982cf4SFabien Sanglard 
11*3f982cf4SFabien Sanglard #include "platform/api/logging.h"
12*3f982cf4SFabien Sanglard 
13*3f982cf4SFabien Sanglard namespace openscreen {
14*3f982cf4SFabien Sanglard namespace internal {
15*3f982cf4SFabien Sanglard 
16*3f982cf4SFabien Sanglard // The stream-based logging macros below are adapted from Chromium's
17*3f982cf4SFabien Sanglard // base/logging.h.
18*3f982cf4SFabien Sanglard class LogMessage {
19*3f982cf4SFabien Sanglard  public:
LogMessage(LogLevel level,const char * file,int line)20*3f982cf4SFabien Sanglard   LogMessage(LogLevel level, const char* file, int line)
21*3f982cf4SFabien Sanglard       : level_(level), file_(file), line_(line) {}
22*3f982cf4SFabien Sanglard 
~LogMessage()23*3f982cf4SFabien Sanglard   ~LogMessage() {
24*3f982cf4SFabien Sanglard     LogWithLevel(level_, file_, line_, std::move(stream_));
25*3f982cf4SFabien Sanglard     if (level_ == LogLevel::kFatal) {
26*3f982cf4SFabien Sanglard       Break();
27*3f982cf4SFabien Sanglard     }
28*3f982cf4SFabien Sanglard   }
29*3f982cf4SFabien Sanglard 
stream()30*3f982cf4SFabien Sanglard   std::ostream& stream() { return stream_; }
31*3f982cf4SFabien Sanglard 
32*3f982cf4SFabien Sanglard  protected:
33*3f982cf4SFabien Sanglard   const LogLevel level_;
34*3f982cf4SFabien Sanglard 
35*3f982cf4SFabien Sanglard   // The file here comes from the __FILE__ macro, which should persist while
36*3f982cf4SFabien Sanglard   // we are doing the logging. Hence, keeping it unmanaged here and not
37*3f982cf4SFabien Sanglard   // creating a copy should be safe.
38*3f982cf4SFabien Sanglard   const char* const file_;
39*3f982cf4SFabien Sanglard   const int line_;
40*3f982cf4SFabien Sanglard   std::stringstream stream_;
41*3f982cf4SFabien Sanglard };
42*3f982cf4SFabien Sanglard 
43*3f982cf4SFabien Sanglard // Used by the OSP_LAZY_STREAM macro to return void after evaluating an ostream
44*3f982cf4SFabien Sanglard // chain expression.
45*3f982cf4SFabien Sanglard class Voidify {
46*3f982cf4SFabien Sanglard  public:
47*3f982cf4SFabien Sanglard   void operator&(std::ostream&) {}
48*3f982cf4SFabien Sanglard };
49*3f982cf4SFabien Sanglard 
50*3f982cf4SFabien Sanglard }  // namespace internal
51*3f982cf4SFabien Sanglard }  // namespace openscreen
52*3f982cf4SFabien Sanglard 
53*3f982cf4SFabien Sanglard #define OSP_LAZY_STREAM(condition, stream) \
54*3f982cf4SFabien Sanglard   !(condition) ? (void)0 : openscreen::internal::Voidify() & (stream)
55*3f982cf4SFabien Sanglard #define OSP_LOG_IS_ON(level_enum) \
56*3f982cf4SFabien Sanglard   openscreen::IsLoggingOn(openscreen::LogLevel::level_enum, __FILE__)
57*3f982cf4SFabien Sanglard #define OSP_LOG_STREAM(level_enum)                                             \
58*3f982cf4SFabien Sanglard   openscreen::internal::LogMessage(openscreen::LogLevel::level_enum, __FILE__, \
59*3f982cf4SFabien Sanglard                                    __LINE__)                                   \
60*3f982cf4SFabien Sanglard       .stream()
61*3f982cf4SFabien Sanglard 
62*3f982cf4SFabien Sanglard #define OSP_VLOG \
63*3f982cf4SFabien Sanglard   OSP_LAZY_STREAM(OSP_LOG_IS_ON(kVerbose), OSP_LOG_STREAM(kVerbose))
64*3f982cf4SFabien Sanglard #define OSP_LOG_INFO \
65*3f982cf4SFabien Sanglard   OSP_LAZY_STREAM(OSP_LOG_IS_ON(kInfo), OSP_LOG_STREAM(kInfo))
66*3f982cf4SFabien Sanglard #define OSP_LOG_WARN \
67*3f982cf4SFabien Sanglard   OSP_LAZY_STREAM(OSP_LOG_IS_ON(kWarning), OSP_LOG_STREAM(kWarning))
68*3f982cf4SFabien Sanglard #define OSP_LOG_ERROR \
69*3f982cf4SFabien Sanglard   OSP_LAZY_STREAM(OSP_LOG_IS_ON(kError), OSP_LOG_STREAM(kError))
70*3f982cf4SFabien Sanglard #define OSP_LOG_FATAL \
71*3f982cf4SFabien Sanglard   OSP_LAZY_STREAM(OSP_LOG_IS_ON(kFatal), OSP_LOG_STREAM(kFatal))
72*3f982cf4SFabien Sanglard 
73*3f982cf4SFabien Sanglard #define OSP_VLOG_IF(condition) !(condition) ? (void)0 : OSP_VLOG
74*3f982cf4SFabien Sanglard #define OSP_LOG_IF(level, condition) !(condition) ? (void)0 : OSP_LOG_##level
75*3f982cf4SFabien Sanglard 
76*3f982cf4SFabien Sanglard #define OSP_CHECK(condition) \
77*3f982cf4SFabien Sanglard   OSP_LOG_IF(FATAL, !(condition)) << "OSP_CHECK(" << #condition << ") failed: "
78*3f982cf4SFabien Sanglard 
79*3f982cf4SFabien Sanglard #define OSP_CHECK_EQ(a, b) \
80*3f982cf4SFabien Sanglard   OSP_CHECK((a) == (b)) << (a) << " vs. " << (b) << ": "
81*3f982cf4SFabien Sanglard #define OSP_CHECK_NE(a, b) \
82*3f982cf4SFabien Sanglard   OSP_CHECK((a) != (b)) << (a) << " vs. " << (b) << ": "
83*3f982cf4SFabien Sanglard #define OSP_CHECK_LT(a, b) OSP_CHECK((a) < (b)) << (a) << " vs. " << (b) << ": "
84*3f982cf4SFabien Sanglard #define OSP_CHECK_LE(a, b) \
85*3f982cf4SFabien Sanglard   OSP_CHECK((a) <= (b)) << (a) << " vs. " << (b) << ": "
86*3f982cf4SFabien Sanglard #define OSP_CHECK_GT(a, b) OSP_CHECK((a) > (b)) << (a) << " vs. " << (b) << ": "
87*3f982cf4SFabien Sanglard #define OSP_CHECK_GE(a, b) \
88*3f982cf4SFabien Sanglard   OSP_CHECK((a) >= (b)) << (a) << " vs. " << (b) << ": "
89*3f982cf4SFabien Sanglard 
90*3f982cf4SFabien Sanglard #if defined(_DEBUG) || defined(DCHECK_ALWAYS_ON)
91*3f982cf4SFabien Sanglard #define OSP_DCHECK_IS_ON() 1
92*3f982cf4SFabien Sanglard #define OSP_DCHECK(condition) OSP_CHECK(condition)
93*3f982cf4SFabien Sanglard #define OSP_DCHECK_EQ(a, b) OSP_CHECK_EQ(a, b)
94*3f982cf4SFabien Sanglard #define OSP_DCHECK_NE(a, b) OSP_CHECK_NE(a, b)
95*3f982cf4SFabien Sanglard #define OSP_DCHECK_LT(a, b) OSP_CHECK_LT(a, b)
96*3f982cf4SFabien Sanglard #define OSP_DCHECK_LE(a, b) OSP_CHECK_LE(a, b)
97*3f982cf4SFabien Sanglard #define OSP_DCHECK_GT(a, b) OSP_CHECK_GT(a, b)
98*3f982cf4SFabien Sanglard #define OSP_DCHECK_GE(a, b) OSP_CHECK_GE(a, b)
99*3f982cf4SFabien Sanglard #else
100*3f982cf4SFabien Sanglard #define OSP_DCHECK_IS_ON() 0
101*3f982cf4SFabien Sanglard // When DCHECKs are off, nothing will be logged. Use that fact to make
102*3f982cf4SFabien Sanglard // references to the |condition| expression (or |a| and |b|) so the compiler
103*3f982cf4SFabien Sanglard // won't emit unused variable warnings/errors when DCHECKs are turned off.
104*3f982cf4SFabien Sanglard #define OSP_EAT_STREAM OSP_LOG_IF(FATAL, false)
105*3f982cf4SFabien Sanglard #define OSP_DCHECK(condition) OSP_EAT_STREAM << !(condition)
106*3f982cf4SFabien Sanglard #define OSP_DCHECK_EQ(a, b) OSP_EAT_STREAM << !((a) == (b))
107*3f982cf4SFabien Sanglard #define OSP_DCHECK_NE(a, b) OSP_EAT_STREAM << !((a) != (b))
108*3f982cf4SFabien Sanglard #define OSP_DCHECK_LT(a, b) OSP_EAT_STREAM << !((a) < (b))
109*3f982cf4SFabien Sanglard #define OSP_DCHECK_LE(a, b) OSP_EAT_STREAM << !((a) <= (b))
110*3f982cf4SFabien Sanglard #define OSP_DCHECK_GT(a, b) OSP_EAT_STREAM << !((a) > (b))
111*3f982cf4SFabien Sanglard #define OSP_DCHECK_GE(a, b) OSP_EAT_STREAM << !((a) >= (b))
112*3f982cf4SFabien Sanglard #endif
113*3f982cf4SFabien Sanglard 
114*3f982cf4SFabien Sanglard #define OSP_DVLOG OSP_VLOG_IF(OSP_DCHECK_IS_ON())
115*3f982cf4SFabien Sanglard #define OSP_DLOG_INFO OSP_LOG_IF(INFO, OSP_DCHECK_IS_ON())
116*3f982cf4SFabien Sanglard #define OSP_DLOG_WARN OSP_LOG_IF(WARN, OSP_DCHECK_IS_ON())
117*3f982cf4SFabien Sanglard #define OSP_DLOG_ERROR OSP_LOG_IF(ERROR, OSP_DCHECK_IS_ON())
118*3f982cf4SFabien Sanglard #define OSP_DLOG_FATAL OSP_LOG_IF(FATAL, OSP_DCHECK_IS_ON())
119*3f982cf4SFabien Sanglard #define OSP_DVLOG_IF(condition) OSP_VLOG_IF(OSP_DCHECK_IS_ON() && (condition))
120*3f982cf4SFabien Sanglard #define OSP_DLOG_IF(level, condition) \
121*3f982cf4SFabien Sanglard   OSP_LOG_IF(level, OSP_DCHECK_IS_ON() && (condition))
122*3f982cf4SFabien Sanglard 
123*3f982cf4SFabien Sanglard // Log when unimplemented code points are reached: If verbose logging is turned
124*3f982cf4SFabien Sanglard // on, log always. Otherwise, just attempt to log once.
125*3f982cf4SFabien Sanglard #define OSP_UNIMPLEMENTED()                                           \
126*3f982cf4SFabien Sanglard   if (OSP_LOG_IS_ON(kVerbose)) {                                      \
127*3f982cf4SFabien Sanglard     OSP_LOG_STREAM(kVerbose) << __func__ << ": UNIMPLEMENTED() hit."; \
128*3f982cf4SFabien Sanglard   } else {                                                            \
129*3f982cf4SFabien Sanglard     static bool needs_warning = true;                                 \
130*3f982cf4SFabien Sanglard     if (needs_warning) {                                              \
131*3f982cf4SFabien Sanglard       OSP_LOG_WARN << __func__ << ": UNIMPLEMENTED() hit.";           \
132*3f982cf4SFabien Sanglard       needs_warning = false;                                          \
133*3f982cf4SFabien Sanglard     }                                                                 \
134*3f982cf4SFabien Sanglard   }
135*3f982cf4SFabien Sanglard 
136*3f982cf4SFabien Sanglard // Since Break() is annotated as noreturn, this will properly signal to the
137*3f982cf4SFabien Sanglard // compiler that this code is truly not reached (and thus doesn't need a return
138*3f982cf4SFabien Sanglard // statement for non-void returning functions/methods).
139*3f982cf4SFabien Sanglard #define OSP_NOTREACHED()                                \
140*3f982cf4SFabien Sanglard   {                                                     \
141*3f982cf4SFabien Sanglard     OSP_LOG_FATAL << __func__ << ": NOTREACHED() hit."; \
142*3f982cf4SFabien Sanglard     Break();                                            \
143*3f982cf4SFabien Sanglard   }
144*3f982cf4SFabien Sanglard 
145*3f982cf4SFabien Sanglard #endif  // UTIL_OSP_LOGGING_H_
146