Skip to content

Commit 5b941a1

Browse files
authored
Merge pull request mtconnect#498 from mtconnect/use_boost_log_channel
2 parents ccb0e40 + 103949c commit 5b941a1

File tree

7 files changed

+151
-106
lines changed

7 files changed

+151
-106
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
set(AGENT_VERSION_MAJOR 2)
33
set(AGENT_VERSION_MINOR 4)
44
set(AGENT_VERSION_PATCH 0)
5-
set(AGENT_VERSION_BUILD 5)
5+
set(AGENT_VERSION_BUILD 6)
66
set(AGENT_VERSION_RC "")
77

88
# This minimum version is to support Visual Studio 2019 and C++ feature checking and FetchContent

conanfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
class MTConnectAgentConan(ConanFile):
1111
name = "mtconnect_agent"
12-
version = "2.3"
12+
version = "2.4"
1313
url = "https://github.com/mtconnect/cppagent.git"
1414
license = "Apache License 2.0"
1515
settings = "os", "compiler", "arch", "build_type"

src/mtconnect/configuration/agent_config.cpp

Lines changed: 99 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,6 @@ BOOST_LOG_ATTRIBUTE_KEYWORD(named_scope, "Scope", logr::attributes::named_scope:
101101
BOOST_LOG_ATTRIBUTE_KEYWORD(utc_timestamp, "Timestamp", logr::attributes::utc_clock::value_type);
102102

103103
namespace 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

Comments
 (0)