]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/log/sinks/text_file_backend.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / log / sinks / text_file_backend.hpp
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_file_backend.hpp
9 * \author Andrey Semashev
10 * \date 09.06.2009
11 *
12 * The header contains implementation of a text file sink backend.
13 */
14
15 #ifndef BOOST_LOG_SINKS_TEXT_FILE_BACKEND_HPP_INCLUDED_
16 #define BOOST_LOG_SINKS_TEXT_FILE_BACKEND_HPP_INCLUDED_
17
18 #include <ios>
19 #include <string>
20 #include <ostream>
21 #include <boost/limits.hpp>
22 #include <boost/cstdint.hpp>
23 #include <boost/optional/optional.hpp>
24 #include <boost/smart_ptr/shared_ptr.hpp>
25 #include <boost/date_time/date_defs.hpp>
26 #include <boost/date_time/special_defs.hpp>
27 #include <boost/date_time/gregorian/greg_day.hpp>
28 #include <boost/date_time/posix_time/posix_time_types.hpp>
29 #include <boost/filesystem/path.hpp>
30 #include <boost/log/keywords/max_size.hpp>
31 #include <boost/log/keywords/max_files.hpp>
32 #include <boost/log/keywords/min_free_space.hpp>
33 #include <boost/log/keywords/target.hpp>
34 #include <boost/log/keywords/target_file_name.hpp>
35 #include <boost/log/keywords/file_name.hpp>
36 #include <boost/log/keywords/open_mode.hpp>
37 #include <boost/log/keywords/auto_flush.hpp>
38 #include <boost/log/keywords/rotation_size.hpp>
39 #include <boost/log/keywords/time_based_rotation.hpp>
40 #include <boost/log/keywords/enable_final_rotation.hpp>
41 #include <boost/log/keywords/auto_newline_mode.hpp>
42 #include <boost/log/detail/config.hpp>
43 #include <boost/log/detail/light_function.hpp>
44 #include <boost/log/detail/parameter_tools.hpp>
45 #include <boost/log/sinks/auto_newline_mode.hpp>
46 #include <boost/log/sinks/basic_sink_backend.hpp>
47 #include <boost/log/sinks/frontend_requirements.hpp>
48 #include <boost/log/detail/header.hpp>
49
50 #ifdef BOOST_HAS_PRAGMA_ONCE
51 #pragma once
52 #endif
53
54 namespace boost {
55
56 BOOST_LOG_OPEN_NAMESPACE
57
58 namespace sinks {
59
60 namespace file {
61
62 //! The enumeration of the stored files scan methods
63 enum scan_method
64 {
65 no_scan, //!< Don't scan for stored files
66 scan_matching, //!< Scan for files with names matching the specified mask
67 scan_all //!< Scan for all files in the directory
68 };
69
70 //! The structure contains filesystem scanning results
71 struct scan_result
72 {
73 //! The number of found files
74 uintmax_t found_count;
75 //! If populated, the largest file counter that was used in the found file names
76 boost::optional< unsigned int > last_file_counter;
77
78 scan_result() BOOST_NOEXCEPT :
79 found_count(0u)
80 {
81 }
82 };
83
84 /*!
85 * \brief Base class for file collectors
86 *
87 * All file collectors, supported by file sink backends, should inherit this class.
88 */
89 struct BOOST_LOG_NO_VTABLE collector
90 {
91 /*!
92 * Default constructor
93 */
94 BOOST_DEFAULTED_FUNCTION(collector(), {})
95
96 /*!
97 * Virtual destructor
98 */
99 #if !defined(BOOST_LOG_NO_CXX11_DEFAULTED_VIRTUAL_FUNCTIONS)
100 BOOST_DEFAULTED_FUNCTION(virtual ~collector(), {})
101 #else
102 virtual ~collector() {}
103 #endif
104
105 /*!
106 * The function stores the specified file in the storage. May lead to an older file
107 * deletion and a long file moving.
108 *
109 * \param src_path The name of the file to be stored
110 */
111 virtual void store_file(filesystem::path const& src_path) = 0;
112
113 /*!
114 * The function checks if the specified path refers to an existing file in the storage.
115 *
116 * \param src_path The path to be checked
117 */
118 virtual bool is_in_storage(filesystem::path const& src_path) const = 0;
119
120 /*!
121 * Scans the target directory for the files that have already been stored. The found
122 * files are added to the collector in order to be tracked and erased, if needed.
123 *
124 * The function may scan the directory in two ways: it will either consider every
125 * file in the directory a log file, or will only consider files with names that
126 * match the specified pattern. The pattern may contain the following placeholders:
127 *
128 * \li %y, %Y, %m, %d - date components, in Boost.DateTime meaning.
129 * \li %H, %M, %S, %f - time components, in Boost.DateTime meaning.
130 * \li %N - numeric file counter. May also contain width specification
131 * in printf-compatible form (e.g. %5N). The resulting number will always be zero-filled.
132 * \li %% - a percent sign
133 *
134 * All other placeholders are not supported.
135 *
136 * \param method The method of scanning. If \c no_scan is specified, the call has no effect.
137 * \param pattern The file name pattern if \a method is \c scan_matching. Otherwise the parameter
138 * is not used.
139 * \return The result of filesystem scanning. The last file counter is only populated if
140 * \a method is \c scan_matching, the \a pattern contains %N placeholder, and at least
141 * one file matching the pattern is found.
142 *
143 * \note In case if \a method is \c scan_matching the effect of this function is highly dependent
144 * on the \a pattern definition. It is recommended to choose patterns with easily
145 * distinguished placeholders (i.e. having delimiters between them). Otherwise
146 * either some files can be mistakenly found or not found, which in turn may lead
147 * to deletion of an unintended file.
148 */
149 virtual scan_result scan_for_files(scan_method method, filesystem::path const& pattern = filesystem::path()) = 0;
150
151 BOOST_DELETED_FUNCTION(collector(collector const&))
152 BOOST_DELETED_FUNCTION(collector& operator= (collector const&))
153 };
154
155 namespace aux {
156
157 //! Creates and returns a file collector with the specified parameters
158 BOOST_LOG_API shared_ptr< collector > make_collector(
159 filesystem::path const& target_dir,
160 uintmax_t max_size,
161 uintmax_t min_free_space,
162 uintmax_t max_files = (std::numeric_limits< uintmax_t >::max)()
163 );
164 template< typename ArgsT >
165 inline shared_ptr< collector > make_collector(ArgsT const& args)
166 {
167 return aux::make_collector(
168 filesystem::path(args[keywords::target]),
169 args[keywords::max_size | (std::numeric_limits< uintmax_t >::max)()],
170 args[keywords::min_free_space | static_cast< uintmax_t >(0)],
171 args[keywords::max_files | (std::numeric_limits< uintmax_t >::max)()]);
172 }
173
174 } // namespace aux
175
176 #ifndef BOOST_LOG_DOXYGEN_PASS
177
178 template< typename T1 >
179 inline shared_ptr< collector > make_collector(T1 const& a1)
180 {
181 return aux::make_collector(a1);
182 }
183 template< typename T1, typename T2 >
184 inline shared_ptr< collector > make_collector(T1 const& a1, T2 const& a2)
185 {
186 return aux::make_collector((a1, a2));
187 }
188 template< typename T1, typename T2, typename T3 >
189 inline shared_ptr< collector > make_collector(T1 const& a1, T2 const& a2, T3 const& a3)
190 {
191 return aux::make_collector((a1, a2, a3));
192 }
193 template< typename T1, typename T2, typename T3, typename T4 >
194 inline shared_ptr< collector > make_collector(T1 const& a1, T2 const& a2, T3 const& a3, T4 const& a4)
195 {
196 return aux::make_collector((a1, a2, a3, a4));
197 }
198
199 #else
200
201 /*!
202 * The function creates a file collector for the specified target directory.
203 * Each target directory is managed by a single file collector, so if
204 * this function is called several times for the same directory,
205 * it will return a reference to the same file collector. It is safe
206 * to use the same collector in different sinks, even in a multithreaded
207 * application.
208 *
209 * One can specify certain restrictions for the stored files, such as
210 * maximum total size or minimum free space left in the target directory.
211 * If any of the specified restrictions is not met, the oldest stored file
212 * is deleted. If the same collector is requested more than once with
213 * different restrictions, the collector will act according to the most strict
214 * combination of all specified restrictions.
215 *
216 * The following named parameters are supported:
217 *
218 * \li \c target - Specifies the target directory for the files being stored in. This parameter
219 * is mandatory.
220 * \li \c max_size - Specifies the maximum total size, in bytes, of stored files that the collector
221 * will try not to exceed. If the size exceeds this threshold the oldest file(s) is
222 * deleted to free space. Note that the threshold may be exceeded if the size of
223 * individual files exceed the \c max_size value. The threshold is not maintained,
224 * if not specified.
225 * \li \c min_free_space - Specifies the minimum free space, in bytes, in the target directory that
226 * the collector tries to maintain. If the threshold is exceeded, the oldest
227 * file(s) is deleted to free space. The threshold is not maintained, if not
228 * specified.
229 * \li \c max_files - Specifies the maximum number of log files stored. If the number of files exceeds
230 * this threshold, the oldest file(s) is deleted to free space. The threshhold is
231 * not maintained if not specified.
232 *
233 * \return The file collector.
234 */
235 template< typename... ArgsT >
236 shared_ptr< collector > make_collector(ArgsT... const& args);
237
238 #endif // BOOST_LOG_DOXYGEN_PASS
239
240 /*!
241 * The class represents the time point of log file rotation. One can specify one of three
242 * types of time point based rotation:
243 *
244 * \li rotation takes place every day, at the specified time
245 * \li rotation takes place on the specified day of every week, at the specified time
246 * \li rotation takes place on the specified day of every month, at the specified time
247 *
248 * The time points are considered to be local time.
249 */
250 class rotation_at_time_point
251 {
252 public:
253 typedef bool result_type;
254
255 private:
256 enum day_kind
257 {
258 not_specified,
259 weekday,
260 monthday
261 };
262
263 unsigned char m_Day : 6;
264 unsigned char m_DayKind : 2; // contains day_kind values
265 unsigned char m_Hour, m_Minute, m_Second;
266
267 mutable posix_time::ptime m_Previous;
268
269 public:
270 /*!
271 * Creates a rotation time point of every day at the specified time
272 *
273 * \param hour The rotation hour, should be within 0 and 23
274 * \param minute The rotation minute, should be within 0 and 59
275 * \param second The rotation second, should be within 0 and 59
276 */
277 BOOST_LOG_API explicit rotation_at_time_point(unsigned char hour, unsigned char minute, unsigned char second);
278
279 /*!
280 * Creates a rotation time point of each specified weekday at the specified time
281 *
282 * \param wday The weekday of the rotation
283 * \param hour The rotation hour, should be within 0 and 23
284 * \param minute The rotation minute, should be within 0 and 59
285 * \param second The rotation second, should be within 0 and 59
286 */
287 BOOST_LOG_API explicit rotation_at_time_point(
288 date_time::weekdays wday,
289 unsigned char hour = 0,
290 unsigned char minute = 0,
291 unsigned char second = 0);
292
293 /*!
294 * Creates a rotation time point of each specified day of month at the specified time
295 *
296 * \param mday The monthday of the rotation, should be within 1 and 31
297 * \param hour The rotation hour, should be within 0 and 23
298 * \param minute The rotation minute, should be within 0 and 59
299 * \param second The rotation second, should be within 0 and 59
300 */
301 BOOST_LOG_API explicit rotation_at_time_point(
302 gregorian::greg_day mday,
303 unsigned char hour = 0,
304 unsigned char minute = 0,
305 unsigned char second = 0);
306
307 /*!
308 * Checks if it's time to rotate the file
309 */
310 BOOST_LOG_API bool operator() () const;
311 };
312
313 /*!
314 * The class represents the time interval of log file rotation. The log file will be rotated
315 * after the specified time interval has passed.
316 */
317 class rotation_at_time_interval
318 {
319 public:
320 typedef bool result_type;
321
322 private:
323 posix_time::time_duration m_Interval;
324 mutable posix_time::ptime m_Previous;
325
326 public:
327 /*!
328 * Creates a rotation time interval of the specified duration
329 *
330 * \param interval The interval of the rotation, should be no less than 1 second
331 */
332 explicit rotation_at_time_interval(posix_time::time_duration const& interval) :
333 m_Interval(interval)
334 {
335 BOOST_ASSERT(!interval.is_special());
336 BOOST_ASSERT(interval.total_seconds() > 0);
337 }
338
339 /*!
340 * Checks if it's time to rotate the file
341 */
342 BOOST_LOG_API bool operator() () const;
343 };
344
345 } // namespace file
346
347
348 /*!
349 * \brief An implementation of a text file logging sink backend
350 *
351 * The sink backend puts formatted log records to a text file.
352 * The sink supports file rotation and advanced file control, such as
353 * size and file count restriction.
354 */
355 class text_file_backend :
356 public basic_formatted_sink_backend<
357 char,
358 combine_requirements< synchronized_feeding, flushing >::type
359 >
360 {
361 //! Base type
362 typedef basic_formatted_sink_backend<
363 char,
364 combine_requirements< synchronized_feeding, flushing >::type
365 > base_type;
366
367 public:
368 //! Character type
369 typedef base_type::char_type char_type;
370 //! String type to be used as a message text holder
371 typedef base_type::string_type string_type;
372 //! Stream type
373 typedef std::basic_ostream< char_type > stream_type;
374
375 //! File open handler
376 typedef boost::log::aux::light_function< void (stream_type&) > open_handler_type;
377 //! File close handler
378 typedef boost::log::aux::light_function< void (stream_type&) > close_handler_type;
379
380 //! Predicate that defines the time-based condition for file rotation
381 typedef boost::log::aux::light_function< bool () > time_based_rotation_predicate;
382
383 private:
384 //! \cond
385
386 struct implementation;
387 implementation* m_pImpl;
388
389 //! \endcond
390
391 public:
392 /*!
393 * Default constructor. The constructed sink backend uses default values of all the parameters.
394 */
395 BOOST_LOG_API text_file_backend();
396
397 /*!
398 * Constructor. Creates a sink backend with the specified named parameters.
399 * The following named parameters are supported:
400 *
401 * \li \c file_name - Specifies the active file name pattern where logs are actually written to. The pattern may
402 * contain directory and file name portions, but only the file name may contain
403 * placeholders. The backend supports Boost.DateTime placeholders for injecting
404 * current time and date into the file name. Also, an additional %N placeholder is
405 * supported, it will be replaced with an integral increasing file counter. The placeholder
406 * may also contain width specification in the printf-compatible form (e.g. %5N). The
407 * printed file counter will always be zero-filled. If \c file_name is not specified,
408 * pattern "%5N.log" will be used.
409 * \li \c target_file_name - Specifies the target file name pattern to use to rename the log file on rotation,
410 * before passing it to the file collector. The pattern may contain the same
411 * placeholders as the \c file_name parameter. By default, no renaming is done,
412 * i.e. the written log file keeps its name according to \c file_name.
413 * \li \c open_mode - File open mode. The mode should be presented in form of mask compatible to
414 * <tt>std::ios_base::openmode</tt>. If not specified, <tt>trunc | out</tt> will be used.
415 * \li \c rotation_size - Specifies the approximate size, in characters written, of the temporary file
416 * upon which the file is passed to the file collector. Note the size does
417 * not count any possible character conversions that may take place during
418 * writing to the file. If not specified, the file won't be rotated upon reaching
419 * any size.
420 * \li \c time_based_rotation - Specifies the predicate for time-based file rotation.
421 * No time-based file rotations will be performed, if not specified.
422 * \li \c enable_final_rotation - Specifies a flag, whether or not perform log file rotation on
423 * sink backend destruction. By default, is \c true.
424 * \li \c auto_flush - Specifies a flag, whether or not to automatically flush the file after each
425 * written log record. By default, is \c false.
426 * \li \c auto_newline_mode - Specifies automatic trailing newline insertion mode. Must be a value of
427 * the \c auto_newline_mode enum. By default, is <tt>auto_newline_mode::insert_if_missing</tt>.
428 *
429 * \note Read the caution note regarding file name pattern in the <tt>sinks::file::collector::scan_for_files</tt>
430 * documentation.
431 */
432 #ifndef BOOST_LOG_DOXYGEN_PASS
433 BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(text_file_backend, construct)
434 #else
435 template< typename... ArgsT >
436 explicit text_file_backend(ArgsT... const& args);
437 #endif
438
439 /*!
440 * Destructor
441 */
442 BOOST_LOG_API ~text_file_backend();
443
444 /*!
445 * The method sets the active file name wildcard for the files being written. The wildcard supports
446 * date and time injection into the file name.
447 *
448 * \param pattern The name pattern for the file being written.
449 */
450 template< typename PathT >
451 void set_file_name_pattern(PathT const& pattern)
452 {
453 set_file_name_pattern_internal(filesystem::path(pattern));
454 }
455
456 /*!
457 * The method sets the target file name wildcard for the files being rotated. The wildcard supports
458 * date and time injection into the file name.
459 *
460 * This pattern will be used when the log file is being rotated, to rename the just written
461 * log file (which has the name according to the pattern in the \c file_name constructor parameter or
462 * set by a call to \c set_file_name_pattern), just before passing the file to the file collector.
463 *
464 * \param pattern The name pattern for the file being rotated.
465 */
466 template< typename PathT >
467 void set_target_file_name_pattern(PathT const& pattern)
468 {
469 set_target_file_name_pattern_internal(filesystem::path(pattern));
470 }
471
472 /*!
473 * The method sets the file open mode
474 *
475 * \param mode File open mode
476 */
477 BOOST_LOG_API void set_open_mode(std::ios_base::openmode mode);
478
479 /*!
480 * The method sets the log file collector function. The function is called
481 * on file rotation and is being passed the written file name.
482 *
483 * \param collector The file collector function object
484 */
485 BOOST_LOG_API void set_file_collector(shared_ptr< file::collector > const& collector);
486
487 /*!
488 * The method sets file opening handler. The handler will be called every time
489 * the backend opens a new temporary file. The handler may write a header to the
490 * opened file in order to maintain file validity.
491 *
492 * \param handler The file open handler function object
493 */
494 BOOST_LOG_API void set_open_handler(open_handler_type const& handler);
495
496 /*!
497 * The method sets file closing handler. The handler will be called every time
498 * the backend closes a temporary file. The handler may write a footer to the
499 * opened file in order to maintain file validity.
500 *
501 * \param handler The file close handler function object
502 */
503 BOOST_LOG_API void set_close_handler(close_handler_type const& handler);
504
505 /*!
506 * The method sets maximum file size. When the size is reached, file rotation is performed.
507 *
508 * \note The size does not count any possible character translations that may happen in
509 * the underlying API. This may result in greater actual sizes of the written files.
510 *
511 * \param size The maximum file size, in characters.
512 */
513 BOOST_LOG_API void set_rotation_size(uintmax_t size);
514
515 /*!
516 * The method sets the predicate that defines the time-based condition for file rotation.
517 *
518 * \note The rotation always occurs on writing a log record, so the rotation is
519 * not strictly bound to the specified condition.
520 *
521 * \param predicate The predicate that defines the time-based condition for file rotation.
522 * If empty, no time-based rotation will take place.
523 */
524 BOOST_LOG_API void set_time_based_rotation(time_based_rotation_predicate const& predicate);
525
526 /*!
527 * The method allows to enable or disable log file rotation on sink destruction.
528 *
529 * By default the sink backend will rotate the log file, if it's been written to, on
530 * destruction.
531 *
532 * \param enable The flag indicates whether the final rotation should be performed.
533 */
534 BOOST_LOG_API void enable_final_rotation(bool enable);
535
536 /*!
537 * Sets the flag to automatically flush write buffers of the file being written after each log record.
538 *
539 * \param enable The flag indicates whether the automatic buffer flush should be performed.
540 */
541 BOOST_LOG_API void auto_flush(bool enable = true);
542
543 /*!
544 * Selects whether a trailing newline should be automatically inserted after every log record. See
545 * \c auto_newline_mode description for the possible modes of operation.
546 *
547 * \param mode The trailing newline insertion mode.
548 */
549 BOOST_LOG_API void set_auto_newline_mode(auto_newline_mode mode);
550
551 /*!
552 * \return The name of the currently open log file. If no file is open, returns an empty path.
553 */
554 BOOST_LOG_API filesystem::path get_current_file_name() const;
555
556 /*!
557 * Performs scanning of the target directory for log files that may have been left from
558 * previous runs of the application. The found files are considered by the file collector
559 * as if they were rotated.
560 *
561 * The file scan can be performed in two ways: either all files in the target directory will
562 * be considered as log files, or only those files that satisfy the target file name pattern.
563 * See documentation on <tt>sinks::file::collector::scan_for_files</tt> for more information.
564 *
565 * \pre File collector and the proper file name pattern have already been set.
566 *
567 * \param method File scanning method
568 * \param update_counter If \c true and \a method is \c scan_matching, the method attempts
569 * to update the internal file counter according to the found files. The counter
570 * is unaffected otherwise.
571 * \return The number of files found.
572 *
573 * \note The method essentially delegates to the same-named function of the file collector.
574 */
575 BOOST_LOG_API uintmax_t scan_for_files(
576 file::scan_method method = file::scan_matching, bool update_counter = true);
577
578 /*!
579 * The method writes the message to the sink
580 */
581 BOOST_LOG_API void consume(record_view const& rec, string_type const& formatted_message);
582
583 /*!
584 * The method flushes the currently open log file
585 */
586 BOOST_LOG_API void flush();
587
588 /*!
589 * The method rotates the file
590 */
591 BOOST_LOG_API void rotate_file();
592
593 private:
594 #ifndef BOOST_LOG_DOXYGEN_PASS
595 //! Constructor implementation
596 template< typename ArgsT >
597 void construct(ArgsT const& args)
598 {
599 construct(
600 filesystem::path(args[keywords::file_name | filesystem::path()]),
601 filesystem::path(args[keywords::target_file_name | filesystem::path()]),
602 args[keywords::open_mode | (std::ios_base::trunc | std::ios_base::out)],
603 args[keywords::rotation_size | (std::numeric_limits< uintmax_t >::max)()],
604 args[keywords::time_based_rotation | time_based_rotation_predicate()],
605 args[keywords::auto_newline_mode | insert_if_missing],
606 args[keywords::auto_flush | false],
607 args[keywords::enable_final_rotation | true]);
608 }
609 //! Constructor implementation
610 BOOST_LOG_API void construct(
611 filesystem::path const& pattern,
612 filesystem::path const& target_file_name,
613 std::ios_base::openmode mode,
614 uintmax_t rotation_size,
615 time_based_rotation_predicate const& time_based_rotation,
616 auto_newline_mode auto_newline,
617 bool auto_flush,
618 bool enable_final_rotation);
619
620 //! The method sets file name pattern
621 BOOST_LOG_API void set_file_name_pattern_internal(filesystem::path const& pattern);
622 //! The method sets target file name pattern
623 BOOST_LOG_API void set_target_file_name_pattern_internal(filesystem::path const& pattern);
624
625 //! Closes the currently open file
626 void close_file();
627 #endif // BOOST_LOG_DOXYGEN_PASS
628 };
629
630 } // namespace sinks
631
632 BOOST_LOG_CLOSE_NAMESPACE // namespace log
633
634 } // namespace boost
635
636 #include <boost/log/detail/footer.hpp>
637
638 #endif // BOOST_LOG_SINKS_TEXT_FILE_BACKEND_HPP_INCLUDED_