Boost logo

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