Luanti 5.11.0-dev
 
Loading...
Searching...
No Matches
log.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later
2
3#pragma once
4
5#include "util/basic_macros.h"
6#include "util/stream.h"
7
8/*
9 * LogTarget
10 *
11 * This is the interface that sits between the LogStreams and the global logger.
12 * Primarily used to route streams to log levels, but could also enable other
13 * custom behavior.
14 *
15 */
16class LogTarget {
17public:
18 // Must be thread-safe. These can be called from any thread.
19 virtual bool hasOutput() = 0;
20 virtual void log(std::string_view buf) = 0;
21};
22
23
24/*
25 * StreamProxy
26 *
27 * An ostream-like object that can proxy to a real ostream or do nothing,
28 * depending on how it is configured. See LogStream below.
29 *
30 */
32public:
33 StreamProxy(std::ostream *os) : m_os(os) { }
34
35 static void fix_stream_state(std::ostream &os);
36
37 template<typename T>
39 {
40 if (m_os) {
41 if (!m_os->good())
44 }
45 return *this;
46 }
47
48 StreamProxy& operator<<(std::ostream& (*manip)(std::ostream&))
49 {
50 if (m_os) {
51 if (!m_os->good())
53 *m_os << manip;
54 }
55 return *this;
56 }
57
58private:
59 template<typename T>
61 {
62 // These calls explicitly use the templated version of operator<<,
63 // so that they won't use the overloads created by ADD_NULL_CHECK.
64 if (arg == nullptr)
65 return this->operator<< <const char*> ("(null)");
66 else
67 return this->operator<< <T>(std::forward<T>(arg));
68 }
69
70public:
71 // Add specific overrides for operator<< which check for NULL string
72 // pointers. This is undefined behavior in the C++ spec, so emit "(null)"
73 // instead. These are method overloads, rather than template specializations.
74#define ADD_NULL_CHECK(_type) \
75 StreamProxy& operator<<(_type arg) \
76 { \
77 return emit_with_null_check(std::forward<_type>(arg)); \
78 }
79
80 ADD_NULL_CHECK(char*)
81 ADD_NULL_CHECK(unsigned char*)
82 ADD_NULL_CHECK(signed char*)
83 ADD_NULL_CHECK(const char*)
84 ADD_NULL_CHECK(const unsigned char*)
85 ADD_NULL_CHECK(const signed char*)
86
87#undef ADD_NULL_CHECK
88
89private:
90 std::ostream *m_os;
91};
92
93
94/*
95 * LogStream
96 *
97 * The public interface for log streams (infostream, verbosestream, etc).
98 *
99 * LogStream minimizes the work done when a given stream is off. (meaning
100 * it has no output targets, so it goes to /dev/null)
101 *
102 * For example, consider:
103 *
104 * verbosestream << "hello world" << 123 << std::endl;
105 *
106 * The compiler evaluates this as:
107 *
108 * (((verbosestream << "hello world") << 123) << std::endl)
109 * ^ ^
110 *
111 * If `verbosestream` is on, the innermost expression (marked by ^) will return
112 * a StreamProxy that forwards to a real ostream, that feeds into the logger.
113 * However, if `verbosestream` is off, it will return a StreamProxy that does
114 * nothing on all later operations. Specifically, CPU time won't be wasted
115 * writing "hello world" and 123 into a buffer, or formatting the log entry.
116 *
117 * It is also possible to directly check if the stream is on/off:
118 *
119 * if (verbosestream) {
120 * auto data = ComputeExpensiveDataForTheLog();
121 * verbosestream << data << endl;
122 * }
123 *
124*/
125
127public:
128 LogStream() = delete;
130
132 m_target(target),
133 m_buffer(std::bind(&LogStream::internalFlush, this, std::placeholders::_1)),
138 m_dummy_proxy(nullptr) { }
139
140 template<typename T>
143 sp << std::forward<T>(arg);
144 return sp;
145 }
146
147 StreamProxy& operator<<(std::ostream& (*manip)(std::ostream&)) {
149 sp << manip;
150 return sp;
151 }
152
153 operator bool() {
154 return m_target.hasOutput();
155 }
156
157 void internalFlush(std::string_view buf) {
158 m_target.log(buf);
159 }
160
161 operator std::ostream&() {
163 }
164
165private:
166 // 10 streams per thread x (256 + overhead) ~ 3K per thread
167 static const int BUFFER_LENGTH = 256;
171 std::ostream m_stream;
172 std::ostream m_dummy_stream;
175
176};
177
178/*
179 * By making the streams thread_local, each thread has its own
180 * private buffer. Two or more threads can write to the same stream
181 * simultaneously (lock-free), and there won't be any interference.
182 *
183 * The finished lines are sent to a LogTarget which is a global (not thread-local)
184 * object, and from there relayed to g_logger. The final writes are serialized
185 * by the mutex in g_logger.
186*/
187
188extern thread_local LogStream dstream;
189extern thread_local LogStream rawstream; // Writes directly to all LL_NONE log outputs with no prefix.
190extern thread_local LogStream errorstream;
191extern thread_local LogStream warningstream;
192extern thread_local LogStream actionstream;
193extern thread_local LogStream infostream;
194extern thread_local LogStream verbosestream;
195extern thread_local LogStream tracestream;
196// TODO: Search/replace these with verbose/tracestream
197extern thread_local LogStream derr_con;
198extern thread_local LogStream dout_con;
199
200#define TRACESTREAM(x) do { \
201 if (tracestream) { \
202 tracestream x; \
203 } \
204} while (0)
Definition stream.h:55
Definition log.h:126
StreamProxy & operator<<(std::ostream &(*manip)(std::ostream &))
Definition log.h:147
std::ostream m_dummy_stream
Definition log.h:172
LogStream(LogTarget &target)
Definition log.h:131
StreamProxy m_dummy_proxy
Definition log.h:174
std::ostream m_stream
Definition log.h:171
StreamProxy & operator<<(T &&arg)
Definition log.h:141
LogTarget & m_target
Definition log.h:168
LogStream()=delete
DummyStreamBuffer m_dummy_buffer
Definition log.h:170
StreamProxy m_proxy
Definition log.h:173
StringStreamBuffer< BUFFER_LENGTH > m_buffer
Definition log.h:169
DISABLE_CLASS_COPY(LogStream)
void internalFlush(std::string_view buf)
Definition log.h:157
static const int BUFFER_LENGTH
Definition log.h:167
Definition log.h:16
virtual bool hasOutput()=0
virtual void log(std::string_view buf)=0
Definition log.h:31
StreamProxy & operator<<(T &&arg)
Definition log.h:38
std::ostream * m_os
Definition log.h:90
static void fix_stream_state(std::ostream &os)
Definition log.cpp:359
StreamProxy & emit_with_null_check(T &&arg)
Definition log.h:60
StreamProxy & operator<<(std::ostream &(*manip)(std::ostream &))
Definition log.h:48
StreamProxy(std::ostream *os)
Definition log.h:33
Definition stream.h:12
#define ADD_NULL_CHECK(_type)
Definition log.h:74
thread_local LogStream infostream
thread_local LogStream errorstream
thread_local LogStream actionstream
thread_local LogStream derr_con
thread_local LogStream dstream
thread_local LogStream tracestream
thread_local LogStream rawstream
thread_local LogStream warningstream
thread_local LogStream verbosestream
thread_local LogStream dout_con