$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_04_20a
$projectbrief
|
$projectbrief
|
$searchbox |
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" // TRACE_CNTL, TRACE 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 // As long as the top-level directory exists, I don't think we 00055 // really care if we have to create application directories... 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 //Canonicalize string: 00175 fhicl::ParameterSet tmp_pset; 00176 fhicl::make_ParameterSet(pstr, tmp_pset); 00177 return tmp_pset.to_string(); 00178 } 00179 // generateMessageFacilityConfiguration 00180 00181 void artdaq::configureTRACE(fhicl::ParameterSet &trace_pset) 00182 { 00183 /* The following code handles this example fhicl: 00184 TRACE:{ 00185 TRACE_NUMENTS:500000 00186 TRACE_ARGSMAX:10 00187 TRACE_MSGMAX:0 00188 TRACE_FILE:"/tmp/trace_buffer_%u" # this is the default 00189 TRACE_LIMIT_MS:[8,80,800] 00190 TRACE_MODE:0xf 00191 TRACE_NAMLVLSET:{ 00192 #name:[lvlsmskM,lvlsmskS[,lvlsmskT]] lvlsmskT is optional 00193 name0:[0x1f,0x7] 00194 name1:[0x2f,0xf] 00195 name2:[0x3f,0x7,0x1] 00196 } 00197 } 00198 */ 00199 std::vector<std::string> names = trace_pset.get_names(); 00200 std::vector<std::string> trace_envs = {//"TRACE_NUMENTS", "TRACE_ARGSMAX", "TRACE_MSGMAX", "TRACE_FILE", 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 // tricky - some env. vars. will over ride info in "mapped" (file) context while others cannot. 00205 for (auto name : names) 00206 { 00207 if (name == "TRACE_NUMENTS" || name == "TRACE_ARGSMAX" 00208 || name == "TRACE_MSGMAX" || name == "TRACE_FILE") // only applicable if env.var. set before before traceInit 00209 // don't override and don't "set_to_unset" (if "mapping", want any subprocess to map also) 00210 setenv(name.c_str(), trace_pset.get<std::string>(name).c_str(), 0); 00211 // These next 3 are looked at when TRACE_CNTL("namlvlset") is called. And, if mapped, get into file! (so may want to unset env???) 00212 else if (name == "TRACE_LIMIT_MS") 00213 { // there is also TRACE_CNTL 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 // could check that it is size()==3??? 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 { // env.var. only applicable if TRACE_NAMLVLSET is set, BUT could TRACE_CNTL("mode",mode)??? 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; // levels builder 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); // 0 means: won't overwrite 00250 } 00251 } 00252 } 00253 TRACE_CNTL("namlvlset"); // acts upon env.var. 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 }