Add DISABLE_CLASS_COPY macro (and use it)
[oweals/minetest.git] / src / log.h
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef LOG_HEADER
21 #define LOG_HEADER
22
23 #include <map>
24 #include <queue>
25 #include <string>
26 #include <fstream>
27 #include "threads.h"
28
29 class ILogOutput;
30
31 enum LogLevel {
32         LL_NONE, // Special level that is always printed
33         LL_ERROR,
34         LL_WARNING,
35         LL_ACTION,  // In-game actions
36         LL_INFO,
37         LL_VERBOSE,
38         LL_MAX,
39 };
40
41 class Logger {
42 public:
43         void addOutput(ILogOutput *out);
44         void addOutput(ILogOutput *out, LogLevel lev);
45         void addOutputMaxLevel(ILogOutput *out, LogLevel lev);
46         void removeOutput(ILogOutput *out);
47         void setLevelSilenced(LogLevel lev, bool silenced);
48
49         void registerThread(const std::string &name);
50         void deregisterThread();
51
52         void log(LogLevel lev, const std::string &text);
53         // Logs without a prefix
54         void logRaw(LogLevel lev, const std::string &text);
55
56         void setTraceEnabled(bool enable) { m_trace_enabled = enable; }
57         bool getTraceEnabled() { return m_trace_enabled; }
58
59         static LogLevel stringToLevel(const std::string &name);
60         static const std::string getLevelLabel(LogLevel lev);
61
62 private:
63         void logToOutputsRaw(LogLevel, const std::string &line);
64         void logToOutputs(LogLevel, const std::string &combined,
65                 const std::string &time, const std::string &thread_name,
66                 const std::string &payload_text);
67
68         const std::string getThreadName();
69
70         std::vector<ILogOutput *> m_outputs[LL_MAX];
71
72         // Should implement atomic loads and stores (even though it's only
73         // written to when one thread has access currently).
74         // Works on all known architectures (x86, ARM, MIPS).
75         volatile bool m_silenced_levels[LL_MAX];
76         std::map<threadid_t, std::string> m_thread_names;
77         mutable Mutex m_mutex;
78         bool m_trace_enabled;
79 };
80
81 class ILogOutput {
82 public:
83         virtual void logRaw(LogLevel, const std::string &line) = 0;
84         virtual void log(LogLevel, const std::string &combined,
85                 const std::string &time, const std::string &thread_name,
86                 const std::string &payload_text) = 0;
87 };
88
89 class ICombinedLogOutput : public ILogOutput {
90 public:
91         void log(LogLevel lev, const std::string &combined,
92                 const std::string &time, const std::string &thread_name,
93                 const std::string &payload_text)
94         {
95                 logRaw(lev, combined);
96         }
97 };
98
99 class StreamLogOutput : public ICombinedLogOutput {
100 public:
101         StreamLogOutput(std::ostream &stream) :
102                 m_stream(stream)
103         {
104         }
105
106         void logRaw(LogLevel lev, const std::string &line)
107         {
108                 m_stream << line << std::endl;
109         }
110
111 private:
112         std::ostream &m_stream;
113 };
114
115 class FileLogOutput : public ICombinedLogOutput {
116 public:
117         void open(const std::string &filename);
118
119         void logRaw(LogLevel lev, const std::string &line)
120         {
121                 m_stream << line << std::endl;
122         }
123
124 private:
125         std::ofstream m_stream;
126 };
127
128 class LogOutputBuffer : public ICombinedLogOutput {
129 public:
130         LogOutputBuffer(Logger &logger, LogLevel lev) :
131                 m_logger(logger)
132         {
133                 m_logger.addOutput(this, lev);
134         }
135
136         ~LogOutputBuffer()
137         {
138                 m_logger.removeOutput(this);
139         }
140
141         void logRaw(LogLevel lev, const std::string &line)
142         {
143                 m_buffer.push(line);
144         }
145
146         bool empty()
147         {
148                 return m_buffer.empty();
149         }
150
151         std::string get()
152         {
153                 if (empty())
154                         return "";
155                 std::string s = m_buffer.front();
156                 m_buffer.pop();
157                 return s;
158         }
159
160 private:
161         std::queue<std::string> m_buffer;
162         Logger &m_logger;
163 };
164
165
166 extern StreamLogOutput stdout_output;
167 extern StreamLogOutput stderr_output;
168 extern std::ostream null_stream;
169
170 extern std::ostream *dout_con_ptr;
171 extern std::ostream *derr_con_ptr;
172 extern std::ostream *dout_server_ptr;
173 extern std::ostream *derr_server_ptr;
174
175 #ifndef SERVER
176 extern std::ostream *dout_client_ptr;
177 extern std::ostream *derr_client_ptr;
178 #endif
179
180 extern Logger g_logger;
181
182 // Writes directly to all LL_NONE log outputs for g_logger with no prefix.
183 extern std::ostream rawstream;
184
185 extern std::ostream errorstream;
186 extern std::ostream warningstream;
187 extern std::ostream actionstream;
188 extern std::ostream infostream;
189 extern std::ostream verbosestream;
190 extern std::ostream dstream;
191
192 #define TRACEDO(x) do {               \
193         if (g_logger.getTraceEnabled()) { \
194                 x;                            \
195         }                                 \
196 } while (0)
197
198 #define TRACESTREAM(x) TRACEDO(verbosestream x)
199
200 #define dout_con (*dout_con_ptr)
201 #define derr_con (*derr_con_ptr)
202 #define dout_server (*dout_server_ptr)
203 #define derr_server (*derr_server_ptr)
204
205 #ifndef SERVER
206         #define dout_client (*dout_client_ptr)
207         #define derr_client (*derr_client_ptr)
208 #endif
209
210
211 #endif