ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

435 lines
11 KiB

  1. //
  2. // Copyright (C) 2009-2012 Artyom Beilis (Tonkikh)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. #ifndef BOOSTER_LOGGER_H
  9. #define BOOSTER_LOGGER_H
  10. #include <booster/config.h>
  11. #include <iosfwd>
  12. #include <booster/auto_ptr_inc.h>
  13. #include <string>
  14. #include <booster/copy_ptr.h>
  15. #include <booster/hold_ptr.h>
  16. #include <booster/noncopyable.h>
  17. /*! \file */
  18. namespace booster {
  19. template<typename T>
  20. class shared_ptr;
  21. template<typename T>
  22. class weak_ptr;
  23. ///
  24. /// \brief This namespace includes Booster.Log related classes
  25. ///
  26. namespace log {
  27. ///
  28. /// This enum defined severity level of logged messages
  29. ///
  30. typedef enum {
  31. emergency = 0,
  32. alert = 10,
  33. critical = 20,
  34. error = 30,
  35. warning = 40,
  36. notice = 50,
  37. info = 60,
  38. debug = 70,
  39. all = 100
  40. } level_type;
  41. ///
  42. /// \brief This class represents a single message that should be written to log
  43. ///
  44. /// Note, it is some generalization of data that allows you to format any generic
  45. /// data, it generally used by logging sinks rather then by end users
  46. ///
  47. class BOOSTER_API message {
  48. public:
  49. ///
  50. /// Create message with severity level \a l, sent from module \a m in file
  51. /// \a name in line \a line
  52. ///
  53. message(level_type l,char const *m,char const *name,int line);
  54. ///
  55. /// Default constructable
  56. ///
  57. message();
  58. ~message();
  59. /// Copy message
  60. message(message &);
  61. /// Assign the message
  62. message &operator=(message &);
  63. ///
  64. /// Get the severity level for the message
  65. ///
  66. level_type level() const;
  67. ///
  68. /// Get the module name
  69. ///
  70. char const *module() const;
  71. ///
  72. /// Get the file name
  73. ///
  74. char const *file_name() const;
  75. ///
  76. /// Get the number of line in the file
  77. ///
  78. int file_line() const;
  79. ///
  80. /// Get the actual message that should be written
  81. ///
  82. std::string log_message() const;
  83. ///
  84. /// Get the output stream that consumes the message
  85. ///
  86. std::ostream &out();
  87. private:
  88. level_type level_;
  89. char const *module_;
  90. char const *file_name_;
  91. int file_line_;
  92. std::auto_ptr<std::ostringstream> message_;
  93. struct data;
  94. copy_ptr<data> d;
  95. };
  96. ///
  97. /// \brief This is the abstract interface to general sink - the consumer
  98. /// of the logged messages
  99. ///
  100. class BOOSTER_API sink : public noncopyable {
  101. public:
  102. ///
  103. /// Send the message \a m to log
  104. ///
  105. /// Note: it does not have to be thread safe - in terms that only
  106. /// one message is sent each time and it is promised that are
  107. /// not sent in parallel
  108. ///
  109. virtual void log(message const &m) = 0;
  110. virtual ~sink() {}
  111. };
  112. ///
  113. /// \brief This is the central class that manages all logging operations.
  114. ///
  115. /// This is singleton, you access it only via instance() static member function.
  116. ///
  117. /// This class is thread safe
  118. ///
  119. class BOOSTER_API logger : public noncopyable {
  120. public:
  121. ///
  122. /// Get the instance of the logger
  123. ///
  124. static logger &instance();
  125. ///
  126. /// Test if the message with severity level \a level of module \a module should
  127. /// be logged. This is generally called before preparing a message in order
  128. /// to prevent logging messages that shouldn't be logged
  129. ///
  130. bool should_be_logged(level_type level,char const *module);
  131. ///
  132. /// Set specific severity level \a level for a module \a module. It would
  133. /// be logged with different logging level then others.
  134. ///
  135. /// Note: \a module string should remain valid all the time this log level
  136. /// is used. It is better to use static strings for these purposes
  137. ///
  138. void set_log_level(level_type level,char const *module);
  139. ///
  140. /// Reset \a module's logging severity to default
  141. ///
  142. void reset_log_level(char const *module);
  143. ///
  144. /// Set default logging level severity
  145. ///
  146. void set_default_level(level_type level);
  147. ///
  148. /// Add new logging sink - the target that receives messages.
  149. /// It is defined by it's pointer.
  150. ///
  151. /// If you plan to remove it, keep the pointer on such logger.
  152. ///
  153. void add_sink(shared_ptr<sink> const &s);
  154. ///
  155. /// Remove a logging sink using its pointer. Note it is enough to keep
  156. /// weak pointer on it allowing the logger to destroy the sink.
  157. ///
  158. void remove_sink(weak_ptr<sink> const &s);
  159. ///
  160. /// Remove all logging sinks from the logger
  161. ///
  162. void remove_all_sinks();
  163. ///
  164. /// Send a message to the log, note, the message is sent regardless of its
  165. /// severity, use should_be_logged before you create the message
  166. ///
  167. void log(message const &);
  168. ///
  169. /// Get convert the severity level to string
  170. ///
  171. static char const *level_to_string(level_type level);
  172. ///
  173. /// Convert string to severity level, if the string is invalid, std::invalid_argument is thrown
  174. ///
  175. static level_type string_to_level(std::string const &);
  176. private:
  177. struct entry {
  178. char const *module;
  179. level_type level;
  180. };
  181. static const int max_entries_size_ = 1024;
  182. level_type default_level_;
  183. entry entries_[max_entries_size_];
  184. int entries_size_;
  185. struct data;
  186. hold_ptr<data> d;
  187. logger();
  188. ~logger();
  189. };
  190. ///
  191. /// \brief This namespace includes various output devices (sinks) for logger.
  192. ///
  193. /// It includes several standard devices that can be used in most applications
  194. ///
  195. namespace sinks {
  196. ///
  197. /// Convert a logging message to a string with all the data that can be
  198. /// written to file, the displayed time is local time
  199. ///
  200. BOOSTER_API std::string format_plain_text_message(message const &msg);
  201. ///
  202. /// Convert a logging message to a string with all the data that can be
  203. /// written to file, the displayed time is GMT+\a timezone_offset.
  204. /// timezone_offset should be represented in seconds, for example
  205. /// for timezone GMT+2:00 it should be 7200
  206. ///
  207. BOOSTER_API std::string format_plain_text_message_tz(message const &msg,int timezone_offset = 0);
  208. ///
  209. /// \brief stderr based sink - sends messages to standard error output
  210. ///
  211. class BOOSTER_API standard_error : public sink {
  212. public:
  213. standard_error();
  214. virtual void log(message const &);
  215. virtual ~standard_error();
  216. private:
  217. struct data;
  218. hold_ptr<data> d;
  219. };
  220. ///
  221. /// \brief log sink for a generic std::ostream
  222. ///
  223. /// \note \a s should be valid as long as the object exists
  224. ///
  225. /// \ver{v1_2}
  226. class BOOSTER_API stream : public sink {
  227. public:
  228. ///
  229. /// Create a new sink, \a s output stream
  230. ///
  231. stream(std::ostream &s);
  232. ///
  233. /// Log the message to the file
  234. ///
  235. virtual void log(message const &msg);
  236. virtual ~stream();
  237. private:
  238. std::ostream *out_;
  239. struct data;
  240. hold_ptr<data> d;
  241. };
  242. ///
  243. /// \brief log file based sink - sends messages to log file
  244. ///
  245. class BOOSTER_API file : public sink {
  246. public:
  247. ///
  248. /// Flag that can be passed to constructor that specifies that
  249. /// the log should be appended to the existing file
  250. ///
  251. /// \ver{v1_2}
  252. static const int app = -1;
  253. ///
  254. /// Creates new object but does not open a file
  255. ///
  256. file();
  257. ///
  258. /// Creates new file sink named \a file_name, if max_files = app,
  259. /// then no new files created but rather the log is appended to the
  260. /// existing file
  261. ///
  262. /// \ver{v1_2}
  263. file(std::string const &file_name,int max_files = 0);
  264. virtual ~file();
  265. ///
  266. /// Open log file
  267. ///
  268. void open(std::string file_name);
  269. ///
  270. /// Enable file rotation and set the maximal number of files that should be kept.
  271. ///
  272. /// Each time the log opened, the old files are renamed, if there are more files
  273. /// then \a limit, the oldest is removed
  274. ///
  275. void max_files(unsigned limit);
  276. ///
  277. /// Append to output file rather then create new one.
  278. ///
  279. void append();
  280. ///
  281. /// Set the time-zone name that should be used in the message.
  282. ///
  283. /// It should have a format GMT+XX:YY like "GMT+2:00" or "GMT-3".
  284. /// "GMT" can be used as well
  285. ///
  286. /// If name is empty local time is used which is the default
  287. ///
  288. void set_timezone(std::string const &name);
  289. /// Send message to the log
  290. virtual void log(message const &);
  291. private:
  292. void shift(std::string const &base);
  293. std::string format_file(std::string const &,int);
  294. unsigned max_files_;
  295. BOOSTER_UNUSED_MEMBER size_t max_size_;
  296. BOOSTER_UNUSED_MEMBER size_t current_size_;
  297. bool opened_;
  298. bool append_;
  299. bool use_local_time_;
  300. int tz_offset_;
  301. struct data;
  302. hold_ptr<data> d;
  303. };
  304. #ifdef BOOSTER_POSIX
  305. ///
  306. /// \brief POSIX syslog sink
  307. ///
  308. /// Available only on POSIX platforms
  309. ///
  310. class BOOSTER_API syslog : public sink {
  311. public:
  312. ///
  313. /// Create a new logger. Note: it does not call openlog, if you want
  314. /// to provide non-default parameters, you need to call it on your own
  315. ///
  316. syslog();
  317. ///
  318. /// Create a new logger and call openlog with id, opts and facility
  319. ///
  320. syslog(std::string const &id,int opts,int facility = 0);
  321. ///
  322. /// Create a new logger and call openlog with NULL id , opts and facility
  323. ///
  324. syslog(int opts,int facility = 0);
  325. ///
  326. /// Send the message to the log
  327. ///
  328. virtual void log(message const &);
  329. virtual ~syslog();
  330. private:
  331. struct data;
  332. hold_ptr<data> d;
  333. };
  334. #endif
  335. } // sinks
  336. ///
  337. /// \def BOOSTER_LOG(level,module)
  338. ///
  339. /// \brief Log a message with severity \a level of the \a module to the log device if applicable.
  340. ///
  341. /// Notes:
  342. ///
  343. /// - it first checks of the message should be logged at all, and if not, all the rest is not called
  344. /// - the message is logged in the destruction of the output stream object
  345. /// - the parameter \a level should be given as is "warning" or "debug" the namespace flags would
  346. /// be added withing macro
  347. /// - It may be more convenient to use BOOSTER_WARNING or BOOSTER_DEBUG macros
  348. ///
  349. /// Example:
  350. ///
  351. /// \code
  352. /// BOOSTER_LOG(warning,"file_system") << "Failed to open file name " << name;
  353. /// BOOSTER_CRITICAL("core") << "Failed to allocate memory";
  354. /// \endcode
  355. ///
  356. #define BOOSTER_LOG(level,module) \
  357. ::booster::log::logger::instance().should_be_logged(::booster::log::level,module) \
  358. && ::booster::log::message(::booster::log::level,module,__FILE__,__LINE__).out()
  359. /// Same as BOOSTER_LOG(emergency,m)
  360. #define BOOSTER_EMERG(m) BOOSTER_LOG(emergency,m)
  361. /// Same as BOOSTER_LOG(alert,m)
  362. #define BOOSTER_ALERT(m) BOOSTER_LOG(alert,m)
  363. /// Same as BOOSTER_LOG(critical,m)
  364. #define BOOSTER_CRITICAL(m) BOOSTER_LOG(critical,m)
  365. /// Same as BOOSTER_LOG(error,m)
  366. #define BOOSTER_ERROR(m) BOOSTER_LOG(error,m)
  367. /// Same as BOOSTER_LOG(warning,m)
  368. #define BOOSTER_WARNING(m) BOOSTER_LOG(warning,m)
  369. /// Same as BOOSTER_LOG(notice,m)
  370. #define BOOSTER_NOTICE(m) BOOSTER_LOG(notice,m)
  371. /// Same as BOOSTER_LOG(info,m)
  372. #define BOOSTER_INFO(m) BOOSTER_LOG(info,m)
  373. /// Same as BOOSTER_LOG(debug,m)
  374. #define BOOSTER_DEBUG(m) BOOSTER_LOG(debug,m)
  375. } // log
  376. } // booster
  377. #endif