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