diff --git a/base/common/CMakeLists.txt b/base/common/CMakeLists.txt index cce3a28e582..1c3e194a54c 100644 --- a/base/common/CMakeLists.txt +++ b/base/common/CMakeLists.txt @@ -16,6 +16,7 @@ set (SRCS setTerminalEcho.cpp shift10.cpp sleep.cpp + terminalColors.cpp ) if (ENABLE_REPLXX) diff --git a/base/common/terminalColors.cpp b/base/common/terminalColors.cpp new file mode 100644 index 00000000000..af1f02d331f --- /dev/null +++ b/base/common/terminalColors.cpp @@ -0,0 +1,49 @@ +#include +#include + + +std::string setColor(UInt64 hash) +{ + /// Make a random RGB color that has constant brightness. + /// https://en.wikipedia.org/wiki/YCbCr + + /// Note that this is darker than the middle relative luminance, see "Gamma_correction" and "Luma_(video)". + /// It still looks awesome. + UInt8 y = 128; + + UInt8 cb = hash % 256; + UInt8 cr = hash / 256 % 256; + + UInt8 r = std::max(0.0, std::min(255.0, y + 1.402 * (cr - 128))); + UInt8 g = std::max(0.0, std::min(255.0, y - 0.344136 * (cb - 128) - 0.714136 * (cr - 128))); + UInt8 b = std::max(0.0, std::min(255.0, y + 1.772 * (cb - 128))); + + /// ANSI escape sequence to set 24-bit foreground font color in terminal. + return "\033[38;2;" + std::to_string(r) + ";" + std::to_string(g) + ";" + std::to_string(b) + "m"; +} + +const char * setColorForLogPriority(int priority) +{ + if (priority < 1 || priority > 8) + return ""; + + static const char * colors[] = + { + "", + "\033[1;41m", /// Fatal + "\033[7;31m", /// Critical + "\033[1;31m", /// Error + "\033[0;31m", /// Warning + "\033[0;33m", /// Notice + "\033[1m", /// Information + "", /// Debug + "\033[2m", /// Trace + }; + + return colors[priority]; +} + +const char * resetColor() +{ + return "\033[0m"; +} diff --git a/base/common/terminalColors.h b/base/common/terminalColors.h new file mode 100644 index 00000000000..0c33b23752b --- /dev/null +++ b/base/common/terminalColors.h @@ -0,0 +1,15 @@ +#include +#include + + +/** Set color in terminal based on 64-bit hash value. + * It can be used to choose some random color deterministically based on some other value. + * Hash value should be uniformly distributed. + */ +std::string setColor(UInt64 hash); + +/** Set color for logger priority value. */ +const char * setColorForLogPriority(int priority); + +/** Undo changes made by the functions above. */ +const char * resetColor(); diff --git a/base/loggers/loggers/OwnPatternFormatter.cpp b/base/loggers/loggers/OwnPatternFormatter.cpp index bd6a2b2d3e9..1f918f01697 100644 --- a/base/loggers/loggers/OwnPatternFormatter.cpp +++ b/base/loggers/loggers/OwnPatternFormatter.cpp @@ -9,57 +9,10 @@ #include #include #include +#include #include "Loggers.h" -static std::string setColor(UInt64 num) -{ - /// Make a random RGB color that has constant brightness. - /// https://en.wikipedia.org/wiki/YCbCr - - /// Note that this is darker than the middle relative luminance, see "Gamma_correction" and "Luma_(video)". - /// It still looks awesome. - UInt8 y = 128; - - UInt8 cb = num % 256; - UInt8 cr = num / 256 % 256; - - UInt8 r = std::max(0.0, std::min(255.0, y + 1.402 * (cr - 128))); - UInt8 g = std::max(0.0, std::min(255.0, y - 0.344136 * (cb - 128) - 0.714136 * (cr - 128))); - UInt8 b = std::max(0.0, std::min(255.0, y + 1.772 * (cb - 128))); - - /// ANSI escape sequence to set 24-bit foreground font color in terminal. - return "\033[38;2;" + DB::toString(r) + ";" + DB::toString(g) + ";" + DB::toString(b) + "m"; -} - -static const char * setColorForLogPriority(int priority) -{ - if (priority < 1 || priority > 8) - return ""; - - static const char * colors[] = - { - "", - "\033[1;41m", /// Fatal - "\033[7;31m", /// Critical - "\033[1;31m", /// Error - "\033[0;31m", /// Warning - "\033[0;33m", /// Notice - "\033[1m", /// Information - "", /// Debug - "\033[2m", /// Trace - }; - - return colors[priority]; -} - -static const char * resetColor() -{ - return "\033[0m"; -} - - - OwnPatternFormatter::OwnPatternFormatter(const Loggers * loggers_, OwnPatternFormatter::Options options_, bool color_) : Poco::PatternFormatter(""), loggers(loggers_), options(options_), color(color_) { diff --git a/dbms/programs/client/Client.cpp b/dbms/programs/client/Client.cpp index 6b240bf0c7e..7236fcdb6b2 100644 --- a/dbms/programs/client/Client.cpp +++ b/dbms/programs/client/Client.cpp @@ -130,7 +130,8 @@ private: bool echo_queries = false; /// Print queries before execution in batch mode. bool ignore_error = false; /// In case of errors, don't print error message, continue to next query. Only applicable for non-interactive mode. bool print_time_to_stderr = false; /// Output execution time to stderr in batch mode. - bool stdin_is_not_tty = false; /// stdin is not a terminal. + bool stdin_is_a_tty = false; /// stdin is a terminal. + bool stdout_is_a_tty = false; /// stdout is a terminal. uint16_t terminal_width = 0; /// Terminal width is needed to render progress bar. @@ -378,7 +379,7 @@ private: /// The value of the option is used as the text of query (or of multiple queries). /// If stdin is not a terminal, INSERT data for the first query is read from it. /// - stdin is not a terminal. In this case queries are read from it. - if (stdin_is_not_tty || config().has("query")) + if (!stdin_is_a_tty || config().has("query")) is_interactive = false; std::cout << std::fixed << std::setprecision(3); @@ -910,7 +911,7 @@ private: ? query.substr(0, parsed_insert_query.data - query.data()) : query; - if (!parsed_insert_query.data && (is_interactive || (stdin_is_not_tty && std_in.eof()))) + if (!parsed_insert_query.data && (is_interactive || (!stdin_is_a_tty && std_in.eof()))) throw Exception("No data to insert", ErrorCodes::NO_DATA_TO_INSERT); connection->sendQuery(connection_parameters.timeouts, query_without_data, query_id, QueryProcessingStage::Complete, &context.getSettingsRef(), nullptr, true); @@ -1332,7 +1333,7 @@ private: } } - logs_out_stream = std::make_shared(*wb); + logs_out_stream = std::make_shared(*wb, stdout_is_a_tty); logs_out_stream->writePrefix(); } } @@ -1643,9 +1644,10 @@ public: } } - stdin_is_not_tty = !isatty(STDIN_FILENO); + stdin_is_a_tty = isatty(STDIN_FILENO); + stdout_is_a_tty = isatty(STDOUT_FILENO); - if (!stdin_is_not_tty) + if (stdin_is_a_tty) terminal_width = getTerminalWidth(); namespace po = boost::program_options; diff --git a/dbms/src/DataStreams/InternalTextLogsRowOutputStream.cpp b/dbms/src/DataStreams/InternalTextLogsRowOutputStream.cpp index 9e33d2ecd94..270497ab814 100644 --- a/dbms/src/DataStreams/InternalTextLogsRowOutputStream.cpp +++ b/dbms/src/DataStreams/InternalTextLogsRowOutputStream.cpp @@ -2,10 +2,12 @@ #include #include #include +#include #include #include #include #include +#include namespace DB @@ -35,7 +37,11 @@ void InternalTextLogsRowOutputStream::write(const Block & block) if (host_name.size) { writeCString("[", wb); + if (color) + writeString(setColor(StringRefHash()(host_name)), wb); writeString(host_name, wb); + if (color) + writeCString(resetColor(), wb); writeCString("] ", wb); } @@ -51,21 +57,34 @@ void InternalTextLogsRowOutputStream::write(const Block & block) writeChar('0' + ((microseconds / 10) % 10), wb); writeChar('0' + ((microseconds / 1) % 10), wb); + UInt64 thread_id = array_thread_id[row_num]; + writeCString(" [ ", wb); + if (color) + writeString(setColor(intHash64(thread_id)), wb); + writeIntText(thread_id, wb); + if (color) + writeCString(resetColor(), wb); + writeCString(" ]", wb); + auto query_id = column_query_id.getDataAt(row_num); if (query_id.size) { writeCString(" {", wb); + if (color) + writeString(setColor(StringRefHash()(query_id)), wb); writeString(query_id, wb); + if (color) + writeCString(resetColor(), wb); writeCString("}", wb); } - UInt64 thread_id = array_thread_id[row_num]; - writeCString(" [ ", wb); - writeIntText(thread_id, wb); - writeCString(" ] <", wb); - Int8 priority = array_priority[row_num]; + writeCString(" <", wb); + if (color) + writeCString(setColorForLogPriority(priority), wb); writeString(InternalTextLogsQueue::getPriorityName(priority), wb); + if (color) + writeCString(resetColor(), wb); writeCString("> ", wb); auto source = column_source.getDataAt(row_num); diff --git a/dbms/src/DataStreams/InternalTextLogsRowOutputStream.h b/dbms/src/DataStreams/InternalTextLogsRowOutputStream.h index 3f54a00e633..0f333f70d18 100644 --- a/dbms/src/DataStreams/InternalTextLogsRowOutputStream.h +++ b/dbms/src/DataStreams/InternalTextLogsRowOutputStream.h @@ -12,8 +12,7 @@ namespace DB class InternalTextLogsRowOutputStream : public IBlockOutputStream { public: - - InternalTextLogsRowOutputStream(WriteBuffer & buf_out) : wb(buf_out) {} + InternalTextLogsRowOutputStream(WriteBuffer & buf_out, bool color_) : wb(buf_out), color(color_) {} Block getHeader() const override; @@ -25,8 +24,8 @@ public: } private: - WriteBuffer & wb; + bool color; }; }