1 /* 2 * Copyright Andrey Semashev 2007 - 2015. 3 * Distributed under the Boost Software License, Version 1.0. 4 * (See accompanying file LICENSE_1_0.txt or copy at 5 * http://www.boost.org/LICENSE_1_0.txt) 6 */ 7 /*! 8 * \file text_multifile_backend.hpp 9 * \author Andrey Semashev 10 * \date 09.06.2009 11 * 12 * The header contains implementation of a text multi-file sink backend. 13 */ 14 15 #ifndef BOOST_LOG_SINKS_TEXT_MULTIFILE_BACKEND_HPP_INCLUDED_ 16 #define BOOST_LOG_SINKS_TEXT_MULTIFILE_BACKEND_HPP_INCLUDED_ 17 18 #include <ios> 19 #include <string> 20 #include <locale> 21 #include <ostream> 22 #include <boost/mpl/if.hpp> 23 #include <boost/mpl/bool.hpp> 24 #include <boost/type_traits/is_same.hpp> 25 #include <boost/filesystem/path.hpp> 26 #include <boost/log/detail/config.hpp> 27 #include <boost/log/detail/light_function.hpp> 28 #include <boost/log/detail/parameter_tools.hpp> 29 #include <boost/log/detail/cleanup_scope_guard.hpp> 30 #include <boost/log/keywords/auto_newline_mode.hpp> 31 #include <boost/log/sinks/auto_newline_mode.hpp> 32 #include <boost/log/sinks/basic_sink_backend.hpp> 33 #include <boost/log/utility/formatting_ostream.hpp> 34 #include <boost/log/detail/header.hpp> 35 36 #ifdef BOOST_HAS_PRAGMA_ONCE 37 #pragma once 38 #endif 39 40 namespace boost { 41 42 BOOST_LOG_OPEN_NAMESPACE 43 44 namespace sinks { 45 46 namespace file { 47 48 /*! 49 * An adapter class that allows to use regular formatters as file name generators. 50 */ 51 template< typename FormatterT > 52 class file_name_composer_adapter 53 { 54 public: 55 //! Functor result type 56 typedef filesystem::path result_type; 57 //! File name character type 58 typedef result_type::string_type::value_type native_char_type; 59 //! The adopted formatter type 60 typedef FormatterT formatter_type; 61 //! Formatting stream type 62 typedef basic_formatting_ostream< native_char_type > stream_type; 63 64 private: 65 //! The adopted formatter 66 formatter_type m_Formatter; 67 //! Formatted file name storage 68 mutable result_type::string_type m_FileName; 69 //! Formatting stream 70 mutable stream_type m_FormattingStream; 71 72 public: 73 /*! 74 * Initializing constructor 75 */ file_name_composer_adapter(formatter_type const & formatter,std::locale const & loc=std::locale ())76 explicit file_name_composer_adapter(formatter_type const& formatter, std::locale const& loc = std::locale()) : 77 m_Formatter(formatter), 78 m_FormattingStream(m_FileName) 79 { 80 m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit); 81 m_FormattingStream.imbue(loc); 82 } 83 /*! 84 * Copy constructor 85 */ file_name_composer_adapter(file_name_composer_adapter const & that)86 file_name_composer_adapter(file_name_composer_adapter const& that) : 87 m_Formatter(that.m_Formatter), 88 m_FormattingStream(m_FileName) 89 { 90 m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit); 91 m_FormattingStream.imbue(that.m_FormattingStream.getloc()); 92 } 93 /*! 94 * Assignment 95 */ operator =(file_name_composer_adapter const & that)96 file_name_composer_adapter& operator= (file_name_composer_adapter const& that) 97 { 98 m_Formatter = that.m_Formatter; 99 return *this; 100 } 101 102 /*! 103 * The operator generates a file name based on the log record 104 */ operator ()(record_view const & rec) const105 result_type operator() (record_view const& rec) const 106 { 107 boost::log::aux::cleanup_guard< stream_type > cleanup1(m_FormattingStream); 108 boost::log::aux::cleanup_guard< result_type::string_type > cleanup2(m_FileName); 109 110 m_Formatter(rec, m_FormattingStream); 111 m_FormattingStream.flush(); 112 113 return result_type(m_FileName); 114 } 115 }; 116 117 /*! 118 * The function adopts a log record formatter into a file name generator 119 * 120 * \param fmt The formatter function object to adopt 121 * \param loc The locale to use to character code conversion and formatting 122 */ 123 template< typename FormatterT > as_file_name_composer(FormatterT const & fmt,std::locale const & loc=std::locale ())124 inline file_name_composer_adapter< FormatterT > as_file_name_composer( 125 FormatterT const& fmt, std::locale const& loc = std::locale()) 126 { 127 return file_name_composer_adapter< FormatterT >(fmt, loc); 128 } 129 130 } // namespace file 131 132 133 /*! 134 * \brief An implementation of a text multiple files logging sink backend 135 * 136 * The sink backend puts formatted log records to one of the text files. 137 * The particular file is chosen upon each record's attribute values, which allows 138 * to distribute records into individual files or to group records related to 139 * some entity or process in a separate file. 140 */ 141 class text_multifile_backend : 142 public basic_formatted_sink_backend< char > 143 { 144 //! Base type 145 typedef basic_formatted_sink_backend< char > base_type; 146 147 public: 148 //! Character type 149 typedef base_type::char_type char_type; 150 //! String type to be used as a message text holder 151 typedef base_type::string_type string_type; 152 153 //! File name composer functor type 154 typedef boost::log::aux::light_function< filesystem::path (record_view const&) > file_name_composer_type; 155 156 private: 157 //! \cond 158 159 struct implementation; 160 implementation* m_pImpl; 161 162 //! \endcond 163 164 public: 165 /*! 166 * Default constructor. The constructed sink backend has no file name composer and 167 * thus will not write any files. All other parameters are set to their defaults. 168 */ 169 BOOST_LOG_API text_multifile_backend(); 170 171 /*! 172 * Constructor. Creates a sink backend with the specified named parameters. 173 * The following named parameters are supported: 174 * 175 * \li \c auto_newline_mode - Specifies automatic trailing newline insertion mode. Must be a value of 176 * the \c auto_newline_mode enum. By default, is <tt>auto_newline_mode::insert_if_missing</tt>. 177 */ 178 #ifndef BOOST_LOG_DOXYGEN_PASS 179 BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(text_multifile_backend, construct) 180 #else 181 template< typename... ArgsT > 182 explicit text_multifile_backend(ArgsT... const& args); 183 #endif 184 185 /*! 186 * Destructor 187 */ 188 BOOST_LOG_API ~text_multifile_backend(); 189 190 /*! 191 * The method sets file name composer functional object. Log record formatters are accepted, too. 192 * 193 * \param composer File name composer functor 194 */ 195 template< typename ComposerT > set_file_name_composer(ComposerT const & composer)196 void set_file_name_composer(ComposerT const& composer) 197 { 198 set_file_name_composer_internal(composer); 199 } 200 201 /*! 202 * Selects whether a trailing newline should be automatically inserted after every log record. See 203 * \c auto_newline_mode description for the possible modes of operation. 204 * 205 * \param mode The trailing newline insertion mode. 206 */ 207 BOOST_LOG_API void set_auto_newline_mode(auto_newline_mode mode); 208 209 /*! 210 * The method writes the message to the sink 211 */ 212 BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message); 213 214 private: 215 #ifndef BOOST_LOG_DOXYGEN_PASS 216 //! Constructor implementation 217 template< typename ArgsT > construct(ArgsT const & args)218 void construct(ArgsT const& args) 219 { 220 construct(args[keywords::auto_newline_mode | insert_if_missing]); 221 } 222 //! Constructor implementation 223 BOOST_LOG_API void construct(auto_newline_mode auto_newline); 224 225 //! The method sets the file name composer 226 BOOST_LOG_API void set_file_name_composer_internal(file_name_composer_type const& composer); 227 #endif // BOOST_LOG_DOXYGEN_PASS 228 }; 229 230 } // namespace sinks 231 232 BOOST_LOG_CLOSE_NAMESPACE // namespace log 233 234 } // namespace boost 235 236 #include <boost/log/detail/footer.hpp> 237 238 #endif // BOOST_LOG_SINKS_TEXT_MULTIFILE_BACKEND_HPP_INCLUDED_ 239