28 #include <boost/assign.hpp> 29 #include <boost/bind.hpp> 30 #include <boost/date_time.hpp> 31 #include <boost/foreach.hpp> 33 #include "goby/common/logger/flex_ostreambuf.h" 36 #include "flex_ncurses.h" 38 #include "flex_ostream.h" 40 #include "goby/common/exception.h" 41 #include "goby/common/time.h" 42 #include "goby/util/sci.h" 43 #include "logger_manipulators.h" 48 boost::mutex curses_mutex;
51 boost::recursive_mutex goby::common::logger::mutex;
53 goby::common::FlexOStreamBuf::FlexOStreamBuf(FlexOstream* parent)
54 : buffer_(1), name_(
"no name"), die_flag_(false), current_verbosity_(logger::UNKNOWN),
58 start_time_(
goby_time()), is_gui_(false), highest_verbosity_(logger::QUIET), parent_(parent)
61 Group no_group(
"",
"Ungrouped messages");
62 groups_[
""] = no_group;
65 goby::common::FlexOStreamBuf::~FlexOStreamBuf()
77 bool stream_exists =
false;
78 BOOST_FOREACH (StreamConfig& sc, streams_)
82 sc.set_verbosity(verbosity);
88 streams_.push_back(StreamConfig(os, verbosity));
90 highest_verbosity_ = logger::QUIET;
91 for (std::vector<StreamConfig>::const_iterator it = streams_.begin(), end = streams_.end();
94 if (it->verbosity() > highest_verbosity_)
95 highest_verbosity_ = it->verbosity();
99 void goby::common::FlexOStreamBuf::enable_gui()
106 boost::mutex::scoped_lock lock(curses_mutex);
111 typedef std::pair<std::string, Group> P;
112 BOOST_FOREACH (
const P& p, groups_)
113 curses_->add_win(&groups_[p.first]);
115 curses_->recalculate_win();
117 input_thread_ = boost::shared_ptr<boost::thread>(
120 throw(
goby::Exception(
"Tried to enable NCurses GUI without compiling against NCurses. Install " 121 "NCurses and recompile goby or disable GUI functionality"));
134 boost::mutex::scoped_lock lock(curses_mutex);
135 curses_->add_win(&groups_[name]);
142 parent_->set_unset_verbosity();
147 buffer_.push_back(std::string());
149 buffer_.back().push_back(c);
157 if (current_verbosity_ == logger::UNKNOWN && lock_action_ == logger_lock::lock)
160 <<
"== Misuse of goby::glog in threaded mode: must use 'goby.is(...) && glog' syntax" 162 std::cerr <<
"== Offending line: " << buffer_.front() << std::endl;
163 assert(!(lock_action_ == logger_lock::lock && current_verbosity_ == logger::UNKNOWN));
168 while (buffer_.size() > 1)
170 display(buffer_.front());
176 current_verbosity_ = logger::UNKNOWN;
181 if (lock_action_ == logger_lock::lock)
183 logger::mutex.unlock();
189 void goby::common::FlexOStreamBuf::display(std::string& s)
191 bool gui_displayed =
false;
192 BOOST_FOREACH (
const StreamConfig& cfg, streams_)
194 if ((cfg.os() == &std::cout || cfg.os() == &std::cerr || cfg.os() == &std::clog) &&
195 current_verbosity_ <= cfg.verbosity())
198 if (is_gui_ && current_verbosity_ <= cfg.verbosity() && !gui_displayed)
202 boost::mutex::scoped_lock lock(curses_mutex);
203 std::stringstream line;
204 boost::posix_time::time_duration time_of_day =
goby_time().time_of_day();
206 << std::setfill(
'0') << std::setw(2) << time_of_day.hours() <<
":" 207 << std::setw(2) << time_of_day.minutes() <<
":" << std::setw(2)
208 << time_of_day.seconds()
212 curses_->insert(
goby_time(), line.str(), &groups_[group_name_]);
216 curses_->alive(
false);
217 input_thread_->join();
220 << esc_nocolor <<
": " << s << esc_nocolor << std::endl;
222 gui_displayed =
true;
229 if (!group_name_.empty())
231 <<
"{" << group_name_ <<
"}";
232 *cfg.os() <<
": " << s << std::endl;
234 else if (cfg.os() && current_verbosity_ <= cfg.verbosity())
236 basic_log_header(*cfg.os(), group_name_);
238 *cfg.os() << s << std::endl;
248 boost::mutex::scoped_lock lock(curses_mutex);
249 curses_->recalculate_win();
255 void goby::common::FlexOStreamBuf::strip_escapes(std::string& s)
257 static const std::string esc =
"\33[";
258 static const std::string m =
"m";
260 size_t esc_pos, m_pos;
261 while ((esc_pos = s.find(esc)) != std::string::npos &&
262 (m_pos = s.find(m, esc_pos)) != std::string::npos)
263 s.erase(esc_pos, m_pos - esc_pos + 1);
void refresh()
refresh the display (does nothing if !is_gui())
void add_group(const std::string &name, Group g)
add a new group
int sync()
virtual inherited from std::streambuf. Called when std::endl or std::flush is inserted into the strea...
void startup()
start the display
std::string goby_time_as_string(const boost::posix_time::ptime &t=goby_time())
Simple string representation of goby_time()
void add_stream(logger::Verbosity verbosity, std::ostream *os)
add a stream to the logger
ReturnType goby_time()
Returns current UTC time as a boost::posix_time::ptime.
void run_input()
run in its own thread to take input from the user
int overflow(int c=EOF)
virtual inherited from std::streambuf. Called when something is inserted into the stream ...
Enables the Verbosity == gui mode of the Goby logger and displays an NCurses gui for the logger conte...
void cleanup()
end the display
simple exception class for goby applications
static std::string esc_code_from_col(const Colors::Color &c)
Escape code from color enumeration (e.g. red -> "\33[31m")
Defines a group of messages to be sent to the Goby logger. For Verbosity == verbose streams...