TrinityCore
Loading...
Searching...
No Matches
AppenderConsole.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "AppenderConsole.h"
19#include "LogMessage.h"
20#include "SmartEnum.h"
21#include "StringFormat.h"
22#include "StringConvert.h"
23#include "Util.h"
24#include <sstream>
25
26#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
27 #include <Windows.h>
28#endif
29
30AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args)
31 : Appender(id, name, level, flags), _colored(false)
32{
33 for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i)
35
36 if (3 < args.size())
37 InitColors(name, args[3]);
38}
39
40void AppenderConsole::InitColors(std::string const& name, std::string_view str)
41{
42 if (str.empty())
43 {
44 _colored = false;
45 return;
46 }
47
48 std::vector<std::string_view> colorStrs = Trinity::Tokenize(str, ' ', false);
49 if (colorStrs.size() != NUM_ENABLED_LOG_LEVELS)
50 {
51 throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Invalid color data '{}' for console appender {} (expected {} entries, got {})",
52 str, name, NUM_ENABLED_LOG_LEVELS, colorStrs.size()));
53 }
54
55 for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i)
56 {
57 if (Optional<uint8> color = Trinity::StringTo<uint8>(colorStrs[i]); color && EnumUtils::IsValid<ColorTypes>(*color))
58 _colors[i] = static_cast<ColorTypes>(*color);
59 else
60 {
61 throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Invalid color '{}' for log level {} on console appender {}",
62 colorStrs[i], EnumUtils::ToTitle(static_cast<LogLevel>(i)), name));
63 }
64 }
65
66 _colored = true;
67}
68
69void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color)
70{
71#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
72 static WORD WinColorFG[NUM_COLOR_TYPES] =
73 {
74 0, // BLACK
75 FOREGROUND_RED, // RED
76 FOREGROUND_GREEN, // GREEN
77 FOREGROUND_RED | FOREGROUND_GREEN, // BROWN
78 FOREGROUND_BLUE, // BLUE
79 FOREGROUND_RED | FOREGROUND_BLUE, // MAGENTA
80 FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN
81 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // WHITE
82 // YELLOW
83 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
84 // RED_BOLD
85 FOREGROUND_RED | FOREGROUND_INTENSITY,
86 // GREEN_BOLD
87 FOREGROUND_GREEN | FOREGROUND_INTENSITY,
88 FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD
89 // MAGENTA_BOLD
90 FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
91 // CYAN_BOLD
92 FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
93 // WHITE_BOLD
94 FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
95 };
96
97 HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
98 SetConsoleTextAttribute(hConsole, WinColorFG[color]);
99#else
100 enum ANSITextAttr
101 {
102 TA_NORMAL = 0,
103 TA_BOLD = 1,
104 TA_BLINK = 5,
105 TA_REVERSE = 7
106 };
107
108 enum ANSIFgTextAttr
109 {
110 FG_BLACK = 30,
111 FG_RED,
112 FG_GREEN,
113 FG_BROWN,
114 FG_BLUE,
115 FG_MAGENTA,
116 FG_CYAN,
117 FG_WHITE,
118 FG_YELLOW
119 };
120
121 enum ANSIBgTextAttr
122 {
123 BG_BLACK = 40,
124 BG_RED,
125 BG_GREEN,
126 BG_BROWN,
127 BG_BLUE,
128 BG_MAGENTA,
129 BG_CYAN,
130 BG_WHITE
131 };
132
133 static uint8 UnixColorFG[NUM_COLOR_TYPES] =
134 {
135 FG_BLACK, // BLACK
136 FG_RED, // RED
137 FG_GREEN, // GREEN
138 FG_BROWN, // BROWN
139 FG_BLUE, // BLUE
140 FG_MAGENTA, // MAGENTA
141 FG_CYAN, // CYAN
142 FG_WHITE, // WHITE
143 FG_YELLOW, // YELLOW
144 FG_RED, // LRED
145 FG_GREEN, // LGREEN
146 FG_BLUE, // LBLUE
147 FG_MAGENTA, // LMAGENTA
148 FG_CYAN, // LCYAN
149 FG_WHITE // LWHITE
150 };
151
152 fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < NUM_COLOR_TYPES ? ";1" : ""));
153 #endif
154}
155
156void AppenderConsole::ResetColor(bool stdout_stream)
157{
158 #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
159 HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
160 SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
161 #else
162 fprintf((stdout_stream ? stdout : stderr), "\x1b[0m");
163 #endif
164}
165
166void AppenderConsole::Print(std::string const& str, bool error)
167{
168#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
169 WriteWinConsole(str + "\n", error);
170#else
171 utf8printf(error ? stderr : stdout, "%s\n", str.c_str());
172#endif
173}
174
176{
177 bool stdout_stream = !(message->level == LOG_LEVEL_ERROR || message->level == LOG_LEVEL_FATAL);
178
179 if (_colored)
180 {
181 uint8 index;
182 switch (message->level)
183 {
184 case LOG_LEVEL_TRACE:
185 index = 5;
186 break;
187 case LOG_LEVEL_DEBUG:
188 index = 4;
189 break;
190 case LOG_LEVEL_INFO:
191 index = 3;
192 break;
193 case LOG_LEVEL_WARN:
194 index = 2;
195 break;
196 case LOG_LEVEL_FATAL:
197 index = 0;
198 break;
199 case LOG_LEVEL_ERROR:
200 [[fallthrough]];
201 default:
202 index = 1;
203 break;
204 }
205
206 SetColor(stdout_stream, _colors[index]);
207 Print(message->prefix + message->text, !stdout_stream);
208 ResetColor(stdout_stream);
209 }
210 else
211 Print(message->prefix + message->text, !stdout_stream);
212}
ColorTypes
@ NUM_COLOR_TYPES
@ YELLOW
uint8_t uint8
Definition Define.h:135
uint16 flags
AppenderFlags
Definition LogCommon.h:50
LogLevel
Definition LogCommon.h:25
@ NUM_ENABLED_LOG_LEVELS
Definition LogCommon.h:34
@ LOG_LEVEL_DEBUG
Definition LogCommon.h:28
@ LOG_LEVEL_ERROR
Definition LogCommon.h:31
@ LOG_LEVEL_FATAL
Definition LogCommon.h:32
@ LOG_LEVEL_TRACE
Definition LogCommon.h:27
@ LOG_LEVEL_WARN
Definition LogCommon.h:30
@ LOG_LEVEL_INFO
Definition LogCommon.h:29
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
bool WriteWinConsole(std::string_view str, bool error)
Definition Util.cpp:641
void utf8printf(FILE *out, const char *str,...)
Definition Util.cpp:581
void InitColors(std::string const &name, std::string_view init_str)
void ResetColor(bool stdout_stream)
void Print(std::string const &str, bool error)
void SetColor(bool stdout_stream, ColorTypes color)
void _write(LogMessage const *message) override
AppenderConsole(uint8 _id, std::string const &name, LogLevel level, AppenderFlags flags, std::vector< std::string_view > const &args)
ColorTypes _colors[NUM_ENABLED_LOG_LEVELS]
std::string name
Definition Appender.h:50
static char const * ToTitle(Enum value)
Definition SmartEnum.h:123
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
Definition Util.cpp:56
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
LogLevel const level
Definition LogMessage.h:37
std::string const text
Definition LogMessage.h:39
std::string prefix
Definition LogMessage.h:40