@@ -101,8 +101,6 @@ BOOST_LOG_ATTRIBUTE_KEYWORD(named_scope, "Scope", logr::attributes::named_scope:
101101BOOST_LOG_ATTRIBUTE_KEYWORD (utc_timestamp, " Timestamp" , logr::attributes::utc_clock::value_type);
102102
103103namespace mtconnect ::configuration {
104- AGENT_LIB_API
105- boost::log::trivial::logger_type *gAgentLogger = nullptr ;
106104
107105 AgentConfiguration::AgentConfiguration ()
108106 : m_context {make_unique<AsyncContext>()}, m_monitorTimer(m_context->get ())
@@ -235,8 +233,10 @@ namespace mtconnect::configuration {
235233#endif
236234 m_context.reset ();
237235
238- if (m_sink)
239- m_sink.reset ();
236+ for (auto &[channelName, logChannel] : m_logChannels)
237+ logChannel.m_logSink .reset ();
238+
239+ m_logChannels.clear ();
240240
241241 logr::core::get ()->remove_all_sinks ();
242242 }
@@ -432,9 +432,8 @@ namespace mtconnect::configuration {
432432
433433 void AgentConfiguration::setLoggingLevel (const logr::trivial::severity_level level)
434434 {
435- using namespace logr ::trivial;
436- m_logLevel = level;
437- logr::core::get ()->set_filter (severity >= level);
435+ for ( auto &[channelName, logChannel] : m_logChannels)
436+ logChannel.m_logLevel = level;
438437 }
439438
440439 static logr::trivial::severity_level StringToLogLevel (const std::string &level)
@@ -476,25 +475,54 @@ namespace mtconnect::configuration {
476475 void AgentConfiguration::configureLogger (const ptree &config)
477476 {
478477 using namespace logr ::trivial;
479- namespace kw = boost::log::keywords;
480478 namespace expr = logr::expressions;
481479
482- logr::core::get ()->remove_all_sinks ();
483- m_sink.reset ();
480+ auto core = logr::core::get ();
481+
482+ core->remove_all_sinks ();
484483
485484 // // Add the commonly used attributes; includes TimeStamp, ProcessID and ThreadID and others
486485 logr::add_common_attributes ();
487- logr:: core::get () ->add_global_attribute (" Scope" , logr::attributes::named_scope ());
488- logr:: core::get () ->add_global_attribute (logr::aux::default_attribute_names::thread_id (),
486+ core->add_global_attribute (" Scope" , logr::attributes::named_scope ());
487+ core->add_global_attribute (logr::aux::default_attribute_names::thread_id (),
489488 logr::attributes::current_thread_id ());
490- logr::core::get ()->add_global_attribute (" Timestamp" , logr::attributes::utc_clock ());
489+ core->add_global_attribute (" Timestamp" , logr::attributes::utc_clock ());
490+
491+ m_logger = &::boost::log::trivial::logger::get ();
492+
493+ auto formatter =
494+ expr::stream << expr::format_date_time<boost::posix_time::ptime>(" Timestamp" ,
495+ " %Y-%m-%dT%H:%M:%S.%fZ " )
496+ << " ("
497+ << expr::attr<logr::attributes::current_thread_id::value_type>(" ThreadID" )
498+ << " ) [" << severity << " ] " << named_scope << " : " << expr::smessage;
499+
500+ configureLoggerChannel (" agent" , config, formatter);
501+ }
502+
503+ void AgentConfiguration::configureLoggerChannel (const std::string &channelName, const ptree &config, std::optional<boost::log::basic_formatter<char >> formatter)
504+ {
505+ using namespace logr ::trivial;
506+ namespace expr = logr::expressions;
507+ namespace kw = boost::log::keywords;
508+
509+ auto &logChannel = m_logChannels[channelName];
510+ if (logChannel.m_channelName == " " )
511+ logChannel.m_channelName = channelName;
512+
513+ if (!formatter)
514+ {
515+ formatter =
516+ expr::stream << expr::format_date_time<boost::posix_time::ptime>(" Timestamp" ,
517+ " %Y-%m-%dT%H:%M:%S.%fZ " )
518+ << std::setw (7 ) << std::left << boost::log::trivial::severity << " " << expr::message;
519+ }
491520
492521 ptree empty;
493522 auto logger = config.get_child_optional (" logger_config" ).value_or (empty);
494- setLoggingLevel (severity_level::info);
495523
496- static const string defaultFileName { " agent .log" } ;
497- static const string defaultArchivePattern ( " agent_ %Y-%m-%d_%H-%M-%S_%N.log" ) ;
524+ const string defaultFileName = channelName + " .log" ;
525+ const string defaultArchivePattern = channelName + " _ %Y-%m-%d_%H-%M-%S_%N.log" ;
498526
499527 ConfigOptions options;
500528 AddDefaultedOptions (logger, options,
@@ -507,19 +535,10 @@ namespace mtconnect::configuration {
507535 {{" output" , string ()}, {" level" , string ()}, {" logging_level" , string ()}});
508536
509537 auto output = GetOption<string>(options, " output" );
510- auto level = setLoggingLevel (
538+ auto level = StringToLogLevel (
511539 GetOption<string>(options, " level" )
512540 .value_or (GetOption<string>(options, " logging_level" ).value_or (" info" s)));
513541
514- gAgentLogger = m_logger = &::boost::log::trivial::logger::get ();
515-
516- auto formatter =
517- expr::stream << expr::format_date_time<boost::posix_time::ptime>(" Timestamp" ,
518- " %Y-%m-%dT%H:%M:%S.%fZ " )
519- << " ("
520- << expr::attr<logr::attributes::current_thread_id::value_type>(" ThreadID" )
521- << " ) [" << severity << " ] " << named_scope << " : " << expr::smessage;
522-
523542 if (m_isDebug || (output && (*output == " cout" || *output == " cerr" )))
524543 {
525544 ostream *out;
@@ -528,11 +547,21 @@ namespace mtconnect::configuration {
528547 else
529548 out = &std::cout;
530549
531- logr::add_console_log (*out, kw::format = formatter, kw::auto_flush = true );
532-
533550 if (m_isDebug && level >= severity_level::debug)
534- setLoggingLevel (severity_level::debug);
551+ level = severity_level::debug;
552+
553+ auto sink = boost::make_shared<console_sink>();
554+ logChannel.m_logSink = sink;
555+ logChannel.m_logLevel = level;
556+ logChannel.m_logFileName = output.value_or (" debug" );
557+
558+ sink->locked_backend ()->add_stream (boost::shared_ptr<std::ostream>(out, boost::null_deleter ()));
559+ sink->locked_backend ()->auto_flush (true );
560+
561+ sink->set_formatter (formatter.value ());
562+ sink->set_filter (expr::attr<std::string>(" Channel" ) == logChannel.m_channelName && severity >= logChannel.m_logLevel );
535563
564+ logr::core::get ()->add_sink (sink);
536565 return ;
537566 }
538567
@@ -560,16 +589,23 @@ namespace mtconnect::configuration {
560589 }
561590 }
562591
563- m_maxLogFileSize = ConvertFileSize (options, " max_size" , m_maxLogFileSize);
564- m_logRotationSize = ConvertFileSize (options, " rotation_size" , m_logRotationSize);
592+ auto &maxLogFileSize = logChannel.m_maxLogFileSize ;
593+ auto &logRotationSize = logChannel.m_logRotationSize ;
594+ auto &rotationLogInterval = logChannel.m_rotationLogInterval ;
595+ auto &logArchivePattern = logChannel.m_logArchivePattern ;
596+ auto &logDirectory = logChannel.m_logDirectory ;
597+ auto &logFileName = logChannel.m_logFileName ;
598+
599+ maxLogFileSize = ConvertFileSize (options, " max_size" , maxLogFileSize);
600+ logRotationSize = ConvertFileSize (options, " rotation_size" , logRotationSize);
565601 int max_index = *GetOption<int >(options, " max_index" );
566602
567603 if (auto sched = GetOption<string>(options, " schedule" ))
568604 {
569605 if (*sched == " DAILY" )
570- m_rotationLogInterval = 24 ;
606+ rotationLogInterval = 24 ;
571607 else if (*sched == " WEEKLY" )
572- m_rotationLogInterval = 168 ;
608+ rotationLogInterval = 168 ;
573609 else if (*sched != " NEVER" )
574610 LOG (error) << " Invalid schedule value." ;
575611 }
@@ -578,52 +614,55 @@ namespace mtconnect::configuration {
578614 auto file_name = *GetOption<string>(options, " file_name" );
579615 auto archive_pattern = *GetOption<string>(options, " archive_pattern" );
580616
581- m_logArchivePattern = fs::path (archive_pattern);
582- if (!m_logArchivePattern .has_filename ())
617+ logArchivePattern = fs::path (archive_pattern);
618+ if (!logArchivePattern .has_filename ())
583619 {
584- m_logArchivePattern =
585- m_logArchivePattern / archiveFileName (get<string>(options[" file_name" ]));
620+ logArchivePattern =
621+ logArchivePattern / archiveFileName (get<string>(options[" file_name" ]));
586622 }
587623
588- if (m_logArchivePattern .is_relative ())
589- m_logArchivePattern = fs::current_path () / m_logArchivePattern ;
624+ if (logArchivePattern .is_relative ())
625+ logArchivePattern = fs::current_path () / logArchivePattern ;
590626
591627 // Get the log directory from the archive path.
592- m_logDirectory = m_logArchivePattern .parent_path ();
628+ logDirectory = logArchivePattern .parent_path ();
593629
594630 // If the file name does not specify a log directory, use the
595631 // archive directory
596- m_logFileName = fs::path (file_name);
597- if (!m_logFileName.has_parent_path ())
598- m_logFileName = m_logDirectory / m_logFileName;
599- else if (m_logFileName.is_relative ())
600- m_logFileName = fs::current_path () / m_logFileName;
601-
602- boost::shared_ptr<logr::core> core = logr::core::get ();
632+ logFileName = fs::path (file_name);
633+ if (!logFileName.has_parent_path ())
634+ logFileName = logDirectory / logFileName;
635+ else if (logFileName.is_relative ())
636+ logFileName = fs::current_path () / logFileName;
603637
604638 // Create a text file sink
605- m_sink = boost::make_shared<text_sink>(
606- kw::file_name = m_logFileName , kw::target_file_name = m_logArchivePattern .filename (),
607- kw::auto_flush = true , kw::rotation_size = m_logRotationSize ,
639+ auto sink = boost::make_shared<text_sink>(
640+ kw::file_name = logFileName , kw::target_file_name = logArchivePattern .filename (),
641+ kw::auto_flush = true , kw::rotation_size = logRotationSize ,
608642 kw::open_mode = ios_base::out | ios_base::app, kw::format = formatter);
609643
644+ logChannel.m_logSink = sink;
645+ logChannel.m_logLevel = level;
646+
610647 // Set up where the rotated files will be stored
611- m_sink ->locked_backend ()->set_file_collector (logr::sinks::file::make_collector (
612- kw::target = m_logDirectory , kw::max_size = m_maxLogFileSize , kw::max_files = max_index));
648+ sink ->locked_backend ()->set_file_collector (logr::sinks::file::make_collector (
649+ kw::target = logDirectory , kw::max_size = maxLogFileSize , kw::max_files = max_index));
613650
614- if (m_rotationLogInterval > 0 )
651+ if (rotationLogInterval > 0 )
615652 {
616- m_sink ->locked_backend ()->set_time_based_rotation (
653+ sink ->locked_backend ()->set_time_based_rotation (
617654 logr::sinks::file::rotation_at_time_interval (
618- boost::posix_time::hours (m_rotationLogInterval )));
655+ boost::posix_time::hours (rotationLogInterval )));
619656 }
620657
621658 // Upon restart, scan the target directory for files matching the file_name pattern
622- m_sink->locked_backend ()->scan_for_files ();
623- m_sink->set_formatter (formatter);
659+ sink->locked_backend ()->scan_for_files ();
660+
661+ sink->set_formatter (formatter.value ());
662+ sink->set_filter (expr::attr<std::string>(" Channel" ) == logChannel.m_channelName && severity >= logChannel.m_logLevel );
624663
625664 // Formatter for the logger
626- core->add_sink (m_sink );
665+ logr:: core::get () ->add_sink (sink );
627666 }
628667
629668 static std::string ExpandValue (const std::map<std::string, std::string> &values,
@@ -736,8 +775,8 @@ namespace mtconnect::configuration {
736775 cerr << " could not load config file: " << e.what () << endl;
737776 throw e;
738777 }
739- // if (!m_loggerFile)
740- if (!m_sink )
778+
779+ if (m_logChannels. empty () )
741780 {
742781 configureLogger (config);
743782 }
0 commit comments