1 // 2 // Copyright(c) 2016 spdlog 3 // Distributed under the MIT License (http://opensource.org/licenses/MIT) 4 // 5 6 #pragma once 7 8 #include <spdlog/sinks/base_sink.h> 9 #include <spdlog/details/null_mutex.h> 10 #include <spdlog/common.h> 11 12 #include <mutex> 13 #include <string> 14 #include <map> 15 #include <wincon.h> 16 17 namespace spdlog 18 { 19 namespace sinks 20 { 21 /* 22 * Windows color console sink. Uses WriteConsoleA to write to the console with colors 23 */ 24 template<class Mutex> 25 class wincolor_sink: public base_sink<Mutex> 26 { 27 public: 28 const WORD BOLD = FOREGROUND_INTENSITY; 29 const WORD RED = FOREGROUND_RED; 30 const WORD CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE; 31 const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; 32 const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN; 33 wincolor_sink(HANDLE std_handle)34 wincolor_sink(HANDLE std_handle): out_handle_(std_handle) 35 { 36 colors_[level::trace] = CYAN; 37 colors_[level::debug] = CYAN; 38 colors_[level::info] = WHITE | BOLD; 39 colors_[level::warn] = YELLOW | BOLD; 40 colors_[level::err] = RED | BOLD; // red bold 41 colors_[level::critical] = BACKGROUND_RED | WHITE | BOLD; // white bold on red background 42 colors_[level::off] = 0; 43 } 44 ~wincolor_sink()45 virtual ~wincolor_sink() 46 { 47 flush(); 48 } 49 50 wincolor_sink(const wincolor_sink& other) = delete; 51 wincolor_sink& operator=(const wincolor_sink& other) = delete; 52 _sink_it(const details::log_msg & msg)53 virtual void _sink_it(const details::log_msg& msg) override 54 { 55 auto color = colors_[msg.level]; 56 auto orig_attribs = set_console_attribs(color); 57 WriteConsoleA(out_handle_, msg.formatted.data(), static_cast<DWORD>(msg.formatted.size()), nullptr, nullptr); 58 SetConsoleTextAttribute(out_handle_, orig_attribs); //reset to orig colors 59 } 60 flush()61 virtual void flush() override 62 { 63 // windows console always flushed? 64 } 65 66 // change the color for the given level set_color(level::level_enum level,WORD color)67 void set_color(level::level_enum level, WORD color) 68 { 69 std::lock_guard<Mutex> lock(_mutex); 70 colors_[level] = color; 71 } 72 73 private: 74 HANDLE out_handle_; 75 std::map<level::level_enum, WORD> colors_; 76 77 // set color and return the orig console attributes (for resetting later) set_console_attribs(WORD attribs)78 WORD set_console_attribs(WORD attribs) 79 { 80 CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info; 81 GetConsoleScreenBufferInfo(out_handle_, &orig_buffer_info); 82 SetConsoleTextAttribute(out_handle_, attribs); 83 return orig_buffer_info.wAttributes; //return orig attribs 84 } 85 }; 86 87 // 88 // windows color console to stdout 89 // 90 template<class Mutex> 91 class wincolor_stdout_sink: public wincolor_sink<Mutex> 92 { 93 public: wincolor_stdout_sink()94 wincolor_stdout_sink():wincolor_sink(GetStdHandle(STD_OUTPUT_HANDLE)) 95 {} 96 }; 97 98 typedef wincolor_stdout_sink<std::mutex> wincolor_stdout_sink_mt; 99 typedef wincolor_stdout_sink<details::null_mutex> wincolor_stdout_sink_st; 100 101 // 102 // windows color console to stderr 103 // 104 template<class Mutex> 105 class wincolor_stderr_sink: public wincolor_sink<Mutex> 106 { 107 public: wincolor_stderr_sink()108 wincolor_stderr_sink():wincolor_sink(GetStdHandle(STD_ERROR_HANDLE)) 109 {} 110 }; 111 112 typedef wincolor_stderr_sink<std::mutex> wincolor_stderr_sink_mt; 113 typedef wincolor_stderr_sink<details::null_mutex> wincolor_stderr_sink_st; 114 115 } 116 } 117