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