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.
		
		
		
		
		
			
		
			
				
					
					
						
							158 lines
						
					
					
						
							4.5 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							158 lines
						
					
					
						
							4.5 KiB
						
					
					
				
								/**
							 | 
						|
								 * @file formatter.h
							 | 
						|
								 * @author Harold Bruintjes <h.bruintjes@cs.rwth-aachen.de>
							 | 
						|
								 *
							 | 
						|
								 * Define the Formatter class, used to format output of a sink
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#pragma once
							 | 
						|
								
							 | 
						|
								#include <string>
							 | 
						|
								#include <tuple>
							 | 
						|
								
							 | 
						|
								namespace l3pp {
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Formats a log messages. This is a base class that simply print the message
							 | 
						|
								 * with the log level prefix, see derived classes such as TemplatedFormatter
							 | 
						|
								 * for more interesting data.
							 | 
						|
								 */
							 | 
						|
								class Formatter {
							 | 
						|
									friend class Logger;
							 | 
						|
								
							 | 
						|
									static void initialize();
							 | 
						|
								
							 | 
						|
									virtual std::string format(EntryContext const& context, std::string const& msg) const;
							 | 
						|
								public:
							 | 
						|
									virtual ~Formatter() {}
							 | 
						|
								
							 | 
						|
									std::string operator()(EntryContext const& context, std::string const& msg) {
							 | 
						|
										return format(context, msg);
							 | 
						|
									}
							 | 
						|
								};
							 | 
						|
								typedef std::shared_ptr<Formatter> FormatterPtr;
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Possible fields for FieldStr instance
							 | 
						|
								 */
							 | 
						|
								enum class Field {
							 | 
						|
									/// Name of the file (everything following the last path separator)
							 | 
						|
									FileName,
							 | 
						|
									/// Full path of the file
							 | 
						|
									FilePath,
							 | 
						|
									/// Line number
							 | 
						|
									Line,
							 | 
						|
									/// Name of function currently executed
							 | 
						|
									Function,
							 | 
						|
									/// Name of the logger
							 | 
						|
									LoggerName,
							 | 
						|
									/// Message to be logged
							 | 
						|
									Message,
							 | 
						|
									/// Level of the log entry
							 | 
						|
									LogLevel,
							 | 
						|
									/// Number of milliseconds since the logger was initialized
							 | 
						|
									WallTime,
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Controls justification of formatted log fields.
							 | 
						|
								 */
							 | 
						|
								enum class Justification {
							 | 
						|
									/// Left align field
							 | 
						|
									LEFT,
							 | 
						|
									/// Right align field
							 | 
						|
									RIGHT
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Formatter for log entry fields, with the exception of time stamp formatting
							 | 
						|
								 * (see TimeStr for that). The Field template argument determines which field
							 | 
						|
								 * is printed, see logging::Field.
							 | 
						|
								 * The other template arguments control the alignment of the output string.
							 | 
						|
								 */
							 | 
						|
								template<Field field, int Width = 0, Justification j = Justification::RIGHT, char Fill = ' '>
							 | 
						|
								class FieldStr {
							 | 
						|
								public:
							 | 
						|
									void stream(std::ostream& os, EntryContext const& context, std::string const& msg) const;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Formatter for log time stamps. The constructor expects a single string
							 | 
						|
								 * argument which is a formatter for the time stamp. For the specification of
							 | 
						|
								 * this format string see the documentation for std::put_time . You can use for
							 | 
						|
								 * example "%c" or "%T".
							 | 
						|
								 * The template arguments control the alignment of the output string.
							 | 
						|
								 */
							 | 
						|
								class TimeStr {
							 | 
						|
									std::string formatStr;
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
									TimeStr(char const* format) : formatStr(format) {
							 | 
						|
									}
							 | 
						|
									TimeStr(std::string const& format) : formatStr(format) {
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									void stream(std::ostream& os, EntryContext const& context, std::string const&) const;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Formatter which formats the output based on the (templated) arguments given.
							 | 
						|
								 * The arguments can be anything that implements the stream operator <<, but
							 | 
						|
								 * more interestingly also the various FormatField subclasses. These classes
							 | 
						|
								 * can output the various fields associated with a log entry.
							 | 
						|
								 */
							 | 
						|
								template<typename ... Formatters>
							 | 
						|
								class TemplateFormatter : public Formatter {
							 | 
						|
									std::tuple<Formatters...> formatters;
							 | 
						|
								
							 | 
						|
									template <int N>
							 | 
						|
									typename std::enable_if<N < (sizeof...(Formatters))>::type
							 | 
						|
									formatTuple(EntryContext const& context, std::string const& msg, std::ostream& os) const {
							 | 
						|
										formatElement(std::get<N>(formatters), os, context, msg);
							 | 
						|
										formatTuple<N+1>(context, msg, os);
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									template <int N>
							 | 
						|
									typename std::enable_if<(N >= sizeof...(Formatters))>::type
							 | 
						|
									formatTuple(EntryContext const&, std::string const&, std::ostream&) const {
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									template<Field field, int Width, Justification j, char Fill>
							 | 
						|
									void formatElement(FieldStr<field, Width, j, Fill> const& t, std::ostream& stream, EntryContext const& context, std::string const& msg) const {
							 | 
						|
										t.stream(stream, context, msg);
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									void formatElement(TimeStr const& t, std::ostream& stream, EntryContext const& context, std::string const& msg) const {
							 | 
						|
										t.stream(stream, context, msg);
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									template<typename T>
							 | 
						|
									void formatElement(T const& t, std::ostream& stream, EntryContext const&, std::string const&) const {
							 | 
						|
										stream << t;
							 | 
						|
									}
							 | 
						|
								public:
							 | 
						|
									TemplateFormatter(Formatters ... formatters) :
							 | 
						|
										formatters(std::forward<Formatters>(formatters)...)
							 | 
						|
									{
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									std::string format(EntryContext const& context, std::string const& msg) const override;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Helper function to create a TemplateFormatter. Simply call with some
							 | 
						|
								 * formatable arguments, e.g.,
							 | 
						|
								 * @code{.cpp}
							 | 
						|
								 * logging::makeTemplateFormatter(
							 | 
						|
								 *     logging::FieldStr<logging::Field::LogLevel>(), " - ",
							 | 
						|
								 *     logging::FieldStr<logging::Field::Message>(), "\n");
							 | 
						|
								 * @endcode
							 | 
						|
								 */
							 | 
						|
								template<typename ... Formatters>
							 | 
						|
								FormatterPtr makeTemplateFormatter(Formatters&& ... formatters) {
							 | 
						|
									return std::make_shared<TemplateFormatter<Formatters...>>(std::forward<Formatters>(formatters)...);
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								}
							 |