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.
 
 
 
 
 
 

228 lines
5.8 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU Lesser General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU Lesser General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Lesser General Public License
  16. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #define CPPCMS_SOURCE
  20. #include "logger.h"
  21. #include "cppcms_error.h"
  22. #include "config.h"
  23. #ifdef CPPCMS_USE_EXTERNAL_BOOST
  24. # include <boost/format.hpp>
  25. # include <boost/shared_ptr.hpp>
  26. #else // Internal Boost
  27. # include <cppcms_boost/format.hpp>
  28. # include <cppcms_boost/shared_ptr.hpp>
  29. namespace boost = cppcms_boost;
  30. #endif
  31. #include <booster/thread.h>
  32. #include <sstream>
  33. #include <fstream>
  34. namespace cppcms {
  35. namespace impl {
  36. class log_device : public booster::noncopyable {
  37. public:
  38. virtual void write(std::string const &msg) = 0;
  39. virtual ~log_device() {}
  40. };
  41. class file_log_device : public log_device {
  42. public:
  43. file_log_device(std::string const &file_name,logger::open_mode_type how)
  44. {
  45. switch(how) {
  46. case logger::overwrite:
  47. output_.open(file_name.c_str());
  48. break;
  49. case logger::append:
  50. default:
  51. output_.open(file_name.c_str(),std::fstream::app);
  52. }
  53. if(!output_)
  54. throw cppcms_error("Failed to open log file:" + file_name);
  55. }
  56. virtual void write(std::string const &msg)
  57. {
  58. output_ << msg <<std::endl;
  59. }
  60. private:
  61. std::ofstream output_;
  62. };
  63. class stream_log_device : public log_device {
  64. public:
  65. stream_log_device(std::ostream &out) : output_(out)
  66. {
  67. }
  68. virtual void write(std::string const &msg)
  69. {
  70. output_ << msg <<std::endl;
  71. }
  72. private:
  73. std::ostream &output_;
  74. };
  75. } /// impl
  76. struct logger::data {
  77. boost::shared_mutex lock;
  78. logger::level_type global_level;
  79. bool empty_map;
  80. typedef std::map<std::string,logger::level_type> module_level_type;
  81. module_level_type module_level;
  82. std::auto_ptr<std::fstream> output;
  83. std::vector<boost::shared_ptr<impl::log_device> > devices;
  84. };
  85. logger::level_type logger::module_level(char const *module)
  86. {
  87. if(d->empty_map) {
  88. return d->global_level;
  89. }
  90. else {
  91. boost::shared_lock<boost::shared_mutex> guard(d->lock);
  92. data::module_level_type::const_iterator p;
  93. if((p=d->module_level.find(module)) != d->module_level.end())
  94. return p->second;
  95. return d->global_level;
  96. }
  97. }
  98. void logger::module_level(char const *module,level_type l)
  99. {
  100. boost::shared_lock<boost::shared_mutex> guard(d->lock);
  101. d->module_level[module] = l;
  102. d->empty_map = false;
  103. }
  104. void logger::reset_module_level(char const *module)
  105. {
  106. boost::shared_lock<boost::shared_mutex> guard(d->lock);
  107. d->module_level.erase(module);
  108. d->empty_map = d->module_level.empty();
  109. }
  110. bool logger::level(level_type l,char const *module)
  111. {
  112. return l <= module_level(module);
  113. }
  114. void logger::default_level(level_type l)
  115. {
  116. d->global_level = l;
  117. }
  118. logger::level_type logger::default_level()
  119. {
  120. return d->global_level;
  121. }
  122. logger::ostream_proxy logger::proxy(level_type l,char const *module,char const *file,int line)
  123. {
  124. ostream_proxy proxy(l,module,file,line,this);
  125. return proxy;
  126. }
  127. logger &logger::instance()
  128. {
  129. static std::auto_ptr<logger> instance_ptr;
  130. static boost::once_flag flag;
  131. boost::call_once(flag,boost::bind(init,boost::ref(instance_ptr)));
  132. }
  133. void logger::init(std::auto_ptr<logger> &logger_ref)
  134. {
  135. logger_ref.reset(new logger());
  136. }
  137. logger::ostream_proxy::ostream_proxy() :
  138. level_(all),
  139. line_(0),
  140. file_(""),
  141. module_(""),
  142. log_(&logger::instance()),
  143. output_(new std::ostringstream)
  144. {
  145. }
  146. logger::ostream_proxy::ostream_proxy(level_type lv,char const *m,char const *f,int line,logger *log) :
  147. level_(lv),
  148. line_(line),
  149. file_(f),
  150. module_(m),
  151. log_(log),
  152. output_(new std::ostringstream)
  153. {
  154. }
  155. logger::ostream_proxy::ostream_proxy(logger::ostream_proxy &other) :
  156. level_(other.level_),
  157. line_(other.line_),
  158. file_(other.file_),
  159. module_(other.module_),
  160. log_(other.log_)
  161. {
  162. output_ = other.output_;
  163. }
  164. logger::ostream_proxy &logger::ostream_proxy::operator=(logger::ostream_proxy &other)
  165. {
  166. if(&other!=this) {
  167. level_ = other.level_;
  168. line_ = other.line_;
  169. file_ = other.file_;
  170. module_ = other.module_;
  171. log_ = other.log_;
  172. output_ = other.output_;
  173. }
  174. return *this;
  175. }
  176. std::ostream &logger::ostream_proxy::out()
  177. {
  178. return *output_;
  179. }
  180. logger::ostream_proxy::~ostream_proxy()
  181. {
  182. try {
  183. log_->write_to_log(level_,module_,file_,line_,output_->str());
  184. }
  185. catch(...)
  186. {
  187. }
  188. }
  189. void logger::write_to_log(level_type l,char const *module,char const *file,int line,std::string const &msg)
  190. {
  191. switch(l) {
  192. case fatal: level = "fatal"; break;
  193. case critical: level = "critical"; break;
  194. case error: level = "error"; break;
  195. case warning: level = "warning"; break;
  196. case message: level = "message"; break;
  197. case info: level = "info"; break;
  198. case debug: level = "debug"; break;
  199. default:
  200. level="unknown";
  201. }
  202. std::string result = (boost::format("%1%, %2%:%3% %4%:%5%")
  203. <<module << file << line << level << msg).str();
  204. for(unsigned i=0;i<d->devices.size();i++)
  205. d->devices[i]->write(result);
  206. }
  207. } // cppcms