Boost logo

Boost :

From: John Torjo (john.groups_at_[hidden])
Date: 2008-01-14 13:23:30


Hi Benjamin,

Sorry for that. It's because I introduced a breaking change: after you
initialize the log, call:

g_logger->turn_cache_off();

That should do the trick.
Best,
John

> Hi John,
>
> I'm working on integrating your last modifications about flushing
> rolling files, but I encounter some problems.
>
> With version V0.11.7, I change rolling_file.hpp (see attached file) to
> flush logs each time. It works fine.
>
> /destination::rolling_file_settings settings;
> settings.file_count( 10 );
> settings.max_size_bytes( 5242880 );
> destination::rolling_file loggerFile( logFile.GetPath(), settings );
> g_logger->writer().add_destination( loggerFile );
> /
>
> With last version (revision 42765), I just add one line. /
> /
>
> /destination::rolling_file_settings settings;/
> /settings.file_count( 10 );/
> /settings.max_size_bytes( 5242880 ); /
> */=> settings.flush_each_time(true); // add this line/*
> /destination::rolling_file loggerFile( logFile.GetPath(), settings );/
> /g_logger->writer().add_destination( loggerFile );/
>
> Then it doesn't work.
> I put a break point in rolling_file_info#write but my program does not
> enter in it anymore !
> I think that rolling file objects are not instanciated because output
> files are MY_FILE.txt and not MY_FILE.txt.1
>
> Even if it will not compile alone, I give you my class Logger to see
> my implementation.
>
> Regards,
> Benjamin
>
>
> ------------------------------------------------------------------------
>
> // destination_rolling_file.hpp
>
> // Boost Logging library
> //
> // Author: John Torjo, www.torjo.com
> //
> // Copyright (C) 2007 John Torjo (see www.torjo.com for email)
> //
> // Distributed under the Boost Software License, Version 1.0.
> // (See accompanying file LICENSE_1_0.txt or copy at
> // http://www.boost.org/LICENSE_1_0.txt)
> //
> // See http://www.boost.org for updates, documentation, and revision history.
> // See http://www.torjo.com/log2/ for more details
>
>
> #ifndef JT28092007_destination_rolling_file_HPP_DEFINED
> #define JT28092007_destination_rolling_file_HPP_DEFINED
>
> #if defined(_MSC_VER) && (_MSC_VER >= 1020)
> # pragma once
> #endif
>
> #if defined(_MSC_VER)
> #pragma warning ( disable : 4355)
> #endif
>
> #include <boost/logging/detail/fwd.hpp>
> #include <boost/logging/detail/manipulator.hpp>
> #include <boost/logging/format/destination/convert_destination.hpp>
> #include <fstream>
> #include <string>
> #include <sstream>
> #include <boost/filesystem/path.hpp>
> #include <boost/filesystem/operations.hpp>
>
> namespace boost { namespace logging { namespace destination {
>
>
> /**
> @brief Settings you can pass to the rolling file. To see how it's used, see @ref dealing_with_flags.
> */
> struct rolling_file_settings {
> typedef boost::logging::detail::flag<rolling_file_settings> flag;
>
> rolling_file_settings()
> : max_size_bytes(this, 1024 * 1024)
> , file_count(this, 10)
> , initial_erase(this, false)
> , start_where_size_not_exceeded(this, true)
> {}
>
> /// maximum size in bytes, by default 1Mb
> flag::t<int> max_size_bytes;
> /// how many files has a rolling file, by default, 10
> flag::t<int> file_count;
> /// if true, it initially erases all files from the rolling file (by default, false)
> flag::t<bool> initial_erase;
> /// if true, it starts with the first file that hasn't exceeded the max size;
> /// otherwise, it starts with the first file (default = true)
> flag::t<bool> start_where_size_not_exceeded;
> };
>
> namespace detail {
> template<class convert_dest >
> struct rolling_file_info {
>
> rolling_file_info (const std::string& name_prefix, rolling_file_settings flags )
> // many thanks to Martin Bauer
> : m_name_prefix(name_prefix), m_flags(flags), m_cur_idx(0) {
> namespace fs = boost::filesystem;
>
> if ( m_flags.initial_erase()) {
> for ( int idx = 0; idx < m_flags.file_count(); ++idx)
> if ( fs::exists( file_name(idx) ))
> fs::remove( file_name(idx) );
> }
>
> // see what file to start from
> if ( m_flags.start_where_size_not_exceeded() ) {
> for ( m_cur_idx = 0; m_cur_idx < m_flags.file_count(); ++m_cur_idx )
> if ( fs::exists( file_name(m_cur_idx) )) {
> if ( fs::file_size( file_name(m_cur_idx)) < m_flags.max_size_bytes() )
> // file hasn't reached max size
> break;
> }
> else
> // file not found, we'll create it now
> break;
>
> }
>
> recreate_file();
> }
>
> std::string file_name(int idx) {
> std::ostringstream out;
> out << m_name_prefix << "." << (idx+1);
> return out.str();
> }
>
> void recreate_file() {
> m_out = boost::shared_ptr< std::basic_ofstream<char_type> >(new std::basic_ofstream<char_type>( file_name(m_cur_idx).c_str(),
> std::ios_base::out | std::ios_base::app));
> m_cur_size = 0;
> }
>
> template<class msg_type> void write( const msg_type& msg) {
> convert_dest::write(msg, (*m_out) );
>
> // bdd 2007-12-10 : flush each time
> m_cur_size += static_cast<int>( msg.size() );
> m_out->flush();
>
> // bdd
> //if ( m_out->tellp() > m_flags.max_size_bytes()) {
> if ( m_cur_size > m_flags.max_size_bytes()) {
> m_cur_idx = (m_cur_idx + 1) % m_flags.file_count();
> recreate_file();
> }
> }
>
> boost::shared_ptr< std::basic_ofstream<char_type> > m_out;
> std::string m_name_prefix;
> rolling_file_settings m_flags;
> // the index of the current file
> int m_cur_idx;
>
> // bdd 2007-12-10 : flush each time
> //size_t m_cur_size;
> int m_cur_size;
> };
> }
>
> /**
> @brief Writes to multiple files: name_prefix.1, name_prefix.2, ... name_prefix.N, and then restarts from 1.
>
> We first write to name_prefix.1.
>
> The log has a max_size. When max_size is reached, we start writing to name_prefix.2. When max_size is reached, we start writing to name_prefix.3.
> And so on, until we reach name_prefix.N (N = file_count). When that gets fool, we start over, with name_prefix.1.
> */
> template<class convert_dest = do_convert_destination > struct rolling_file_t : is_generic, non_const_context<detail::rolling_file_info<convert_dest> > {
> typedef non_const_context<detail::rolling_file_info<convert_dest> > non_const_context_base;
>
> /**
> Constructs a rolling file
>
> @param name_prefix the name to be used as prefix for the files
>
> @param flags [optional] extra settings to pass to the rolling file. See rolling_file_settings and @ref dealing_with_flags.
> */
> rolling_file_t(const std::string & name_prefix, rolling_file_settings flags = rolling_file_settings() ) : non_const_context_base(name_prefix, flags) {}
>
> template<class msg_type> void operator()( const msg_type & msg) const {
> non_const_context_base::context().write(msg);
> }
>
> bool operator==(const rolling_file_t & other) const {
> return non_const_context_base::context().m_name_prefix == other.context().m_name_prefix;
> }
> };
>
> /** @brief rolling_file_t with default values. See rolling_file_t
>
> @copydoc rolling_file_t
> */
> typedef rolling_file_t<> rolling_file;
>
>
>
>
> }}}
>
> #endif
>
>
> ------------------------------------------------------------------------
>
>
>
> //=============================================================================
> // Includes
> //=============================================================================
> #include "StdAfx.h"
> #include "common/log/Logger.h"
>
> //----- MEDCommon -----
> #include "common/system/ApplicationHelper.h"
> #include "common/io/Directory.h"
> #include "common/system/Time.h"
>
> //----- boost -----
> #pragma warning(disable: 4541)
>
> #include "boost/logging/tags.hpp"
> #include "boost/logging/defaults.hpp"
> #include "boost/logging/format.hpp"
> #include "boost/logging/format_all.hpp"
> #include "boost/logging/format_fwd.hpp"
> #include "boost/logging/format_ts.hpp"
> #include "boost/logging/logging.hpp"
> #include "boost/logging/detail/error.hpp"
> #include "boost/logging/detail/filter.hpp"
> #include "boost/logging/detail/find_gather.hpp"
> #include "boost/logging/detail/format_msg_type.hpp"
> #include "boost/logging/detail/format_write_detail.hpp"
> #include "boost/logging/detail/forward_constructor.hpp"
> #include "boost/logging/detail/fwd.hpp"
> #include "boost/logging/detail/level.hpp"
> #include "boost/logging/detail/log_keeper.hpp"
> #include "boost/logging/detail/logger.hpp"
> #include "boost/logging/detail/macros.hpp"
> #include "boost/logging/detail/manipulator.hpp"
> #include "boost/logging/detail/scenario.hpp"
> #include "boost/logging/detail/template.hpp"
> #include "boost/logging/detail/use_format_write.hpp"
> // raw_doc ?
> #include "boost/logging/detail/ts/ts.hpp"
> #include "boost/logging/detail/ts/ts_boost.hpp"
> #include "boost/logging/detail/ts/ts_none.hpp"
> //#include "boost/logging/detail/ts/ts_posix.hpp"
> #include "boost/logging/detail/ts/ts_resource.hpp"
> #include "boost/logging/detail/ts/ts_win32.hpp"
> #include "boost/logging/detail/tss/tss.hpp"
> #include "boost/logging/detail/tss/tss_ensure_proper_delete.hpp"
> #include "boost/logging/detail/tss/tss_impl.hpp"
> //#include "boost/logging/detail/tss/tss_impl_pthread.hpp"
> #include "boost/logging/detail/tss/tss_impl_win32.hpp"
> #include "boost/logging/format/array.hpp"
> #include "boost/logging/format/op_equal.hpp"
> #include "boost/logging/format/optimize.hpp"
> #include "boost/logging/format/destination/convert_destination.hpp"
> #include "boost/logging/format/destination/defaults.hpp"
> #include "boost/logging/format/destination/file.hpp"
> #include "boost/logging/format/destination/rolling_file.hpp"
> #include "boost/logging/format/destination/shared_memory.hpp"
> #include "boost/logging/format/formatter/convert_format.hpp"
> #include "boost/logging/format/formatter/defaults.hpp"
> #include "boost/logging/format/formatter/tags.hpp"
> #include "boost/logging/format/formatter/thread_id.hpp"
> #include "boost/logging/format/formatter/time.hpp"
> #include "boost/logging/gather/ostream_like.hpp"
> #include "boost/logging/tag/defaults.hpp"
> #include "boost/logging/writer/format_write.hpp"
> #include "boost/logging/writer/on_dedicated_thread.hpp"
> #include "boost/logging/writer/ts_write.hpp"
>
> using namespace boost::logging;
>
> //----- Step 3 : Specify your logging class(es) -----
> //typedef logger_format_write< > log_type;
> // thread safe
> typedef logger_format_write< default_, default_, writer::threading::ts_write > log_type;
> //typedef logger_format_write< default_, default_, writer::threading::on_dedicated_thread > log_type;
>
> //----- Step 4: declare which filters and loggers you'll use (usually in a header file) -----
> // filter
> BOOST_DECLARE_LOG_FILTER(g_log_level, level::holder )
> BOOST_DECLARE_LOG_FILTER(g_audit_filter, filter::ts )
>
> // logger
> BOOST_DECLARE_LOG(g_logger, log_type)
> BOOST_DECLARE_LOG(g_audit, log_type)
> BOOST_DECLARE_LOG(g_debug, log_type)
>
> //----- Step 5: define the macros through which you'll log -----
>
> //----- Step 6: Define the filters and loggers you'll use (usually in a source file) -----
> // filter
> BOOST_DEFINE_LOG_FILTER(g_log_level, level::holder ) // holds the application log level
> BOOST_DEFINE_LOG_FILTER(g_audit_filter, filter::ts )
> BOOST_DEFINE_LOG_FILTER(g_debug_filter, filter::ts )
> //BOOST_DEFINE_LOG_FILTER(g_audit_filter, filter::no_ts )
> // logger
> BOOST_DEFINE_LOG(g_logger, log_type)
> BOOST_DEFINE_LOG(g_audit, log_type)
> BOOST_DEFINE_LOG(g_debug, log_type)
>
> using namespace common::log;
>
> //=============================================================================
> // Global functions
> //=============================================================================
> void
> Audit( const std::ostringstream & msg )
> {
> Info( msg );
> BOOST_LOG_USE_LOG_IF_FILTER(g_audit, g_audit_filter->is_enabled() ) << "\t[AUDIT]\t" << msg.str();
> }
>
> void
> Debug( const std::ostringstream & msg )
> {
> BOOST_LOG_USE_LOG_IF_FILTER(g_debug, g_debug_filter->is_enabled() ) << "\t[DEBUG]\t" << msg.str();
> }
>
> void
> Trace2( const std::ostringstream & msg )
> {
> Debug( msg );
> common::log::Logger::s_traces.Push( msg.str() );
> }
>
> void
> Info( const std::ostringstream & msg )
> {
> BOOST_LOG_USE_LOG_IF_LEVEL(g_logger, g_log_level, info ) << "\t[INFO]\t" << msg.str();
> BOOST_LOG_USE_LOG_IF_FILTER(g_debug, g_debug_filter->is_enabled() ) << "\t[INFO]\t" << msg.str();
> }
>
> void
> Warning( const std::ostringstream & msg )
> {
> BOOST_LOG_USE_LOG_IF_LEVEL(g_logger, g_log_level, warning ) << "\t[WARN]\t" << msg.str();
> BOOST_LOG_USE_LOG_IF_FILTER(g_debug, g_debug_filter->is_enabled() ) << "\t[WARN]\t" << msg.str();
> }
>
> void
> Error( const std::ostringstream & msg )
> {
> if ( ! common::log::Logger::IsInitialized() )
> {
> common::log::Logger::Init( "INIT" );
> }
> if ( ! common::log::Logger::s_traces.IsEmpty() )
> {
> //
> vector<string> traces = common::log::Logger::s_traces.ToArray();
> for ( size_t i=0; i < traces.size(); i++ )
> {
> BOOST_LOG_USE_LOG_IF_LEVEL(g_logger, g_log_level, error ) << "\t[TRACE]\t" << traces[i];
> }
> }
> BOOST_LOG_USE_LOG_IF_LEVEL(g_logger, g_log_level, error ) << "\t[ERROR]\t" << msg.str();
> BOOST_LOG_USE_LOG_IF_FILTER(g_debug, g_debug_filter->is_enabled() ) << "\t[ERROR]\t" << msg.str();
> }
>
> void
> Exception( const std::ostringstream & msg )
> {
> if ( ! common::log::Logger::IsInitialized() )
> {
> common::log::Logger::Init( "INIT" );
> }
> if ( ! common::log::Logger::s_traces.IsEmpty() )
> {
> //
> vector<string> traces = common::log::Logger::s_traces.ToArray();
> for ( size_t i=0; i < traces.size(); i++ )
> {
> BOOST_LOG_USE_LOG_IF_LEVEL(g_logger, g_log_level, fatal ) << "\t[TRACE]\t" << traces[i];
> }
> }
> BOOST_LOG_USE_LOG_IF_LEVEL(g_logger, g_log_level, fatal ) << "\t[FATAL]\t" << msg.str();
> BOOST_LOG_USE_LOG_IF_FILTER(g_debug, g_debug_filter->is_enabled() ) << "\t[FATAL]\t" << msg.str();
> }
>
>
>
> //=============================================================================
> // Class attributs
> //=============================================================================
> bool Logger::s_isInitialized = false;
> bool Logger::MODE_DEBUG = false;
> common::container::RollingStack<string> Logger::s_traces( 15 );
>
> //=============================================================================
> // Class methods
> //=============================================================================
> void
> Logger::SetLevel( LEVEL level )
> {
> g_audit_filter->set_enabled(true);
> g_debug_filter->set_enabled(false);
> switch ( level )
> {
> case LEVEL_DEBUG :
> Logger::MODE_DEBUG = true;
> g_debug_filter->set_enabled(true);
> g_log_level->set_enabled(level::debug); // debug
> break;
> case LEVEL_INFO :
> g_log_level->set_enabled(level::info); // info + warning + ...
> break;
> case LEVEL_ERROR :
> g_log_level->set_enabled(level::error); // error + fatal + ...
> break;
> default:
> g_log_level->set_enabled(level::info);
> break;
> }
>
> }
>
> bool
> Logger::IsInitialized()
> {
> return s_isInitialized;
> }
>
> void
> Logger::Init( const string & product )
> {
> if ( s_isInitialized )
> {
> return;
> }
>
> // check log dir
> common::system::ApplicationHelper ah;
> common::io::Directory dir( ah.GetPath() + "logfiles" );
> dir.CheckAndCreate();
>
> // init file names
> //string date = common::system::Time::GetTime( common::system::Time::FORMAT_AAAA_MM_JJ );
> //common::io::File logFile( dir.GetPath() + date + "_" + product + ".txt" );
> //common::io::File auditFile( dir.GetPath() + date + "_AUDIT_" + product + ".txt" );
> common::io::File logFile( dir.GetPath() + product + ".txt" );
> common::io::File auditFile( dir.GetPath() + "AUDIT_" + product + ".txt" );
> common::io::File debugFile( dir.GetPath() + "DEBUG_" + product + ".txt" );
>
> // Step 7: add formatters and destinations
> // That is, how the message is to be formatted...
> g_logger->writer().add_formatter( formatter::time("$dd/$MM/$yyyy - $hh:$mm.$ss ") );
> g_logger->writer().add_formatter( formatter::idx() );
> g_logger->writer().add_formatter( formatter::append_newline() );
> //g_log_err->writer().add_formatter( formatter::tag::module() ); // tag::file_line() );
> //g_log_err->writer().add_formatter( formatter::tag::level() );
>
> g_audit->writer().add_formatter( formatter::time("$dd/$MM/$yyyy - $hh:$mm.$ss ") );
> g_audit->writer().add_formatter( formatter::idx() );
> g_audit->writer().add_formatter( formatter::append_newline() );
>
> g_debug->writer().add_formatter( formatter::time("$dd/$MM/$yyyy - $hh:$mm.$ss ") );
> g_debug->writer().add_formatter( formatter::idx() );
> g_debug->writer().add_formatter( formatter::append_newline() );
>
> g_logger->writer().add_destination( destination::cout() );
>
> // bdd : rolling file : pb de flush (garde les donnees en cache)
> destination::rolling_file_settings settings;
> settings.file_count( 10 );
> settings.max_size_bytes( 5242880 ); // bytes = 5M
> //settings.flush_each_time(true);
> destination::rolling_file loggerFile( logFile.GetPath(), settings );
> g_logger->writer().add_destination( loggerFile );
>
> g_debug->writer().add_destination( destination::dbg_window() );
>
> destination::rolling_file_settings settingsD;
> settingsD.file_count( 30 );
> settingsD.max_size_bytes( 10000000 ); // ~10M
> //settingsD.flush_each_time(true);
> g_debug->writer().add_destination( destination::rolling_file( debugFile.GetPath(), settingsD ) );
>
> // bdd xml : en attente
> //g_log_err->writer().add_destination( as_xml("logerror.xml") );
>
> g_audit->writer().add_destination( destination::file( auditFile.GetPath() ) );
>
> #ifdef _DEBUG
> SetLevel( Logger::LEVEL_DEBUG );
> #else
> SetLevel( Logger::LEVEL_INFO );
> #endif
> s_isInitialized = true;
> // Step 9 : Enjoy!
> }
>
>
> //=============================================================================
> // Constructor and destructor
> //=============================================================================
> Logger::Logger(void)
> : common::app::Object("common::log::Logger")
> {
> }
>
> Logger::~Logger(void)
> {
> }
>
> //=============================================================================
> // Public methods
> //=============================================================================
>
>
> ------------------------------------------------------------------------
>
> //* Step 1: (optional) Specify your format message class and/or destination message class. By default, it's std::(w)string. You'll use this when you want a optimize string class.
> //* Step 2: (optional) Specify your formatter & destination base classes
> //* Step 3: Specify your logger class(es)
> //* Step 4: Declare the filters and loggers you'll use (in a header file)
> //* Step 5: Define the macros through which you'll do logging
> //* Step 6: Define the loggers and the filters you'll use (in a source file). We need this separation (into declaring and defining the logs/filters), in order to make compilation times fast.
> //* Step 7: Add formatters and destinations. That is, how the message is to be formatted...
> //* Step 8: Use it
> //* Step 9: Enjoy the results!
>
> //* debug (smallest level),
> //* info,
> //* warning ,
> //* error ,
> //* fatal (highest level)
>
> #ifndef _COMMON_LOG_LOGGER_H_
> #define _COMMON_LOG_LOGGER_H_
> #pragma once
>
> //=============================================================================
> // Includes
> //=============================================================================
> //----- MEDCommon -----
> #include "../commonIncludes.h"
> #include "../app/Object.h"
> #include "StackLog.h"
> #include "common/txt/StringHelper.h"
> #include "common/container/RollingStack.h"
>
> void MEDCOMMON_API Audit( const std::ostringstream & msg );
> void MEDCOMMON_API Debug( const std::ostringstream & msg );
> void MEDCOMMON_API Trace2( const std::ostringstream & msg );
> void MEDCOMMON_API Info( const std::ostringstream & msg );
> void MEDCOMMON_API Warning( const std::ostringstream & msg );
> void MEDCOMMON_API Error( const std::ostringstream & msg );
> void MEDCOMMON_API Exception( const std::ostringstream & msg );
>
> #define MED_FUNCTION \
> common::log::StackLog log( __FUNCTION__ );
>
> #define MED_FUNCTION2( msg ) \
> ostringstream s; \
> s << msg; \
> common::log::StackLog log( __FUNCTION__, s );
>
> #define MED_METHOD( object ) \
> common::log::StackLog log( object,__FUNCTION__ );
>
> #define MED_METHOD2( object, params ) \
> ostringstream s; \
> s << params; \
> common::log::StackLog log( object,__FUNCTION__, s );
>
> #define MED_AUDIT( module, msg ) \
> { \
> ostringstream s; \
> s << "[" << module << "]\t" \
> << msg; \
> Audit( s ); \
> }
>
> #define MED_DBG2( module, msg ) \
> { \
> if ( common::log::Logger::MODE_DEBUG ) \
> { \
> string file = __FILE__; \
> string fileName = common::txt::StringHelper::LastToken(file,"\\"); \
> ostringstream s; \
> s << "[" << module << "]\t" \
> << msg \
> << " (" \
> << fileName \
> << "#" \
> << __FUNCTION__ \
> << " L." \
> << __LINE__ \
> << ")"; \
> Debug( s ); \
> } \
> }
>
> #define MED_TRC2( module, msg ) \
> { \
> string file = __FILE__; \
> string fileName = common::txt::StringHelper::LastToken(file,"\\"); \
> ostringstream s; \
> s << "[" << module << "]\t" \
> << msg \
> << " (" \
> << fileName \
> << "#" \
> << __FUNCTION__ \
> << " L." \
> << __LINE__ \
> << ")"; \
> Trace2( s ); \
> }
>
> #define MED_INF2( module, msg ) \
> { \
> ostringstream s; \
> s << "[" << module << "]\t" \
> << msg; \
> Info( s ); \
> }
>
> #define MED_WARN2( module, msg ) \
> { \
> string file = __FILE__; \
> string fileName = common::txt::StringHelper::LastToken(file,"\\"); \
> ostringstream s; \
> s << "[" << module << "]\t" \
> << msg \
> << " (" \
> << fileName \
> << "#" \
> << __FUNCTION__ \
> << " L." \
> << __LINE__ \
> << ")"; \
> Warning( s ); \
> }
>
> #define MED_ERR2( module, msg ) \
> { \
> string file = __FILE__; \
> string fileName = common::txt::StringHelper::LastToken(file,"\\"); \
> ostringstream s; \
> s << "[" << module << "]\t" \
> << msg \
> << " (" \
> << fileName \
> << "#" \
> << __FUNCTION__ \
> << " L." \
> << __LINE__ \
> << ")"; \
> Error( s ); \
> }
>
> #define MED_EXC2( module, msg ) \
> { \
> string file = __FILE__; \
> string fileName = common::txt::StringHelper::LastToken(file,"\\"); \
> ostringstream s; \
> s << "[" << module << "]\t" \
> << msg \
> << " (" \
> << fileName \
> << "#" \
> << __FUNCTION__ \
> << " L." \
> << __LINE__ \
> << ")"; \
> Exception( s ); \
> }
>
> namespace common
> {
> namespace log
> {
> class MEDCOMMON_API Logger : public common::app::Object
> {
>
>
>
> //=============================================================================
> // Constants
> //=============================================================================
> public:
> enum LEVEL {
> LEVEL_DEBUG ,
> LEVEL_INFO ,
> LEVEL_ERROR };
>
> //=============================================================================
> // Class attributs
> //=============================================================================
> public:
> static bool MODE_DEBUG;
> // traces
> static common::container::RollingStack<string> s_traces;
>
> private:
> static bool s_isInitialized;
>
> //=============================================================================
> // Class methods
> //=============================================================================
> public:
> static void SetProduct( const string & product );
> static bool IsInitialized();
> static void Init( const string & product );
> static void SetLevel( LEVEL level );
>
> //=============================================================================
> // Attributs
> //=============================================================================
> private:
>
>
> //=============================================================================
> // Constructor and destructor
> //=============================================================================
> private:
> Logger();
> virtual ~Logger();
>
> //=============================================================================
> // Public methods
> //=============================================================================
> public:
>
> //=============================================================================
> // Other methods
> //=============================================================================
> protected:
>
> };
> } // namespace log
> } // namespace common
>
> #endif // _COMMON_LOG_LOGGER_H_
>
>

-- 
http://John.Torjo.com -- C++ expert
... call me only if you want things done right

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk