00001 #include "artdaq-core/Utilities/configureMessageFacility.hh"
00002 #include "messagefacility/MessageLogger/MessageLogger.h"
00003 #if CANVAS_HEX_VERSION >= 0x20002 // art v2_07_03 means a new versions of fhicl, boost, etc
00004 # include "fhiclcpp/ParameterSet.h"
00005 # include <boost/lexical_cast.hpp>
00006 #endif
00007 #include "fhiclcpp/make_ParameterSet.h"
00008 #include "cetlib_except/exception.h"
00009 #include <boost/filesystem.hpp>
00010 #include <unistd.h>
00011 #include <fstream>
00012 #include <sstream>
00013 #define TRACE_NAME "configureMessageFacility"
00014 #include "tracemf.h"
00015
00016 namespace BFS = boost::filesystem;
00017
00018 std::string artdaq::generateMessageFacilityConfiguration(char const* progname, bool useConsole, bool printDebug)
00019 {
00020 std::string logPathProblem = "";
00021 std::string logfileName = "";
00022 char* logRootString = getenv("ARTDAQ_LOG_ROOT");
00023 char* logFhiclCode = getenv("ARTDAQ_LOG_FHICL");
00024 char* artdaqMfextensionsDir = getenv("ARTDAQ_MFEXTENSIONS_DIR");
00025 char* useMFExtensionsS = getenv("ARTDAQ_MFEXTENSIONS_ENABLED");
00026 bool useMFExtensions = false;
00027 if (useMFExtensionsS != nullptr && !(strncmp(useMFExtensionsS, "0", 1) == 0))
00028 {
00029 useMFExtensions = true;
00030 }
00031
00032 char* printTimestampsToConsoleS = getenv("ARTDAQ_LOG_TIMESTAMPS_TO_CONSOLE");
00033 bool printTimestampsToConsole = true;
00034 if (printTimestampsToConsoleS != nullptr && strncmp(printTimestampsToConsoleS, "0", 1) == 0)
00035 {
00036 printTimestampsToConsole = false;
00037 }
00038
00039 std::string logfileDir = "";
00040 if (logRootString != nullptr)
00041 {
00042 if (!BFS::exists(logRootString))
00043 {
00044 logPathProblem = "Log file root directory ";
00045 logPathProblem.append(logRootString);
00046 logPathProblem.append(" does not exist!");
00047 throw cet::exception("ConfigureMessageFacility") << logPathProblem;
00048 }
00049 else
00050 {
00051 logfileDir = logRootString;
00052 logfileDir.append("/");
00053 logfileDir.append(progname);
00054
00055
00056
00057 if (!BFS::exists(logfileDir))
00058 BFS::create_directory(logfileDir);
00059
00060 time_t rawtime;
00061 struct tm* timeinfo;
00062 char timeBuff[256];
00063 time(&rawtime);
00064 timeinfo = localtime(&rawtime);
00065 strftime(timeBuff, 256, "%Y%m%d%H%M%S", timeinfo);
00066
00067 char hostname[256];
00068 std::string hostString = "";
00069 if (gethostname(&hostname[0], 256) == 0)
00070 {
00071 std::string tmpString(hostname);
00072 hostString = tmpString;
00073 size_t pos = hostString.find(".");
00074 if (pos != std::string::npos && pos > 2)
00075 {
00076 hostString = hostString.substr(0, pos);
00077 }
00078 }
00079
00080 logfileName.append(logfileDir);
00081 logfileName.append("/");
00082 logfileName.append(progname);
00083 logfileName.append("-");
00084 if (hostString.size() > 0 && logfileName.find(hostString) == std::string::npos)
00085 {
00086 logfileName.append(hostString);
00087 logfileName.append("-");
00088 }
00089 logfileName.append(timeBuff);
00090 logfileName.append("-");
00091 logfileName.append(boost::lexical_cast<std::string>(getpid()));
00092 logfileName.append(".log");
00093 }
00094 }
00095
00096 std::ostringstream ss;
00097 ss << "debugModules:[\"*\"] "
00098 << " destinations : { ";
00099
00100 if (useConsole)
00101 {
00102 std::string outputLevel = "\"INFO\" ";
00103 if (printDebug) outputLevel = "\"DEBUG\" ";
00104 if (artdaqMfextensionsDir != nullptr && useMFExtensions)
00105 {
00106 ss << " console : { "
00107 << " type : \"ANSI\" threshold : " << outputLevel;
00108 if (!printTimestampsToConsole)
00109 {
00110 #if MESSAGEFACILITY_HEX_VERSION < 0x20103
00111 ss << " noTimeStamps : true ";
00112 #else
00113 ss << " format: { timestamp: none } ";
00114 #endif
00115 }
00116 ss << " bell_on_error: true ";
00117 ss << " } ";
00118 }
00119 else
00120 {
00121 ss << " console : { "
00122 << " type : \"cout\" threshold :" << outputLevel;
00123 if (!printTimestampsToConsole)
00124 {
00125 #if MESSAGEFACILITY_HEX_VERSION < 0x20103
00126 ss << " noTimeStamps : true ";
00127 #else
00128 ss << " format: { timestamp: none } ";
00129 #endif
00130 }
00131 ss << " } ";
00132 }
00133 }
00134
00135 if (logfileDir.size())
00136 {
00137 ss << " file: {";
00138 ss << " type: \"GenFile\" threshold: \"DEBUG\" seperator: \"-\"";
00139 ss << " pattern: \"" << progname << "-%?H%t-%p.log" << "\"";
00140 ss << " timestamp_pattern: \"%Y%m%d%H%M%S\"";
00141 ss << " directory: \"" << logfileDir << "\"";
00142 ss << " append : false";
00143 ss << " }";
00144 }
00145 #if 0 // ELF 01/17/2018 Removed because it violates the "every EVB art process must have identical configuration" rule
00146 else if (logfileName.length() > 0)
00147 {
00148 ss << " file : { "
00149 << " type : \"file\" threshold : \"DEBUG\" "
00150 << " filename : \"" << logfileName << "\" "
00151 << " append : false "
00152 << " } ";
00153 }
00154 #endif
00155
00156 if (artdaqMfextensionsDir != nullptr && useMFExtensions)
00157 {
00158 ss << " trace : { "
00159 << " type : \"TRACE\" threshold : \"DEBUG\" format:{noLineBreaks: true} lvls: 0x7 lvlm: 0xF"
00160 << " } ";
00161 }
00162
00163 if (logFhiclCode != nullptr)
00164 {
00165 std::ifstream logfhicl(logFhiclCode);
00166
00167 if (logfhicl.is_open())
00168 {
00169 std::stringstream fhiclstream;
00170 fhiclstream << logfhicl.rdbuf();
00171 ss << fhiclstream.str();
00172 }
00173 else
00174 {
00175 throw cet::exception("configureMessageFacility") << "Unable to open requested fhicl file \"" << logFhiclCode << "\".";
00176 }
00177 }
00178
00179 ss << " } ";
00180
00181 std::string pstr(ss.str());
00182
00183
00184 fhicl::ParameterSet tmp_pset;
00185 fhicl::make_ParameterSet(pstr, tmp_pset);
00186 return tmp_pset.to_string();
00187 }
00188
00189
00190 void artdaq::configureTRACE(fhicl::ParameterSet &trace_pset)
00191 {
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 std::vector<std::string> names = trace_pset.get_names();
00209 std::vector<std::string> trace_envs = {
00210 "TRACE_LIMIT_MS", "TRACE_MODE", "TRACE_NAMLVLSET" };
00211 std::unordered_map<std::string, bool> envs_set_to_unset;
00212 for (auto env : trace_envs) envs_set_to_unset[env] = false;
00213
00214 for (auto name : names)
00215 {
00216 if (name == "TRACE_NUMENTS" || name == "TRACE_ARGSMAX"
00217 || name == "TRACE_MSGMAX" || name == "TRACE_FILE")
00218
00219 setenv(name.c_str(), trace_pset.get<std::string>(name).c_str(), 0);
00220
00221 else if (name == "TRACE_LIMIT_MS")
00222 {
00223 if (!getenv(name.c_str()))
00224 {
00225 envs_set_to_unset[name] = true;
00226 std::vector<uint32_t> limit = trace_pset.get<std::vector<uint32_t>>(name);
00227
00228 std::string limits = std::to_string(limit[0]) + "," + std::to_string(limit[1]) + "," + std::to_string(limit[2]);
00229 setenv(name.c_str(), limits.c_str(), 0);
00230 }
00231 }
00232 else if (name == "TRACE_MODE")
00233 {
00234 if (!getenv(name.c_str()))
00235 {
00236 envs_set_to_unset[name] = true;
00237 setenv(name.c_str(), trace_pset.get<std::string>(name).c_str(), 0);
00238 }
00239 }
00240 else if (name == "TRACE_NAMLVLSET")
00241 {
00242 if (!getenv(name.c_str()))
00243 {
00244 envs_set_to_unset[name] = true;
00245 std::stringstream lvlsbldr;
00246 fhicl::ParameterSet lvls_pset = trace_pset.get<fhicl::ParameterSet>(name);
00247 std::vector<std::string> tnames = lvls_pset.get_names();
00248 for (auto tname : tnames)
00249 {
00250 lvlsbldr << tname;
00251 std::vector<uint64_t> msks = lvls_pset.get<std::vector<uint64_t>>(tname);
00252 for (auto msk : msks)
00253 {
00254 lvlsbldr << " 0x" << std::hex << (unsigned long long)msk;
00255 }
00256 lvlsbldr << "\n";
00257 }
00258 setenv(name.c_str(), lvlsbldr.str().c_str(), 0);
00259 }
00260 }
00261 }
00262 TRACE_CNTL("namlvlset");
00263 for (auto env : trace_envs) if (envs_set_to_unset[env]) unsetenv(env.c_str());
00264 }
00265
00266 void artdaq::configureMessageFacility(char const* progname, bool useConsole, bool printDebug)
00267 {
00268 auto pstr = generateMessageFacilityConfiguration(progname, useConsole, printDebug);
00269 fhicl::ParameterSet pset;
00270 fhicl::make_ParameterSet(pstr, pset);
00271
00272 fhicl::ParameterSet trace_pset;
00273 if (!pset.get_if_present<fhicl::ParameterSet>("TRACE", trace_pset))
00274 {
00275 fhicl::ParameterSet trace_dflt_pset;
00276 fhicl::make_ParameterSet("TRACE:{TRACE_MSGMAX:0 TRACE_LIMIT_MS:[10,500,1500]}", trace_dflt_pset);
00277 pset.put<fhicl::ParameterSet>("TRACE", trace_dflt_pset.get<fhicl::ParameterSet>("TRACE"));
00278 trace_pset = pset.get<fhicl::ParameterSet>("TRACE");
00279 }
00280 configureTRACE(trace_pset);
00281 pstr = pset.to_string();
00282 pset.erase("TRACE");
00283
00284 #if CANVAS_HEX_VERSION >= 0x30300 // art v2_11_00
00285 mf::StartMessageFacility(pset, progname);
00286
00287 #elif CANVAS_HEX_VERSION >= 0x20002 // art v2_07_03 means a new versions of fhicl, boost, etc
00288 mf::StartMessageFacility(pset);
00289
00290 mf::SetApplicationName(progname);
00291
00292 mf::setEnabledState("");
00293 # else
00294 mf::StartMessageFacility(mf::MessageFacilityService::MultiThread, pset);
00295
00296 mf::SetModuleName(progname);
00297 mf::SetContext(progname);
00298 # endif
00299 TLOG(TLVL_TRACE) << "Message Facility Config input is: " << pstr;
00300 TLOG(TLVL_INFO) << "Message Facility Application " << progname << " configured with: " << pset.to_string();
00301 }
00302
00303 std::string artdaq::setMsgFacAppName(const std::string& appType, unsigned short port)
00304 {
00305 std::string appName(appType);
00306
00307 char hostname[256];
00308 if (gethostname(&hostname[0], 256) == 0)
00309 {
00310 std::string hostString(hostname);
00311 size_t pos = hostString.find(".");
00312 if (pos != std::string::npos && pos > 2)
00313 {
00314 hostString = hostString.substr(0, pos);
00315 }
00316 appName.append("-");
00317 appName.append(hostString);
00318 }
00319
00320 appName.append("-");
00321 appName.append(boost::lexical_cast<std::string>(port));
00322
00323 mf::SetApplicationName(appName);
00324 return appName;
00325 }