Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #ifndef INCLUDED_CLOGGER
19 : #define INCLUDED_CLOGGER
20 :
21 : #include <deque>
22 : #include <fmt/printf.h>
23 : #include <mutex>
24 : #include <string>
25 : #include <sstream>
26 :
27 : class CCanvas2D;
28 :
29 : class CLogger;
30 : extern CLogger* g_Logger;
31 :
32 :
33 : #define LOGMESSAGE(...) g_Logger->WriteMessage(fmt::sprintf(__VA_ARGS__).c_str(), false)
34 : #define LOGMESSAGERENDER(...) g_Logger->WriteMessage(fmt::sprintf(__VA_ARGS__).c_str(), true)
35 : #define LOGWARNING(...) g_Logger->WriteWarning(fmt::sprintf(__VA_ARGS__).c_str())
36 : #define LOGERROR(...) g_Logger->WriteError (fmt::sprintf(__VA_ARGS__).c_str())
37 :
38 : /**
39 : * Error/warning/message logging class.
40 : *
41 : * Thread-safety:
42 : * - Expected to be constructed/destructed in the main thread.
43 : * - The message logging functions may be called from any thread
44 : * while the object is alive.
45 : */
46 : class CLogger
47 : {
48 : NONCOPYABLE(CLogger);
49 : public:
50 : enum ELogMethod
51 : {
52 : Normal,
53 : Error,
54 : Warning
55 : };
56 :
57 : // Default constructor - outputs to normal log files
58 : CLogger();
59 :
60 : // Special constructor (mostly for testing) - outputs to provided streams.
61 : // Can take ownership of streams and delete them in the destructor.
62 : CLogger(std::ostream* mainLog, std::ostream* interestingLog, bool takeOwnership, bool useDebugPrintf);
63 :
64 : ~CLogger();
65 :
66 : // Functions to write different message types (Errors and warnings are placed
67 : // both in mainLog and intrestingLog.)
68 : void WriteMessage(const char* message, bool doRender);
69 : void WriteError (const char* message);
70 : void WriteWarning(const char* message);
71 :
72 : // Render recent log messages onto the screen
73 : void Render(CCanvas2D& canvas);
74 :
75 : private:
76 : void Init();
77 :
78 : void PushRenderMessage(ELogMethod method, const char* message);
79 :
80 : // Delete old timed-out entries from the list of text to render
81 : void CleanupRenderQueue();
82 :
83 : // the output streams
84 : std::ostream* m_MainLog;
85 : std::ostream* m_InterestingLog;
86 : bool m_OwnsStreams;
87 :
88 : // whether errors should be reported via debug_printf (default)
89 : // or suppressed (for tests that intentionally trigger errors)
90 : bool m_UseDebugPrintf;
91 :
92 : // vars to hold message counts
93 : int m_NumberOfMessages;
94 : int m_NumberOfErrors;
95 : int m_NumberOfWarnings;
96 :
97 : // Used for Render()
98 813 : struct RenderedMessage
99 : {
100 : ELogMethod method;
101 : double time;
102 : std::string message;
103 : };
104 : std::deque<RenderedMessage> m_RenderMessages;
105 : double m_RenderLastEraseTime;
106 :
107 : // Lock for all state modified by logging commands
108 : std::mutex m_Mutex;
109 : };
110 :
111 : /**
112 : * Helper class for unit tests - captures all log output while it is in scope,
113 : * and returns it as a single string.
114 : */
115 : class TestLogger
116 : {
117 : NONCOPYABLE(TestLogger);
118 : public:
119 : TestLogger();
120 : ~TestLogger();
121 : std::string GetOutput();
122 : private:
123 : CLogger* m_OldLogger;
124 : std::stringstream m_Stream;
125 : };
126 :
127 : /**
128 : * Helper class for unit tests - redirects all log output to stdout.
129 : */
130 : class TestStdoutLogger
131 : {
132 : NONCOPYABLE(TestStdoutLogger);
133 : public:
134 : TestStdoutLogger();
135 : ~TestStdoutLogger();
136 : private:
137 : CLogger* m_OldLogger;
138 : };
139 :
140 : #endif
|