mercredi 31 août 2016

Boost.log: How to prevent the output will be duplicated to all added streams when it uses the add_file_log() function?

I use the add_file_log() function to initialize a logging sink that stores log records into a text file. When I define several sinks, I have observed:

  • a file is created for each sink.
  • the output is copied to all files.

This is my logger:

class logger
{
public:
  logger(const logger&) =delete;
  logger(logger&&) =delete;
  logger& operator=(const logger&) =delete;
  logger& operator=(logger&&) =delete;

  static logger& get_instance(
    const std::string& file,
    bool console
  )
  {
      boost::log::register_simple_formatter_factory<
                                                    boost::log::trivial::severity_level,
                                                    char
                                                   >("Severity");

      std::string the_format = "[%TimeStamp%] (%LineID%) [%Severity%]: %Message%";

      if(!file.empty()) {
        boost::log::add_file_log(
          boost::log::keywords::file_name = file + "_%N.log",
          boost::log::keywords::rotation_size = 10 * 1024 * 1024,
          boost::log::keywords::time_based_rotation =
            boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
          boost::log::keywords::auto_flush = true,
          //boost::log::keywords::open_mode = (std::ios::out | std::ios::app),
          boost::log::keywords::format = the_format
        );
      }

      boost::log::add_common_attributes();
      static logger instance{ the_format, console };
      return instance;
  }

  void log(
    const std::string& msg
  )
  {
      BOOST_LOG_SEV ( m_log_, boost::log::trivial::info ) << msg;
  }

private:
  boost::log::sources::severity_logger<
                                       boost::log::trivial::severity_level
                                      > m_log_;

  logger(
    const std::string& format,
    bool console
  )
  {
      if(console) {
        boost::log::add_console_log(
          std::clog,
          boost::log::keywords::format = format
        );
      }
  }
}; // logger

This is my main() function:

void test(
  const std::string& file
)
{
  logger& lg1 = logger::get_instance( file, false );
  lg1.log( "Hello" );
  lg1.log( "World" );
  lg1.log( "Bye" );
} // test

int main()
{
  unsigned char result = EXIT_SUCCESS;

  try
  {
    std::string file1 = "a.txt",
                file2 = "b.txt";
    logger& lg = logger::get_instance( file1, false );

    for(int i = 1; i<=10; i++) {
       lg.log( std::to_string(i) );
       if(i == 5) {
         test( file2 );
       }
    }
  }
  catch ( std::exception& e )
  {
    std::cerr << "Error: " << e.what() << std::endl;
    result = EXIT_FAILURE;
  }
  return result;
}

After running the example, the files contain:

a.txt_0.log

[2016-Aug-31 11:49:48.584353] (1) [info]: 1
[2016-Aug-31 11:49:48.585376] (2) [info]: 2
[2016-Aug-31 11:49:48.585418] (3) [info]: 3
[2016-Aug-31 11:49:48.585442] (4) [info]: 4
[2016-Aug-31 11:49:48.585462] (5) [info]: 5
[2016-Aug-31 11:49:48.585505] (6) [info]: Hello  <-- 
[2016-Aug-31 11:49:48.585610] (7) [info]: World  <-- Generated by second logger
[2016-Aug-31 11:49:48.585672] (8) [info]: Bye    <--
[2016-Aug-31 11:49:48.585709] (9) [info]: 6
[2016-Aug-31 11:49:48.585744] (10) [info]: 7
[2016-Aug-31 11:49:48.585777] (11) [info]: 8
[2016-Aug-31 11:49:48.585813] (12) [info]: 9
[2016-Aug-31 11:49:48.585842] (13) [info]: 10

b.txt_0.log

[2016-Aug-31 11:49:48.585505] (6) [info]: Hello
[2016-Aug-31 11:49:48.585610] (7) [info]: World
[2016-Aug-31 11:49:48.585672] (8) [info]: Bye
[2016-Aug-31 11:49:48.585709] (9) [info]: 6    <--
[2016-Aug-31 11:49:48.585744] (10) [info]: 7   <--
[2016-Aug-31 11:49:48.585777] (11) [info]: 8   <-- Generated by the first logger
[2016-Aug-31 11:49:48.585813] (12) [info]: 9   <--
[2016-Aug-31 11:49:48.585842] (13) [info]: 10  <--

How I can prevent this behavior? I want each file only stores the information generated by its associated logger.

Aucun commentaire:

Enregistrer un commentaire