Belle II Software development
LogConnectionConsole.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <framework/logging/LogConnectionConsole.h>
10#include <framework/logging/LogMessage.h>
11#include <boost/python.hpp>
12#include <boost/algorithm/string.hpp>
13#include <sstream>
14#include <cstring> // strerror()
15#include <unistd.h> // isatty(), dup()
16#include <cstdlib> // getenv()
17
18using namespace Belle2;
19
22
24 m_fd(dup(outputFD)), m_color(color)
25{
26 // check fd
27 if (m_fd < 0) throw std::runtime_error(std::string("Error duplicating file descriptor: ") + std::strerror(errno));
28}
29
31{
32 if (m_fd > 0) close(m_fd);
33}
34
36{
37 return s_pythonLoggingEnabled || m_fd >= 0;
38}
39
41{
42 //enable color for TTYs with color support (list taken from gtest)
43 const bool isTTY = isatty(fileDescriptor);
44 const char* term = getenv("TERM");
45 const std::string termName = term ? term : "";
46 const bool useColor = isTTY and
47 (termName == "xterm" or termName == "xterm-color" or termName == "xterm-256color" or
48 termName == "sceen" or termName == "screen-256color" or termName == "tmux" or
49 termName == "tmux-256color" or termName == "rxvt-unicode" or
50 termName == "rxvt-unicode-256color" or termName == "linux" or termName == "cygwin");
51 return useColor;
52}
53
54void LogConnectionConsole::write(const std::string& message)
55{
57 auto pymessage = boost::python::import("sys").attr("stdout");
58 pymessage.attr("write")(message);
59 pymessage.attr("flush")();
60 } else {
61 ::write(m_fd, message.data(), message.size());
62 }
63}
64
66{
67 if (!isConnected()) return false;
68 // format message
69 std::stringstream stream;
70 if (m_color) {
71 const std::string color_str[] = {
72 "\x1b[32m", // Debug : green
73 "", // Info : terminal default
74 "\x1b[34m", // Result : blue
75 "\x1b[33m", // Warning: yellow
76 "\x1b[31m", // Error : red
77 "\x1b[07m\x1b[31m" // Fatal : red reversed
78 };
79 const std::string& c{color_str[message.getLogLevel()]};
80 stream << c;
81 }
82 stream << message;
83 std::string messagestr = stream.str();
85 // remove trailing whitespace
86 boost::trim_right_if(messagestr, boost::is_any_of(" \t\n\r"));
87 // escape all remaining newlines
88 boost::replace_all(messagestr, "\n", "\\n");
89 // and make sure we end in an actual newline
90 messagestr += "\n";
91 }
92 if (m_color) {
93 messagestr += "\x1b[m";
94 }
95 write(messagestr);
96 return true;
97}
98
100{
101 // If python logging is enabled we need to give jupyter some time to flush
102 // the output as this happens only in the output thread. Seems flushing again is fine :D
104 boost::python::import("sys").attr("stdout").attr("flush")();
105 }
106}
bool m_color
Flag for color output.
static bool getPythonLoggingEnabled()
Check whether console logging via python is enabled.
static bool s_escapeNewlinesEnabled
Flag to indicate whether newlines should be replaced by ' ' in the output.
~LogConnectionConsole() override
Destructor.
LogConnectionConsole(int outputFD, bool color)
Constructor.
static bool terminalSupportsColors(int fileDescriptor)
Returns true if the given file descriptor is a tty and supports colors.
static bool s_pythonLoggingEnabled
Flag to indicate whether log messages should be sent to python sys.stdout.
bool isConnected() override
Returns true if the connection to the io stream could be established.
bool sendMessage(const LogMessage &message) override
Sends a log message.
int m_fd
The output stream used for sending the log message.
void finalizeOnAbort() override
Make sure output is flushed on abort.
void write(const std::string &message)
Send a preformatted string message to the connected output.
The LogMessage class.
Definition: LogMessage.h:29
Abstract base class for different kinds of events.