mod_servlet
C++Servlets
 All Classes Files Functions Variables Typedefs Macros Pages
logger.h
Go to the documentation of this file.
1 /*
2 Copyright (c) 2016 Alexei Novakov
3 https://github.com/novalexei
4 
5 Distributed under the Boost Software License, Version 1.0.
6 http://boost.org/LICENSE_1_0.txt
7 */
8 #ifndef SERVLET_LOGGER_H
9 #define SERVLET_LOGGER_H
10 
16 #include <experimental/string_view>
17 #include <atomic>
18 #include <string>
19 #include <memory>
20 #include <map>
21 #include <mutex>
22 #include <thread>
23 #include <iomanip>
24 #include <vector>
25 
26 #include <servlet/lib/io_string.h>
27 
28 namespace servlet {
29 
30 using std::experimental::string_view;
31 
32 namespace logging {
33 
38 {
39 public:
40  virtual ~log_output() noexcept {}
41 
47  virtual void write_string(string_view str) = 0;
51  virtual void flush() = 0;
52 
69  virtual void load_config(std::map<std::string, std::string, std::less<>>& props,
70  const std::string& conf_prefix, const std::string &base_dir) = 0;
71 };
72 
77 {
78  virtual ~log_output_factory() noexcept {}
83  virtual log_output* new_log_output() = 0;
84 };
85 
89 enum class SYNC_POLICY
90 {
95  SINGLE_THREAD,
103  SYNC,
113  ASYNC
114 };
115 
119 enum class LEVEL
120 {
124  CRITICAL,
128  ERROR,
132  WARNING,
136  INFO,
140  CONFIG,
144  DEBUG,
148  TRACE
149 };
150 
159 {
160 public:
161  virtual ~prefix_printer() noexcept {}
162 
169  virtual void print_prefix(LEVEL level, const std::string &name, std::ostream &out) const = 0;
182  virtual void load_config(std::map<std::string, std::string, std::less<>>& props, const std::string& conf_prefix) = 0;
183 };
184 
189 {
190  virtual ~prefix_printer_factory() noexcept {}
195  virtual prefix_printer* new_prefix_printer() = 0;
196 };
197 
198 class logger;
199 
231 {
232 public:
233  ~level_logger() noexcept;
234 
243  template<typename T>
244  inline level_logger &operator<<(const T &value);
245 
251  level_logger &operator<<(std::ostream &(*manip)(std::ostream &));
252 
259  level_logger &operator<<(char ch);
266  level_logger &operator<<(char16_t ch);
276  level_logger &operator<<(const char16_t* str);
286  level_logger &operator<<(const std::u16string& str);
293  level_logger &operator<<(char32_t ch);
303  level_logger &operator<<(const char32_t* str);
313  level_logger &operator<<(const std::u32string& str);
320  level_logger &operator<<(wchar_t ch);
330  level_logger &operator<<(const wchar_t* str);
340  level_logger &operator<<(const std::wstring& str);
341 
346  level_logger &flush() { _out->flush(); return *this; }
347 
354  level_logger &put(char ch) { return (*this) << ch; }
361  level_logger &put(char16_t ch) { return (*this) << ch; }
368  level_logger &put(char32_t ch) { return (*this) << ch; }
375  level_logger &put(wchar_t ch) { return (*this) << ch; }
376 
384  level_logger &write (const char* s, std::streamsize n);
385 private:
386  friend class logger;
387  level_logger(LEVEL level, logger &log) : _log_level{level}, _logger{log} {}
388 
389  LEVEL _log_level;
390  logger &_logger;
391  inplace_ostream *_out = nullptr;
392 };
393 
394 class locked_stream
395 {
396 public:
397  virtual ~locked_stream() noexcept {}
398 
399  virtual inplace_ostream *get_buffer(const std::locale& loc) = 0;
400  virtual void return_buffer(inplace_ostream *buf) = 0;
401 };
402 
403 class log_registry;
404 
425 class logger
426 {
427 public:
428  ~logger() noexcept = default;
429 
434  const std::string& name() const { return _name; }
435 
440  level_logger critical() { return level_logger{LEVEL::CRITICAL, *this}; }
445  level_logger error() { return level_logger{LEVEL::ERROR, *this}; }
450  level_logger warning() { return level_logger{LEVEL::WARNING, *this}; }
455  level_logger info() { return level_logger{LEVEL::INFO, *this}; }
460  level_logger config() { return level_logger{LEVEL::CONFIG, *this}; }
465  level_logger debug() { return level_logger{LEVEL::DEBUG, *this}; }
470  level_logger trace() { return level_logger{LEVEL::TRACE, *this}; }
471 
476  level_logger log(LEVEL level) { return level_logger{level, *this}; }
483  bool is_loggable(LEVEL level) const { return level <= _log_level.load(); }
484 
491  void set_log_level(LEVEL log_level) { _log_level = log_level; }
496  void set_prefix_printer(std::shared_ptr<prefix_printer> new_pp) { std::atomic_store(&_formatter, new_pp); }
502  void set_log_output(log_output* new_out, SYNC_POLICY policy = SYNC_POLICY::SYNC);
503 
511  void imbue(const std::locale& loc) { _loc = loc; }
512 
513 private:
514  friend class level_logger;
515  friend class log_registry;
516 
517  logger(std::shared_ptr<prefix_printer> pref, std::shared_ptr<locked_stream> lock_stream,
518  LEVEL log_level, std::string name, const std::locale& loc) :
519  _formatter{pref}, _lock_stream{lock_stream}, _name{std::move(name)}, _log_level{log_level}, _loc{loc} {}
520 
521  void set_locked_stream(std::shared_ptr<locked_stream> lock_stream)
522  { std::atomic_store(&_lock_stream, lock_stream); }
523 
524  std::shared_ptr<prefix_printer> _formatter;
525  std::shared_ptr<locked_stream> _lock_stream;
526 
527  std::atomic<LEVEL> _log_level;
528  const std::string _name;
529  std::locale _loc;
530 };
531 
624 {
625 public:
629  static constexpr std::size_t DEFAULT_FILE_ROTATION_SIZE = 1024*1024*16;
634  static constexpr std::size_t DEFAULT_ASYNC_QUEUE_SIZE = 1024;
635 
639  typedef std::map<std::string, std::string, std::less<>> properties_type;
640 
644  log_registry();
645 
652  std::shared_ptr<logger> log(const std::string& name = "root");
653 
661  void read_configuration(const std::string& config_file_name,
662  const std::string& base_dir, bool update_loggers = true);
671  void read_configuration(properties_type props, const std::string& base_dir, bool update_loggers = true);
672 
679  LEVEL get_log_level(const std::string& name);
684  void set_log_level(LEVEL level) { _log_level = level; }
685 
694  void imbue(const std::locale& loc) { _loc = loc; }
695 
701  void set_base_directory(const std::string& base_dir);
707  void set_base_directory(std::string&& base_dir);
708 
713  SYNC_POLICY get_synchronization_policy() const { return _sync_policy; }
720  void set_synchronization_policy(SYNC_POLICY sync_policy);
721 
727  { std::atomic_store(&_prefix_printer, std::shared_ptr<prefix_printer>(pp)); }
728 
733  void set_log_output(log_output *log_out);
734 
744  void reset_loggers_config(bool update_prefix_printer, bool update_log_output, bool update_locale);
745 
746 protected:
765  void add_prefix_printer_factory(const std::string& name, prefix_printer_factory* fac)
766  { _prefix_printer_factories.emplace(name, fac); }
785  void add_log_output_factory(const std::string& name, log_output_factory* fac)
786  { _log_output_factories.emplace(name, fac); }
787 
788 private:
789  logger* create_new_logger(std::string name);
790  std::shared_ptr<log_output> get_or_create_output(bool force_create = false);
791  std::shared_ptr<prefix_printer> get_or_create_prefix_printer(bool force_create = false);
792  std::shared_ptr<locked_stream> get_or_create_locked_stream(bool force_create = false);
793 
794  std::map<std::string, std::shared_ptr<logger>, std::less<>> _loggers;
795 
796  std::locale _loc;
797  std::string _base_dir;
798  properties_type _properties;
799 
800  std::atomic<LEVEL> _log_level{LEVEL::WARNING};
801  std::atomic<SYNC_POLICY> _sync_policy{SYNC_POLICY::SYNC};
802 
803  std::shared_ptr<log_output> _log_out;
804  std::shared_ptr<locked_stream> _locked_stream;
805  std::shared_ptr<prefix_printer> _prefix_printer;
806  std::recursive_mutex _config_mx;
807 
808  std::map<std::string, std::unique_ptr<prefix_printer_factory>, std::less<>> _prefix_printer_factories;
809  std::map<std::string, std::unique_ptr<log_output_factory>, std::less<>> _log_output_factories;
810 };
811 
815 extern thread_local std::shared_ptr<log_registry> THREAD_REGISTRY;
816 
821 log_registry& registry();
827 void load_config(const char* cfg_file_name, const std::string& base_dir = "");
828 
835 inline std::shared_ptr<logger> get_logger(const std::string& name) { return registry().log(name); }
841 inline std::shared_ptr<logger> get_logger() { return registry().log(); }
842 
858 std::shared_ptr<logger> get_class_logger(log_registry& registry, const char * class_name);
859 
867 inline std::shared_ptr<logger> get_class_logger(const char * class_name)
868 { return get_class_logger(registry(), class_name); }
869 
870 /* Necessary implementations */
871 
872 inline level_logger::~level_logger() noexcept { if (_out) _logger._lock_stream->return_buffer(_out); }
873 
874 template<typename T>
876 {
877  if (!_logger.is_loggable(_log_level)) return *this;
878  if (!_out)
879  {
880  _out = _logger._lock_stream->get_buffer(_logger._loc);
881  _logger._formatter->print_prefix(_log_level, _logger._name, *_out);
882  }
883  else if ((*_out)->view().empty()) _logger._formatter->print_prefix(_log_level, _logger._name, *_out);
884  (*_out) << value;
885  if ((*_out)->view().back() == '\n')
886  {
887  _logger._lock_stream->return_buffer(_out);
888  _out = nullptr;
889  }
890  return *this;
891 }
892 
893 } // end of servlet::logging namespace
894 
895 } // end of servlet namespace
896 
897 #endif // SERVLET_LOGGER_H
level_logger info()
Creates new level_logger with logging level LEVEL::INFO
Definition: logger.h:455
level_logger config()
Creates new level_logger with logging level LEVEL::CONFIG
Definition: logger.h:460
Abstract interface for prefix_printer factory.
Definition: logger.h:188
bool is_loggable(LEVEL level) const
Tests if the requested level is loggable.
Definition: logger.h:483
Abstract interface for logging prefix printer.
Definition: logger.h:158
level_logger critical()
Creates new level_logger with logging level LEVEL::CRITICAL
Definition: logger.h:440
Abstract interface for log_output factory.
Definition: logger.h:76
level_logger & put(char ch)
Puts a character of type wchar to output if the logging level is sufficient.
Definition: logger.h:354
virtual void load_config(std::map< std::string, std::string, std::less<>> &props, const std::string &conf_prefix)=0
Loads configuration from the properties provided.
level_logger error()
Creates new level_logger with logging level LEVEL::ERROR
Definition: logger.h:445
const std::string & name() const
Returns name of this logger.
Definition: logger.h:434
Abstract interface for logging output.
Definition: logger.h:37
virtual prefix_printer * new_prefix_printer()=0
Creates new prefix_printer object and returns pointer to it.
std::shared_ptr< logger > log(const std::string &name="root")
Searches for registered logger with a given name.
Logger class.
Definition: logger.h:425
Logger with specific logging LEVEL to use.
Definition: logger.h:230
level_logger & put(char16_t ch)
Puts a character of type char16_t to output if the logging level is sufficient.
Definition: logger.h:361
virtual void flush()=0
Flushes the output represented by this object.
LEVEL get_log_level(const std::string &name)
Returns logging level for a logger with a given name.
void add_prefix_printer_factory(const std::string &name, prefix_printer_factory *fac)
This method allows to provide custom prefix_printer's in inherited registries.
Definition: logger.h:765
void set_log_output(log_output *new_out, SYNC_POLICY policy=SYNC_POLICY::SYNC)
Sets new log_output for this logger.
void set_prefix_printer(prefix_printer *pp)
Sets new prefix_printer for this registry.
Definition: logger.h:726
static constexpr std::size_t DEFAULT_ASYNC_QUEUE_SIZE
Default size of asynchronous queue used if synchronization policy is SYNC_POLICY::ASYNC ...
Definition: logger.h:634
level_logger & operator<<(const T &value)
Generic streaming output operator.
Definition: logger.h:875
void imbue(const std::locale &loc)
Imbue locale.
Definition: logger.h:511
level_logger trace()
Creates new level_logger with logging level LEVEL::TRACE
Definition: logger.h:470
level_logger & write(const char *s, std::streamsize n)
Writes first n characters of array s to the output stream if the logging level is sufficient...
virtual void print_prefix(LEVEL level, const std::string &name, std::ostream &out) const =0
Prints prefix to the log output.
void reset_loggers_config(bool update_prefix_printer, bool update_log_output, bool update_locale)
Traverses all created loggers and resets their configuration with new configuration parameters...
SYNC_POLICY get_synchronization_policy() const
Returns current synchronization policy used by this registry.
Definition: logger.h:713
virtual void load_config(std::map< std::string, std::string, std::less<>> &props, const std::string &conf_prefix, const std::string &base_dir)=0
Loads configuration from the properties provided.
level_logger warning()
Creates new level_logger with logging level LEVEL::WARNING
Definition: logger.h:450
level_logger debug()
Creates new level_logger with logging level LEVEL::DEBUG
Definition: logger.h:465
void add_log_output_factory(const std::string &name, log_output_factory *fac)
This method allows to provide custom log_output's in inherited registries.
Definition: logger.h:785
void set_synchronization_policy(SYNC_POLICY sync_policy)
Sets new synchronization policy.
level_logger & put(char32_t ch)
Puts a character of type char32_t to output if the logging level is sufficient.
Definition: logger.h:368
void set_log_output(log_output *log_out)
Sets new log_output for this registry.
level_logger log(LEVEL level)
Creates new level_logger with a provided logging level.
Definition: logger.h:476
void set_prefix_printer(std::shared_ptr< prefix_printer > new_pp)
Sets new prefix_printer for this logger.
Definition: logger.h:496
void imbue(const std::locale &loc)
Imbue locale.
Definition: logger.h:694
void set_base_directory(const std::string &base_dir)
Sets base directory.
Registry object to configure and hold available loggers.
Definition: logger.h:623
virtual log_output * new_log_output()=0
Creates new log_output object and returns pointer to it.
std::map< std::string, std::string, std::less<> > properties_type
Type definition for properties map.
Definition: logger.h:639
void set_log_level(LEVEL log_level)
Sets new new minimum logging level for this logger.
Definition: logger.h:491
level_logger & put(wchar_t ch)
Puts a character of type wchar_t to output if the logging level is sufficient.
Definition: logger.h:375
log_registry()
Creates registry object with default settings.
virtual void write_string(string_view str)=0
Writes a given string_view to the output represented by this object.
void read_configuration(const std::string &config_file_name, const std::string &base_dir, bool update_loggers=true)
Reads configuration file and parses properties as described in class documentation.
level_logger & flush()
Flushes underlying stream.
Definition: logger.h:346
static constexpr std::size_t DEFAULT_FILE_ROTATION_SIZE
Default file rotation size - 16 Mb.
Definition: logger.h:629
void set_log_level(LEVEL level)
Sets new global logging level.
Definition: logger.h:684