blob: 1f051f03e345788b110a037908228ace2356ca69 [file] [log] [blame]
btolsch9d6900c2018-05-30 18:22:53 -07001// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef PLATFORM_API_LOGGING_H_
6#define PLATFORM_API_LOGGING_H_
7
8#include <sstream>
9
btolsch2f2e7fa2019-03-29 16:48:49 -070010#include "absl/strings/string_view.h"
Jordan Baylesd08f8d22019-01-17 15:06:02 -080011
btolsch9d6900c2018-05-30 18:22:53 -070012namespace openscreen {
13namespace platform {
14
15enum class LogLevel {
16 kVerbose = 0,
17 kInfo,
18 kWarning,
19 kError,
20 kFatal,
21};
22
23std::string LogLevelToString(LogLevel level);
24
25//
26// PLATFORM IMPLEMENTATION
btolsch6d3d0bc2018-12-10 18:59:28 -080027// The following functions must be implemented by the platform.
28void LogInit(const char* filename);
Jordan Baylesf2591472019-02-16 12:04:50 -080029void SetLogLevel(LogLevel level);
btolsch9d6900c2018-05-30 18:22:53 -070030void LogWithLevel(LogLevel level,
Jordan Baylesd08f8d22019-01-17 15:06:02 -080031 absl::string_view file,
btolsch9d6900c2018-05-30 18:22:53 -070032 int line,
Jordan Baylesd08f8d22019-01-17 15:06:02 -080033 absl::string_view msg);
btolsch9d6900c2018-05-30 18:22:53 -070034void Break();
35//
36// END PLATFORM IMPLEMENTATION
37//
38
39// The stream-based logging macros below are adapted from Chromium's
40// base/logging.h.
41class LogMessage {
42 public:
Jordan Baylesf2591472019-02-16 12:04:50 -080043 LogMessage(LogLevel level, absl::string_view file, int line);
btolsch9d6900c2018-05-30 18:22:53 -070044 ~LogMessage();
45
46 std::ostream& stream() { return stream_; }
47
48 private:
49 const LogLevel level_;
Jordan Baylesd08f8d22019-01-17 15:06:02 -080050
51 // The file here comes from the __FILE__ macro, which should persist while
52 // we are doing the logging. Hence, keeping it unmanaged here and not
53 // creating a copy should be safe.
54 absl::string_view const file_;
btolsch9d6900c2018-05-30 18:22:53 -070055 const int line_;
56 std::ostringstream stream_;
57};
58
Jordan Baylesf2591472019-02-16 12:04:50 -080059// OSP_LOG_* are defined as macros so we can access the handy
60// __FILE__ and __LINE__ expansions.
61
62#define OSP_VLOG \
63 openscreen::platform::LogMessage(openscreen::platform::LogLevel::kVerbose, \
64 __FILE__, __LINE__) \
btolsch9d6900c2018-05-30 18:22:53 -070065 .stream()
Jordan Baylesf2591472019-02-16 12:04:50 -080066
Jordan Baylesf2591472019-02-16 12:04:50 -080067#define OSP_LOG_INFO \
68 openscreen::platform::LogMessage(openscreen::platform::LogLevel::kInfo, \
69 __FILE__, __LINE__) \
btolsch9d6900c2018-05-30 18:22:53 -070070 .stream()
Jordan Baylesf2591472019-02-16 12:04:50 -080071#define OSP_LOG OSP_LOG_INFO
72
73#define OSP_LOG_WARN \
74 openscreen::platform::LogMessage(openscreen::platform::LogLevel::kWarning, \
75 __FILE__, __LINE__) \
btolsch9d6900c2018-05-30 18:22:53 -070076 .stream()
Jordan Baylesf2591472019-02-16 12:04:50 -080077#define OSP_LOG_ERROR \
78 openscreen::platform::LogMessage(openscreen::platform::LogLevel::kError, \
79 __FILE__, __LINE__) \
btolsch9d6900c2018-05-30 18:22:53 -070080 .stream()
Jordan Baylesf2591472019-02-16 12:04:50 -080081#define OSP_LOG_FATAL \
82 openscreen::platform::LogMessage(openscreen::platform::LogLevel::kFatal, \
83 __FILE__, __LINE__) \
btolsch9d6900c2018-05-30 18:22:53 -070084 .stream()
85
86namespace detail {
87
88class Voidify {
89 public:
90 Voidify() = default;
91 void operator&(std::ostream&) {}
92};
93
94} // namespace detail
95
btolschfc647682018-11-13 23:43:33 -080096#define OSP_LAZY_STREAM(stream, condition) \
Jordan Baylesf2591472019-02-16 12:04:50 -080097 !(condition) ? (void)0 : openscreen::platform::detail::Voidify() & (stream)
98#define OSP_EAT_STREAM OSP_LAZY_STREAM(OSP_LOG, false)
btolsch2f2e7fa2019-03-29 16:48:49 -070099#define OSP_VLOG_IF(condition) OSP_LAZY_STREAM(OSP_VLOG, (condition))
btolschfc647682018-11-13 23:43:33 -0800100#define OSP_LOG_IF(level, condition) \
101 OSP_LAZY_STREAM(OSP_LOG_##level, (condition))
btolsch9d6900c2018-05-30 18:22:53 -0700102
btolschfc647682018-11-13 23:43:33 -0800103// TODO(btolsch): Add tests for (D)OSP_CHECK and possibly logging.
104#define OSP_CHECK(condition) \
105 OSP_LAZY_STREAM(OSP_LOG_FATAL, !(condition)) \
106 << "OSP_CHECK(" << #condition << ") failed: "
btolsch9d6900c2018-05-30 18:22:53 -0700107
Yuri Wiitala981576c2019-03-22 18:05:53 -0700108#define OSP_CHECK_EQ(a, b) \
109 OSP_CHECK((a) == (b)) << (a) << " vs. " << (b) << ": "
110#define OSP_CHECK_NE(a, b) \
111 OSP_CHECK((a) != (b)) << (a) << " vs. " << (b) << ": "
112#define OSP_CHECK_LT(a, b) OSP_CHECK((a) < (b)) << (a) << " vs. " << (b) << ": "
113#define OSP_CHECK_LE(a, b) \
114 OSP_CHECK((a) <= (b)) << (a) << " vs. " << (b) << ": "
115#define OSP_CHECK_GT(a, b) OSP_CHECK((a) > (b)) << (a) << " vs. " << (b) << ": "
116#define OSP_CHECK_GE(a, b) \
117 OSP_CHECK((a) >= (b)) << (a) << " vs. " << (b) << ": "
btolsch834accf2018-06-13 23:10:28 -0700118
Yuri Wiitala0233cdd2019-02-04 17:57:25 -0800119#if defined(_DEBUG) || defined(DCHECK_ALWAYS_ON)
btolschfc647682018-11-13 23:43:33 -0800120#define OSP_DCHECK_IS_ON() 1
121#define OSP_DCHECK(condition) OSP_CHECK(condition)
122#define OSP_DCHECK_EQ(a, b) OSP_CHECK_EQ(a, b)
123#define OSP_DCHECK_NE(a, b) OSP_CHECK_NE(a, b)
124#define OSP_DCHECK_LT(a, b) OSP_CHECK_LT(a, b)
125#define OSP_DCHECK_LE(a, b) OSP_CHECK_LE(a, b)
126#define OSP_DCHECK_GT(a, b) OSP_CHECK_GT(a, b)
127#define OSP_DCHECK_GE(a, b) OSP_CHECK_GE(a, b)
btolsch9d6900c2018-05-30 18:22:53 -0700128#else
btolschfc647682018-11-13 23:43:33 -0800129#define OSP_DCHECK_IS_ON() 0
Yuri Wiitala0233cdd2019-02-04 17:57:25 -0800130// When DCHECKs are off, nothing will be logged. Use that fact to make
131// references to the |condition| expression (or |a| and |b|) so the compiler
132// won't emit unused variable warnings/errors when DCHECKs are turned off.
133#define OSP_DCHECK(condition) OSP_EAT_STREAM << !(condition)
134#define OSP_DCHECK_EQ(a, b) OSP_EAT_STREAM << !((a) == (b))
135#define OSP_DCHECK_NE(a, b) OSP_EAT_STREAM << !((a) != (b))
136#define OSP_DCHECK_LT(a, b) OSP_EAT_STREAM << !((a) < (b))
137#define OSP_DCHECK_LE(a, b) OSP_EAT_STREAM << !((a) <= (b))
138#define OSP_DCHECK_GT(a, b) OSP_EAT_STREAM << !((a) > (b))
139#define OSP_DCHECK_GE(a, b) OSP_EAT_STREAM << !((a) >= (b))
btolsch9d6900c2018-05-30 18:22:53 -0700140#endif
141
btolsch2f2e7fa2019-03-29 16:48:49 -0700142#define OSP_DVLOG OSP_VLOG_IF(OSP_DCHECK_IS_ON())
btolschfc647682018-11-13 23:43:33 -0800143#define OSP_DLOG_INFO OSP_LOG_IF(INFO, OSP_DCHECK_IS_ON())
144#define OSP_DLOG_WARN OSP_LOG_IF(WARN, OSP_DCHECK_IS_ON())
145#define OSP_DLOG_ERROR OSP_LOG_IF(ERROR, OSP_DCHECK_IS_ON())
146#define OSP_DLOG_FATAL OSP_LOG_IF(FATAL, OSP_DCHECK_IS_ON())
btolsch2f2e7fa2019-03-29 16:48:49 -0700147#define OSP_DVLOG_IF(condition) OSP_VLOG_IF(OSP_DCHECK_IS_ON() && (condition))
btolschfc647682018-11-13 23:43:33 -0800148#define OSP_DLOG_IF(level, condition) \
149 OSP_LOG_IF(level, OSP_DCHECK_IS_ON() && (condition))
Jordan Bayles8ccb4852019-01-16 18:51:27 -0800150
btolschfc647682018-11-13 23:43:33 -0800151#define OSP_UNIMPLEMENTED() OSP_LOG_ERROR << __func__ << ": unimplemented"
btolsch4b68dc92018-07-26 00:26:54 -0700152
Yuri Wiitala10dea9f2019-02-04 20:19:17 -0800153#define OSP_NOTREACHED() OSP_CHECK(false) << __func__ << ": NOTREACHED() hit."
154
btolsch9d6900c2018-05-30 18:22:53 -0700155} // namespace platform
156} // namespace openscreen
157
btolscha21e8ed2018-08-30 15:13:48 -0700158#endif // PLATFORM_API_LOGGING_H_