summaryrefslogtreecommitdiff
path: root/chromium/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_logging_impl.h
blob: c2372cab45bd56007405a5794806255913ee7bd3 (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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2021 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.

// This file does not actually implement logging, it merely provides enough of
// logging code for QUICHE to compile and pass the unit tests.  QUICHE embedders
// are encouraged to override this file with their own logic.  If at some point
// logging becomes a part of Abseil, this file will likely start using that
// instead.

#ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_LOGGING_IMPL_H_
#define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_LOGGING_IMPL_H_

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>

#include "absl/base/attributes.h"
#include "quiche/common/platform/api/quiche_export.h"
#include "quiche_platform_impl/quiche_stack_trace_impl.h"

namespace quiche {

class QUICHE_EXPORT_PRIVATE LogStreamVoidHelper {
 public:
  // This operator has lower precedence than << but higher than ?:, which is
  // useful for implementing QUICHE_DISREGARD_LOG_STREAM below.
  constexpr void operator&(std::ostream&) {}
};

// NoopLogSink provides a log sink that does not put the data that it logs
// anywhere.
class QUICHE_EXPORT_PRIVATE NoopLogSink {
 public:
  NoopLogSink() {}

  template <typename T>
  constexpr NoopLogSink(const T&) {}

  template <typename T1, typename T2>
  constexpr NoopLogSink(const T1&, const T2&) {}

  constexpr std::ostream& stream() { return stream_; }

 protected:
  std::string str() { return stream_.str(); }

 private:
  std::stringstream stream_;
};

// We need to actually implement LOG(FATAL), otherwise some functions will fail
// to compile due to the "failed to return value from non-void function" error.
class QUICHE_EXPORT_PRIVATE FatalLogSink : public NoopLogSink {
 public:
  ABSL_ATTRIBUTE_NORETURN ~FatalLogSink() {
    std::cerr << str() << std::endl;
    std::cerr << quiche::QuicheStackTraceImpl() << std::endl;
    abort();
  }
};

class QUICHE_EXPORT_PRIVATE CheckLogSink : public NoopLogSink {
 public:
  CheckLogSink(bool condition) : condition_(condition) {}
  ~CheckLogSink() {
    if (!condition_) {
      std::cerr << "Check failed: " << str() << std::endl;
      std::cerr << quiche::QuicheStackTraceImpl() << std::endl;
      abort();
    }
  }

 private:
  const bool condition_;
};

}  // namespace quiche

// This is necessary because we sometimes call QUICHE_DCHECK inside constexpr
// functions, and then write non-constexpr expressions into the resulting log.
#define QUICHE_CONDITIONAL_LOG_STREAM(stream, condition) \
  !(condition) ? (void)0 : ::quiche::LogStreamVoidHelper() & (stream)
#define QUICHE_DISREGARD_LOG_STREAM(stream) \
  QUICHE_CONDITIONAL_LOG_STREAM(stream, /*condition=*/false)
#define QUICHE_NOOP_STREAM() \
  QUICHE_DISREGARD_LOG_STREAM(::quiche::NoopLogSink().stream())
#define QUICHE_NOOP_STREAM_WITH_CONDITION(condition) \
  QUICHE_DISREGARD_LOG_STREAM(::quiche::NoopLogSink(condition).stream())

#define QUICHE_DVLOG_IMPL(verbose_level) QUICHE_NOOP_STREAM()
#define QUICHE_DVLOG_IF_IMPL(verbose_level, condition) \
  QUICHE_NOOP_STREAM_WITH_CONDITION(condition)
#define QUICHE_DLOG_IMPL(severity) QUICHE_NOOP_STREAM()
#define QUICHE_VLOG_IMPL(verbose_level) QUICHE_NOOP_STREAM()
#define QUICHE_LOG_FIRST_N_IMPL(severity, n) QUICHE_NOOP_STREAM()
#define QUICHE_LOG_EVERY_N_SEC_IMPL(severity, seconds) QUICHE_NOOP_STREAM()

#define QUICHE_LOG_IMPL(severity) QUICHE_LOG_IMPL_##severity()
#define QUICHE_LOG_IMPL_FATAL() ::quiche::FatalLogSink().stream()
#define QUICHE_LOG_IMPL_ERROR() ::quiche::NoopLogSink().stream()
#define QUICHE_LOG_IMPL_WARNING() ::quiche::NoopLogSink().stream()
#define QUICHE_LOG_IMPL_INFO() ::quiche::NoopLogSink().stream()

#define QUICHE_LOG_IF_IMPL(severity, condition) \
  QUICHE_CONDITIONAL_LOG_STREAM(QUICHE_LOG_IMPL_##severity(), condition)

#ifdef NDEBUG
#define QUICHE_LOG_IMPL_DFATAL() ::quiche::NoopLogSink().stream()
#define QUICHE_DLOG_IF_IMPL(severity, condition) \
  QUICHE_NOOP_STREAM_WITH_CONDITION(condition)
#else
#define QUICHE_LOG_IMPL_DFATAL() ::quiche::FatalLogSink().stream()
#define QUICHE_DLOG_IF_IMPL(severity, condition) \
  QUICHE_CONDITIONAL_LOG_STREAM(QUICHE_LOG_IMPL_##severity(), condition)
#endif

#define QUICHE_PLOG_IMPL(severity) QUICHE_NOOP_STREAM()

#define QUICHE_DLOG_INFO_IS_ON_IMPL() false
#define QUICHE_LOG_INFO_IS_ON_IMPL() false
#define QUICHE_LOG_WARNING_IS_ON_IMPL() false
#define QUICHE_LOG_ERROR_IS_ON_IMPL() false

#define QUICHE_CHECK_IMPL(condition) \
  ::quiche::CheckLogSink(static_cast<bool>(condition)).stream()
#define QUICHE_CHECK_EQ_IMPL(val1, val2) \
  ::quiche::CheckLogSink((val1) == (val2)).stream()
#define QUICHE_CHECK_NE_IMPL(val1, val2) \
  ::quiche::CheckLogSink((val1) != (val2)).stream()
#define QUICHE_CHECK_LE_IMPL(val1, val2) \
  ::quiche::CheckLogSink((val1) <= (val2)).stream()
#define QUICHE_CHECK_LT_IMPL(val1, val2) \
  ::quiche::CheckLogSink((val1) < (val2)).stream()
#define QUICHE_CHECK_GE_IMPL(val1, val2) \
  ::quiche::CheckLogSink((val1) >= (val2)).stream()
#define QUICHE_CHECK_GT_IMPL(val1, val2) \
  ::quiche::CheckLogSink((val1) > (val2)).stream()
#define QUICHE_CHECK_OK_IMPL(status) \
  QUICHE_CHECK_EQ_IMPL(absl::OkStatus(), (status))

#ifdef NDEBUG
#define QUICHE_DCHECK_IMPL(condition) \
  QUICHE_NOOP_STREAM_WITH_CONDITION((condition))
#else
#define QUICHE_DCHECK_IMPL(condition)                       \
  QUICHE_LOG_IF_IMPL(DFATAL, !static_cast<bool>(condition)) \
      << "Check failed: " << #condition
#endif
#define QUICHE_DCHECK_EQ_IMPL(val1, val2) QUICHE_DCHECK_IMPL((val1) == (val2))
#define QUICHE_DCHECK_NE_IMPL(val1, val2) QUICHE_DCHECK_IMPL((val1) != (val2))
#define QUICHE_DCHECK_LE_IMPL(val1, val2) QUICHE_DCHECK_IMPL((val1) <= (val2))
#define QUICHE_DCHECK_LT_IMPL(val1, val2) QUICHE_DCHECK_IMPL((val1) < (val2))
#define QUICHE_DCHECK_GE_IMPL(val1, val2) QUICHE_DCHECK_IMPL((val1) >= (val2))
#define QUICHE_DCHECK_GT_IMPL(val1, val2) QUICHE_DCHECK_IMPL((val1) > (val2))

#define QUICHE_NOTREACHED_IMPL() QUICHE_DCHECK_IMPL(false)

#endif  // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_LOGGING_IMPL_H_