00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00026 #include "LogFormat.hh"
00027
00028
00029
00030 #include <unistd.h>
00031 #include <locale>
00032 #include <boost/date_time/posix_time/posix_time.hpp>
00033 #include <senf/Scheduler/ClockService.hh>
00034 #include <senf/Utils/Console/ScopedDirectory.hh>
00035 #include <senf/Utils/Console/ParsedCommand.hh>
00036
00037
00038 #define prefix_
00039
00040
00041 prefix_ senf::log::detail::LogFormat::LogFormat()
00042 : tag_ (detail::getDefaultTag()), noformat_ (false), showTime_ (true),
00043 showStream_ (false), showLevel_ (true), showArea_ (true), timeBase_ (-1)
00044 {
00045 timeFormat("%Y-%m-%d %H:%M:%S.%f-0000");
00046 }
00047
00048 prefix_ senf::log::detail::LogFormat::LogFormat(console::ScopedDirectory<> & dir)
00049 : tag_ (detail::getDefaultTag()), noformat_ (false), showTime_ (true),
00050 showStream_ (false), showLevel_ (true), showArea_ (true), timeBase_ (-1)
00051 {
00052 namespace kw = console::kw;
00053 namespace fty = console::factory;
00054
00055 timeFormat("%Y-%m-%d %H:%M:%S.%f-0000");
00056
00057 dir.add("showTime", fty::Command(&LogFormat::showTime, this)
00058 .arg("flag","whether to display the time in log messages",
00059 kw::default_value = true)
00060 .doc("Set time display in log messages. If time display is enabled, see the 'timeFormat'\n"
00061 "command to set the time format.") );
00062 dir.add("showStream", fty::Command(&LogFormat::showStream, this)
00063 .arg("flag","whether to display the stream in log messages",
00064 kw::default_value = true)
00065 .doc("Set stream display in log messages.") );
00066 dir.add("showLevel", fty::Command(&LogFormat::showLevel, this)
00067 .arg("flag","whether to display the log level in log messages",
00068 kw::default_value = true)
00069 .doc("Set log level display in log messages.") );
00070 dir.add("showArea", fty::Command(&LogFormat::showArea, this)
00071 .arg("flag","whether to display the area in log messages",
00072 kw::default_value = true)
00073 .doc("Set area display in log messages.") );
00074 dir.add("timeFormat", fty::Command(&LogFormat::timeFormat, this)
00075 .arg("format","time format")
00076 .doc("Set time format. The time format is specified using a format string. This format\n"
00077 "string follows the strftime format.\n"
00078 "\n"
00079 "As additional option, the format string may be set to the empty string. In this\n"
00080 "case the time will be displayed as 'second.nanosecond' value. IN this case, the\n"
00081 "time is displayed relative to the first message after changing the format.") );
00082 dir.add("tag", fty::Command(&LogFormat::tag, this)
00083 .arg("tag","log message tag prefix")
00084 .doc("Every log message is optionally prefixed with a tag value. This value defaults to\n"
00085 "the executable name and pid.") );
00086 dir.add("format", fty::Command(&LogFormat::consoleFormat, this)
00087 .doc("Show the current log message format.") );
00088 }
00089
00090 prefix_ void senf::log::detail::LogFormat::consoleFormat(std::ostream & os)
00091 {
00092 if (showTime_) os << "showTime ";
00093 if (showStream_) os << "showStream ";
00094 if (showLevel_) os << "showLevel ";
00095 if (showArea_) os << "showArea ";
00096 if (showTime_ || showStream_ || showLevel_ || showArea_) os << "\n";
00097 else os << "(all flags disabled)\n";
00098
00099 os << "timeFormat \"" << timeFormat_ << "\"\n";
00100 os << "tag \"" << tag_ << "\"\n";
00101 }
00102
00103 prefix_ void senf::log::detail::LogFormat::timeFormat(std::string const & format)
00104 {
00105 timeFormat_ = format;
00106 if (format.empty()) {
00107 noformat_ = true;
00108 timeBase_ = ClockService::now();
00109 } else {
00110 noformat_ = false;
00111 std::locale const & loc (datestream_.getloc());
00112 datestream_.imbue( std::locale(
00113 loc, new boost::posix_time::time_facet(format.c_str())) );
00114 }
00115 }
00116
00117 prefix_ std::string senf::log::detail::LogFormat::prefix(time_type timestamp,
00118 std::string const & stream,
00119 std::string const & area,
00120 unsigned level)
00121 {
00122 datestream_.str("");
00123
00124 if (showTime_) {
00125 if (noformat_) {
00126 time_type delta (timestamp - timeBase_);
00127 datestream_ << std::setfill('0') << std::right
00128 << std::setw(10) << (delta / 1000000000ll) << '.'
00129 << std::setw(9) << (delta % 1000000000ll);
00130 }
00131 else
00132 datestream_ << senf::ClockService::abstime(timestamp);
00133 datestream_ << ' ';
00134 }
00135 if (!tag_.empty())
00136 datestream_ << tag_ << ": ";
00137 if (showStream_)
00138 datestream_ << '[' << stream << "] ";
00139 if (showLevel_)
00140 datestream_ << '[' << LEVELNAMES[level] << "] ";
00141 if (showArea_ && area != "senf::log::DefaultArea")
00142 datestream_ << '[' << area << "] ";
00143
00144 return datestream_.str();
00145 }
00146
00147
00148
00149 prefix_ void senf::log::detail::quoteNonPrintable(std::string & s)
00150 {
00151 for (std::string::iterator i (s.begin()); i != s.end(); ++i)
00152 if (*i < ' ' && *i != '\n')
00153 *i = '?';
00154 }
00155
00156 prefix_ std::string senf::log::detail::getDefaultTag()
00157 {
00158 std::stringstream ss;
00159 ss << ::program_invocation_short_name << '[' << ::getpid() << ']';
00160 return ss.str();
00161 }
00162
00163
00164 #undef prefix_
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176