aboutsummaryrefslogtreecommitdiff
path: root/util/logging.h
diff options
context:
space:
mode:
Diffstat (limited to 'util/logging.h')
-rw-r--r--util/logging.h144
1 files changed, 144 insertions, 0 deletions
diff --git a/util/logging.h b/util/logging.h
new file mode 100644
index 00000000..54870111
--- /dev/null
+++ b/util/logging.h
@@ -0,0 +1,144 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UTIL_LOGGING_H_
+#define UTIL_LOGGING_H_
+
+#include <sstream>
+
+#include "platform/api/logging.h"
+
+namespace openscreen {
+namespace platform {
+namespace internal {
+
+// The stream-based logging macros below are adapted from Chromium's
+// base/logging.h.
+class LogMessage {
+ public:
+ LogMessage(LogLevel level, const char* file, int line)
+ : level_(level), file_(file), line_(line) {}
+
+ ~LogMessage() {
+ LogWithLevel(level_, file_, line_, stream_.str());
+ if (level_ == LogLevel::kFatal) {
+ Break();
+ }
+ }
+
+ std::ostream& stream() { return stream_; }
+
+ protected:
+ const LogLevel level_;
+
+ // The file here comes from the __FILE__ macro, which should persist while
+ // we are doing the logging. Hence, keeping it unmanaged here and not
+ // creating a copy should be safe.
+ const char* const file_;
+ const int line_;
+ std::ostringstream stream_;
+};
+
+// Used by the OSP_LAZY_STREAM macro to return void after evaluating an ostream
+// chain expression.
+class Voidify {
+ public:
+ void operator&(std::ostream&) {}
+};
+
+} // namespace internal
+} // namespace platform
+} // namespace openscreen
+
+#define OSP_LAZY_STREAM(condition, stream) \
+ !(condition) ? (void)0 : openscreen::platform::internal::Voidify() & (stream)
+#define OSP_LOG_IS_ON(level_enum) \
+ openscreen::platform::IsLoggingOn( \
+ openscreen::platform::LogLevel::level_enum, __FILE__)
+#define OSP_LOG_STREAM(level_enum) \
+ openscreen::platform::internal::LogMessage( \
+ openscreen::platform::LogLevel::level_enum, __FILE__, __LINE__) \
+ .stream()
+
+#define OSP_VLOG \
+ OSP_LAZY_STREAM(OSP_LOG_IS_ON(kVerbose), OSP_LOG_STREAM(kVerbose))
+#define OSP_LOG_INFO \
+ OSP_LAZY_STREAM(OSP_LOG_IS_ON(kInfo), OSP_LOG_STREAM(kInfo))
+#define OSP_LOG_WARN \
+ OSP_LAZY_STREAM(OSP_LOG_IS_ON(kWarning), OSP_LOG_STREAM(kWarning))
+#define OSP_LOG_ERROR \
+ OSP_LAZY_STREAM(OSP_LOG_IS_ON(kError), OSP_LOG_STREAM(kError))
+#define OSP_LOG_FATAL \
+ OSP_LAZY_STREAM(OSP_LOG_IS_ON(kFatal), OSP_LOG_STREAM(kFatal))
+
+// TODO(miu): Remove this legacy alias.
+#define OSP_LOG OSP_LOG_INFO
+
+#define OSP_VLOG_IF(condition) !(condition) ? (void)0 : OSP_VLOG
+#define OSP_LOG_IF(level, condition) !(condition) ? (void)0 : OSP_LOG_##level
+
+// TODO(btolsch): Add tests for (D)OSP_CHECK and possibly logging.
+#define OSP_CHECK(condition) \
+ OSP_LOG_IF(FATAL, !(condition)) << "OSP_CHECK(" << #condition << ") failed: "
+
+#define OSP_CHECK_EQ(a, b) \
+ OSP_CHECK((a) == (b)) << (a) << " vs. " << (b) << ": "
+#define OSP_CHECK_NE(a, b) \
+ OSP_CHECK((a) != (b)) << (a) << " vs. " << (b) << ": "
+#define OSP_CHECK_LT(a, b) OSP_CHECK((a) < (b)) << (a) << " vs. " << (b) << ": "
+#define OSP_CHECK_LE(a, b) \
+ OSP_CHECK((a) <= (b)) << (a) << " vs. " << (b) << ": "
+#define OSP_CHECK_GT(a, b) OSP_CHECK((a) > (b)) << (a) << " vs. " << (b) << ": "
+#define OSP_CHECK_GE(a, b) \
+ OSP_CHECK((a) >= (b)) << (a) << " vs. " << (b) << ": "
+
+#if defined(_DEBUG) || defined(DCHECK_ALWAYS_ON)
+#define OSP_DCHECK_IS_ON() 1
+#define OSP_DCHECK(condition) OSP_CHECK(condition)
+#define OSP_DCHECK_EQ(a, b) OSP_CHECK_EQ(a, b)
+#define OSP_DCHECK_NE(a, b) OSP_CHECK_NE(a, b)
+#define OSP_DCHECK_LT(a, b) OSP_CHECK_LT(a, b)
+#define OSP_DCHECK_LE(a, b) OSP_CHECK_LE(a, b)
+#define OSP_DCHECK_GT(a, b) OSP_CHECK_GT(a, b)
+#define OSP_DCHECK_GE(a, b) OSP_CHECK_GE(a, b)
+#else
+#define OSP_DCHECK_IS_ON() 0
+// When DCHECKs are off, nothing will be logged. Use that fact to make
+// references to the |condition| expression (or |a| and |b|) so the compiler
+// won't emit unused variable warnings/errors when DCHECKs are turned off.
+#define OSP_EAT_STREAM OSP_LOG_IF(FATAL, false)
+#define OSP_DCHECK(condition) OSP_EAT_STREAM << !(condition)
+#define OSP_DCHECK_EQ(a, b) OSP_EAT_STREAM << !((a) == (b))
+#define OSP_DCHECK_NE(a, b) OSP_EAT_STREAM << !((a) != (b))
+#define OSP_DCHECK_LT(a, b) OSP_EAT_STREAM << !((a) < (b))
+#define OSP_DCHECK_LE(a, b) OSP_EAT_STREAM << !((a) <= (b))
+#define OSP_DCHECK_GT(a, b) OSP_EAT_STREAM << !((a) > (b))
+#define OSP_DCHECK_GE(a, b) OSP_EAT_STREAM << !((a) >= (b))
+#endif
+
+#define OSP_DVLOG OSP_VLOG_IF(OSP_DCHECK_IS_ON())
+#define OSP_DLOG_INFO OSP_LOG_IF(INFO, OSP_DCHECK_IS_ON())
+#define OSP_DLOG_WARN OSP_LOG_IF(WARN, OSP_DCHECK_IS_ON())
+#define OSP_DLOG_ERROR OSP_LOG_IF(ERROR, OSP_DCHECK_IS_ON())
+#define OSP_DLOG_FATAL OSP_LOG_IF(FATAL, OSP_DCHECK_IS_ON())
+#define OSP_DVLOG_IF(condition) OSP_VLOG_IF(OSP_DCHECK_IS_ON() && (condition))
+#define OSP_DLOG_IF(level, condition) \
+ OSP_LOG_IF(level, OSP_DCHECK_IS_ON() && (condition))
+
+// Log when unimplemented code points are reached: If verbose logging is turned
+// on, log always. Otherwise, just attempt to log once.
+#define OSP_UNIMPLEMENTED() \
+ if (OSP_LOG_IS_ON(kVerbose)) { \
+ OSP_LOG_STREAM(kVerbose) << __func__ << ": UNIMPLEMENTED() hit."; \
+ } else { \
+ static bool needs_warning = true; \
+ if (needs_warning) { \
+ OSP_LOG_WARN << __func__ << ": UNIMPLEMENTED() hit."; \
+ needs_warning = false; \
+ } \
+ }
+
+#define OSP_NOTREACHED() OSP_LOG_FATAL << __func__ << ": NOTREACHED() hit."
+
+#endif // UTIL_LOGGING_H_