4 #include "cetlib/BasicPluginFactory.h" 5 #include "cetlib/HorizontalRule.h" 6 #include "cetlib/bold_fontify.h" 7 #include "cetlib/plugin_libpath.h" 26 #include <type_traits> 30 #include <arpa/inet.h> 33 #include <netinet/in.h> 49 if (getenv(
"MF_PLUGIN_PATH") !=
nullptr) {
50 return cet::search_path{
"MF_PLUGIN_PATH"};
52 return cet::search_path{cet::plugin_libpath(), std::nothrow};
55 atomic<bool> isStarted{
false};
56 map<string const, unique_ptr<service::ELdestination>> destinations_;
57 bool cleanSlateConfiguration_{
true};
58 atomic<bool> purgeMode_{
false};
59 atomic<int> count_{0};
60 std::recursive_mutex msgMutex_{};
68 thread_local
string module_ =
"Early";
73 thread_local
string iteration_ =
"pre-events";
76 initGlobalVars(
string const& applicationName =
"")
78 char hostname[1024] = {0};
80 (gethostname(hostname, 1023) == 0) ? hostname :
"Unknown Host";
81 hostent* host =
nullptr;
82 host = gethostbyname(hostname);
83 if (host !=
nullptr) {
85 char* ip = inet_ntoa(*(
struct in_addr*)host->h_addr);
90 ifaddrs* ifAddrStruct =
nullptr;
91 if (getifaddrs(&ifAddrStruct)) {
93 hostaddr_ =
"127.0.0.1";
96 for (ifaddrs* ifa = ifAddrStruct; ifa !=
nullptr;
97 ifa = ifa->ifa_next) {
98 if (ifa->ifa_addr->sa_family == AF_INET) {
100 void* tmpAddrPtr = &((sockaddr_in*)ifa->ifa_addr)->sin_addr;
101 char addressBuffer[INET_ADDRSTRLEN];
102 inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
103 hostaddr_ = addressBuffer;
104 }
else if (ifa->ifa_addr->sa_family == AF_INET6) {
106 void* tmpAddrPtr = &((sockaddr_in6*)ifa->ifa_addr)->sin6_addr;
107 char addressBuffer[INET6_ADDRSTRLEN];
108 inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
109 hostaddr_ = addressBuffer;
112 if (!
empty(hostaddr_) && hostaddr_.compare(
"127.0.0.1") &&
113 hostaddr_.compare(
"::1")) {
117 if (
empty(hostaddr_)) {
119 hostaddr_ =
"127.0.0.1";
123 if (!
empty(applicationName)) {
124 application_ = applicationName;
128 ss <<
"//proc//" << pid_ <<
"//cmdline";
129 ifstream procfile{ss.str().c_str()};
131 if (procfile.is_open()) {
133 procfile >> procinfo;
136 auto end = procinfo.find(
'\0');
137 auto start = procinfo.find_last_of(
'/',
end);
138 application_ = procinfo.substr(start + 1,
end - start - 1);
140 pid_ =
static_cast<long>(getpid());
147 unique_ptr<service::ELdestination>
148 makePlugin_(cet::BasicPluginFactory& plugin_factory,
149 string const& libspec,
150 string const& psetname,
153 unique_ptr<service::ELdestination> result;
155 auto const pluginType = plugin_factory.pluginType(libspec);
159 plugin_factory.makePlugin<unique_ptr<service::ELdestination>>(
160 libspec, psetname, pset);
163 <<
"unrecognized plugin type " << pluginType <<
"for plugin " 169 <<
"Exception caught while processing plugin spec.\n";
174 string const default_destination_config_string =
" type: cerr" 181 default_destination_config()
187 default_destination_set_config()
189 string const config{
"cerr: { "s + default_destination_config_string +
197 map<
string const, unique_ptr<service::ELdestination>>& destinations)
208 if (msg.
xid().
pid() == 0) {
211 if (
empty(destinations)) {
212 cerr <<
"\nERROR LOGGED WITHOUT DESTINATION!\nAttaching destination " 213 "\"cerr\" by default\n\n";
214 destinations.emplace(
216 make_unique<service::ELostreamOutput>(
217 default_destination_set_config(), cet::ostream_handle{cerr}));
219 for (
auto& destid_and_destination : destinations) {
220 destid_and_destination.second->log(msg);
226 cet::BasicPluginFactory& plugin_factory,
230 vector<string> config_errors;
233 if (dest_pset.is_empty()) {
234 dest_pset = default_destination_config();
238 if (!dest_pset.get_if_present(
"type", dest_type)) {
240 <<
"No 'type' specified for destination '" << psetname <<
"'.\n";
242 if (configuration == destination_kind::statistics) {
243 if ((dest_type !=
"cout"s) && (dest_type !=
"cerr"s) &&
244 (dest_type !=
"file"s)) {
247 <<
"Unsupported type [ " << dest_type
248 <<
" ] chosen for statistics printout.\n" 249 <<
"Must choose ostream type: \"cout\", \"cerr\", or \"file\"" 253 string outputId{dest_type};
254 if ((dest_type !=
"cout"s) && (dest_type !=
"cerr"s) &&
255 (dest_type !=
"syslog"s)) {
256 outputId +=
":" + dest_pset.get<
string>(
"filename", psetname);
258 if (!ids.emplace(outputId).second) {
260 if (configuration == destination_kind::statistics) {
262 <<
" Output identifier: \"" << outputId <<
"\"" 263 <<
" already specified within ordinary/statistics block in FHiCL " 268 auto iter_id_dest = destinations_.find(outputId);
269 if (iter_id_dest != destinations_.end()) {
270 constexpr cet::HorizontalRule rule{76};
271 string const hrule{
'\n' + rule(
'=') +
'\n'};
272 ostringstream except_msg;
273 except_msg << hrule <<
"\n Duplicate name for a ";
274 if (configuration == destination_kind::ordinary) {
275 except_msg <<
"MessageLogger";
277 except_msg <<
"MessageLogger Statistics";
279 except_msg <<
" destination: \"" << outputId <<
'"';
280 ostringstream orig_config_msg;
282 <<
"\n Only original configuration instructions are used. \n" 284 if (cleanSlateConfiguration_) {
286 << except_msg.str() << orig_config_msg.str();
289 << except_msg.str() << orig_config_msg.str();
293 string const& libspec = dest_type;
295 destinations_[outputId] =
296 makePlugin_(plugin_factory, libspec, psetname, dest_pset);
299 string msg{
"Configuration error for destination: " +
300 cet::bold_fontify(psetname) +
"\n\n"};
302 config_errors.push_back(std::move(msg));
305 if (!
empty(config_errors)) {
306 string msg{
"\nThe following messagefacility destinations have " 307 "configuration errors:\n\n"};
308 constexpr cet::HorizontalRule rule{60};
311 auto start =
cbegin(config_errors);
314 for (
auto it = start,
e =
cend(config_errors); it !=
e; ++it) {
327 cet::BasicPluginFactory& pluginFactory,
328 cet::BasicPluginFactory& pluginStatsFactory)
330 if (destinations_.size() > 1) {
332 <<
"The message logger has been configured multiple times";
333 cleanSlateConfiguration_ =
false;
338 dest_psets = default_destination_set_config();
340 ordinaryDests = dest_psets;
341 ordinaryDests.
erase(
"statistics");
347 string const default_config{
"file_stats: {\n" 349 " filename: \"err.log\"\n" 350 " threshold: WARNING\n" 354 makeDestinations(ordinaryDests, pluginFactory, destination_kind::ordinary);
356 "statistics", default_statistics_config);
357 makeDestinations(statDests, pluginStatsFactory, destination_kind::statistics);
368 std::lock_guard sentry{msgMutex_};
371 unique_ptr<ErrorObj> msgHolder{msg};
373 sendMsgToDests(*msg, destinations_);
377 cerr <<
"MessageLoggerScribe caught " << count_
378 <<
" cet::exceptions, text = \n" 381 cerr <<
"MessageLogger will no longer be processing messages due to " 382 "errors (entering purge mode).\n";
387 cerr <<
"MessageLoggerScribe caught an unknown exception and will no " 388 "longer be processing messages. (entering purge mode)\n";
396 for (
auto& destid_and_dest : destinations_) {
397 auto& dest = *destid_and_dest.second;
402 cerr <<
"MessageLoggerScribe caught exception during summarize:\n" 406 cerr <<
"MessageLoggerScribe caught unknown exception type during " 407 "summarize. (Ignored)\n";
416 return isStarted.load();
423 if (isStarted.load()) {
446 if (isStarted.load()) {
459 string const& applicationName)
461 if (isStarted.load()) {
465 cet::BasicPluginFactory pluginFactory{getPluginPath(),
"mfPlugin"};
466 cet::BasicPluginFactory pluginStatsFactory{getPluginPath(),
471 initGlobalVars(applicationName);
473 destinations_[
"cerr_early"s] = makePlugin_(
474 pluginFactory,
"cerr",
"cerr_early", default_destination_config());
477 string msg{
"\nConfiguration error for destination: " +
478 cet::bold_fontify(
"cerr_early") +
"\n\n"};
494 "Exception from MessageLoggerScribe::configure",
497 isStarted.store(
true);
504 isStarted.store(
false);
507 for (
auto& category_and_destination : destinations_) {
508 category_and_destination.second->finish();
516 application_ = applicationName;
523 hostname_ = hostname;
530 hostaddr_ = hostaddr;
649 if (isStarted.load()) {
fhicl::OptionalDelegatedParameter destinations
ELseverityLevel severity() const
void SetIteration(string const &val)
std::optional< T > get_if_present() const
void SetHostAddr(string const &hostaddr)
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
void EndMessageFacility()
static ParameterSet make(intermediate_table const &tbl)
std::string const & application() const
virtual void setPID(long)
string const & GetModuleName()
static struct mf::FinalShutdown ensureShutdown
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
ELslProxy< ELhighestSeverityGen > constexpr ELhighestSeverity
virtual void setHostName(std::string const &)
void SetContextIteration(string const &val)
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
std::string const & idOverflow() const
bool isMessageProcessingSetUp()
std::vector< std::string > get_pset_names() const
void StartMessageFacility(fhicl::ParameterSet const &pset, string const &applicationName)
std::string const & hostaddr() const
ELextendedID const & xid() const
cet::coded_exception< errors::error, detail::translate > Exception
T get(std::string const &key) const
virtual void setHostAddr(std::string const &)
std::string const & id() const
std::string fullText() const
virtual void setApplication(std::string const &)
void SetHostName(string const &hostname)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
string const & GetHostName()
char const * what() const noexcept override
string const & GetIteration()
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void SetContextSinglet(string const &val)
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
virtual void setReactedTo(bool)
bool erase(std::string const &key)
void LogErrorObj(ErrorObj *msg)
void SetModuleName(string const &val)
void SetApplicationName(string const &applicationName)
std::string const & hostname() const
void SetPid(long const pid)
cet::coded_exception< error, detail::translate > exception
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
std::string getSymbol() const
string const & GetApplicationName()
string const & GetHostAddr()