aboutsummaryrefslogtreecommitdiff
path: root/util/logging.h
blob: 4c76040e684198680cf94735e6a8e8d5074b0806 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// 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 <utility>

#include "platform/api/logging.h"

namespace openscreen {
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_, std::move(stream_));
    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::stringstream 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 openscreen

#define OSP_LAZY_STREAM(condition, stream) \
  !(condition) ? (void)0 : openscreen::internal::Voidify() & (stream)
#define OSP_LOG_IS_ON(level_enum) \
  openscreen::IsLoggingOn(openscreen::LogLevel::level_enum, __FILE__)
#define OSP_LOG_STREAM(level_enum)                                             \
  openscreen::internal::LogMessage(openscreen::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_