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