|
Boost : |
Subject: Re: [boost] Boost.log: set_channel name dynamically for a basic_composite_logger
From: syvyi (alexander.svk_at_[hidden])
Date: 2012-10-20 11:35:30
I need to be UNICODE friendly. What is analog to BOOST_LOG for UNICODE?
#pragma once
/*
* Copyright Alexander Sivak 2012 - 2013.
*/
/*!
* \file logger\manster_logger.h
* \author Alexander Sivak
* \date 16.10.2012
*
* This header contains logger class declaration.
*/
#pragma comment(lib, "Shlwapi.lib") // PathStripPath
#include <tchar.h>
#include <Shlwapi.h>
#include <string>
#include <boost/typeof/typeof.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
// SYSTEM
//
#include <string>
#include <map>
#include <Windows.h>
// PROJECT
//
#include <boost/log/core.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/filters.hpp>
#include <boost/log/formatters.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/utility/exception_handler.hpp>
#include <boost/log/sources/exception_handler_feature.hpp>
#include <boost/log/sources/channel_feature.hpp>
#include <boost/thread.hpp>
#include <boost/make_shared.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/log/trivial.hpp>
#include <boost/thread/shared_mutex.hpp>
// LOCAL
//
namespace logging = boost::log;
namespace sinks = boost::log::sinks;
namespace src = boost::log::sources;
namespace fmt = boost::log::formatters;
namespace flt = boost::log::filters;
namespace attrs = boost::log::attributes;
namespace keywords = boost::log::keywords;
#define MANSTER_LOG_DECLARE_GLOBAL_LOGGER_ARGS_INIT( tag_name, lg, args )\
struct tag_name\
{\
typedef lg logger_type;\
enum registration_line_t { registration_line = __LINE__ };\
static const char* registration_file() { return __FILE__; }\
static logger_type construct_logger()\
{\
return logger_type(BOOST_PP_SEQ_ENUM(args));\
}\
static inline logger_type& get()\
{\
return ::boost::log::sources::aux::logger_singleton< tag_name
>::get();\
}\
};\
inline tag_name::logger_type& BOOST_JOIN(get_, tag_name)()\
{\
return tag_name::get();\
}
enum severity_level
{
information,
warning,
error,
fatal
};
template< typename CharT, typename TraitsT >
inline std::basic_ostream< CharT, TraitsT >& operator<< (
std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)
{
static const char* const str[] =
{
"information",
"warning",
"error",
"fatal"
};
if (static_cast< std::size_t >(lvl) < (sizeof(str) / sizeof(*str)))
strm << str[lvl];
else
strm << static_cast< int >(lvl);
return strm;
}
namespace manster
{
class logger // Non-copyconstractable and non-copyable, since scoped_ptr is
used.
{
public:
// TYPES
typedef boost::shared_ptr< logger > logger_ptr;
enum logger_type
{
db,
sys,
gui,
inet
};
// Compiler copy_ctor/dtor/operator=
// OPERATIONS
static logger_ptr const & instance()
{
if ( !instance_.get( ) )
instance_.reset( new logger( ) );
return instance_;
}
class manster_logger_mt;
void log( logger_type const & lg_type, std::string const & logged_data )
{
if ( initialized )
BOOST_LOG( loggers_map[ lg_type ] ) << logged_data.data( );
}
void log( logger_type const & lg_type, std::string const & logged_data,
severity_level const & lvl )
{
if ( initialized )
BOOST_LOG_SEV( loggers_map[ lg_type ], lvl ) << logged_data.data( );
}
void log( logger_type const & lg_type, std::wstring const & logged_data )
{
if ( initialized )
BOOST_LOG( wloggers_map[ lg_type ] ) << logged_data.data( );
}
void log( logger_type const & lg_type, std::wstring const & logged_data,
severity_level const & lvl )
{
if ( initialized )
BOOST_LOG_SEV( wloggers_map[ lg_type ], lvl ) << logged_data.data( );
}
void initialize( );
// ACCESS
void set_low_bound_filter( severity_level const & lvl )
{
sink_ptr->set_filter( flt::attr< severity_level >( "Severity",
std::nothrow) >= lvl );
}
public:
// TYPES
// Multibyte character logger type.
class manster_logger_mt :
public src::basic_composite_logger<
char,
manster_logger_mt,
// src::multi_thread_model<logging::aux::light_rw_mutex>,
src::multi_thread_model< boost::shared_mutex >,
src::features<
src::severity< severity_level >,
// src::exception_handler,
src::channel< std::string >
>
>
{
BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS( manster_logger_mt )
};
// MULTIBYTE CHARACTER LOGGERS
MANSTER_LOG_DECLARE_GLOBAL_LOGGER_ARGS_INIT(
logman_gui,
manster_logger_mt,
(keywords::severity = information)(keywords::channel = "GUI"))
MANSTER_LOG_DECLARE_GLOBAL_LOGGER_ARGS_INIT(
logman_inet,
manster_logger_mt,
(keywords::severity = information)(keywords::channel = "Inet"))
MANSTER_LOG_DECLARE_GLOBAL_LOGGER_ARGS_INIT(
logman_db,
manster_logger_mt,
(keywords::severity = information)(keywords::channel = "DataBase"))
MANSTER_LOG_DECLARE_GLOBAL_LOGGER_ARGS_INIT(
logman_sys,
manster_logger_mt,
(keywords::severity = information)(keywords::channel = "Sys"))
// Wide-character logger type.
class manster_wlogger_mt :
public src::basic_composite_logger<
wchar_t,
manster_wlogger_mt,
src::multi_thread_model< boost::shared_mutex >,
src::features<
src::severity< severity_level >,
src::channel< std::wstring >
>
>
{
BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS( manster_wlogger_mt )
};
// WIDE-BYTE LOGGERS
MANSTER_LOG_DECLARE_GLOBAL_LOGGER_ARGS_INIT(
wlogman_gui,
manster_wlogger_mt,
(keywords::severity = information)(keywords::channel = L"GUI"))
MANSTER_LOG_DECLARE_GLOBAL_LOGGER_ARGS_INIT(
wlogman_inet,
manster_wlogger_mt,
(keywords::severity = information)(keywords::channel = L"Inet"))
MANSTER_LOG_DECLARE_GLOBAL_LOGGER_ARGS_INIT(
wlogman_db,
manster_wlogger_mt,
(keywords::severity = information)(keywords::channel = L"DataBase"))
MANSTER_LOG_DECLARE_GLOBAL_LOGGER_ARGS_INIT(
wlogman_sys,
manster_wlogger_mt,
(keywords::severity = information)(keywords::channel = L"Sys"))
// FIELDS
static bool initialized;
private:
// LIFECYCLE
logger() : sink_ptr( boost::make_shared< file_sink > ( keywords::file_name
= ".//log//%N.log" ) )
{
}
// FIELDS && TYPES
typedef sinks::synchronous_sink< sinks::text_file_backend > file_sink;
boost::shared_ptr< file_sink > sink_ptr;
static logger_ptr instance_;
enum byteness { unicode, multi };
typedef std::map< logger_type, manster_logger_mt > log_type_to_log;
static log_type_to_log loggers_map;
typedef std::map< logger_type, manster_wlogger_mt > log_type_to_wlog;
static log_type_to_wlog wloggers_map;
};
}
typedef std::basic_string< TCHAR > stl_tchs;
BOOST_TYPEOF_REGISTER_TYPE( severity_level );
BOOST_TYPEOF_REGISTER_TYPE( manster::logger::logger_type );
//! Adds line number and file name to a message.
inline std::basic_string< TCHAR > locate_msg( stl_tchs const & msg, stl_tchs
const & line, stl_tchs const & file )
{
PathStripPath( const_cast< LPTSTR >( file.data( ) ) );
stl_tchs lm = msg;
static stl_tchs const fhead = _T( " File: " );
static stl_tchs const lhead = _T( " Line: " );
lm += fhead + file + lhead + line;
return lm;
}
//! Types. conseq: std::basic_string<TCHAR>; reason:
std::basic_string<TCHAR>||char[const]*[const].
#define CONS_REAS_CONCAT( conseq, reason ) conseq + _T( ":" ) + reason
typedef std::basic_string< TCHAR > stl_str;
inline void LOG( stl_str const & reason, stl_str const & conseq,
manster::logger::logger_type const & lgr_type, severity_level const &
sev_lvl, bool const & with_file_line )\
{\
if ( ( (boost::is_convertible< BOOST_TYPEOF( reason ), std::string
>::value && \
boost::is_convertible< BOOST_TYPEOF( conseq ), std::string >::value) ||\
(boost::is_convertible< BOOST_TYPEOF( reason ), std::wstring >::value && \
boost::is_convertible< BOOST_TYPEOF( conseq ), std::wstring >::value ) )
&&\
( boost::is_same< BOOST_TYPEOF( lgr_type ), manster::logger::logger_type
>::value ) &&\
( boost::is_same< BOOST_TYPEOF( sev_lvl ), severity_level >::value ) &&\
( boost::is_same< BOOST_TYPEOF( with_file_line ), bool >::value ) )\
manster::logger::instance( )->log(\
lgr_type,\
with_file_line ?\
locate_msg( CONS_REAS_CONCAT( conseq, reason ), boost::lexical_cast<
stl_tchs >( __LINE__ ), _T( __FILE__ ) ) :\
CONS_REAS_CONCAT( conseq, reason ),\
sev_lvl );\
}
///////////////////////////////////////////////////////////
// GUI LOGGING
#define LOG_GUI( reason, conseq, sev_lvl, with_file_line )\
LOG( reason, conseq, manster::logger::gui, sev_lvl, with_file_line )
#define LOG_GUI_FATAL( reason, conseq, with_file_line )\
LOG_GUI( reason, conseq, severity_level::fatal, with_file_line )
#define LOG_GUI_ERR( reason, conseq, with_file_line )\
LOG_GUI( reason, conseq, severity_level::error, with_file_line )
#define LOG_GUI_WARN( reason, conseq, with_file_line )\
LOG_GUI( reason, conseq, severity_level::warning, with_file_line )
#define LOG_GUI_INFO( reason, conseq, with_file_line )\
LOG_GUI( reason, conseq, severity_level::information, with_file_line )
///////////////////////////////////////////////////////////
// SYS LOGGING
//! System type logger used.
#define LOG_SYS( reason, conseq, sev_lvl, with_file_line )\
LOG( reason, conseq, manster::logger::sys, sev_lvl, with_file_line )
//! System type logger with fatal severity level used.
#define LOG_SYS_FATAL( reason, conseq, with_file_line )\
LOG_SYS( reason, conseq, severity_level::fatal, with_file_line )
//! System type logger with error severity level used.
#define LOG_SYS_ERR( reason, conseq, with_file_line )\
LOG_SYS( reason, conseq, severity_level::error, with_file_line )
//! System type logger with warning severity level used.
#define LOG_SYS_WARN( reason, conseq, with_file_line )\
LOG_SYS( reason, conseq, severity_level::warning, with_file_line )
//! System type logger with information severity level used.
#define LOG_SYS_INFO( reason, conseq, with_file_line )\
LOG_SYS( reason, conseq, severity_level::information, with_file_line )
///////////////////////////////////////////////////////////////
// CUSTOM LOGGING
//! System type logger with error severity level and prede used.
#define LOG_MEM_ALLOC_ERR( conseq, with_file_line )\
LOG_SYS_ERR( stl_tchs( _T( "Memory allocation failed" ) ), conseq,
with_file_line )
-- View this message in context: http://boost.2283326.n4.nabble.com/Boost-log-set-channel-name-dynamically-for-a-basic-composite-logger-tp4637012p4637366.html Sent from the Boost - Dev mailing list archive at Nabble.com.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk