$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_04_11
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #define TRACE_NAME "GenFileOutput" 00002 00003 #include "cetlib/PluginTypeDeducer.h" 00004 #include "cetlib/ostream_handle.h" 00005 #include "cetlib/ProvideMakePluginMacros.h" 00006 #include "fhiclcpp/ParameterSet.h" 00007 00008 #include "boost/date_time/posix_time/posix_time.hpp" 00009 00010 #include "messagefacility/MessageService/ELdestination.h" 00011 # include "messagefacility/Utilities/ELseverityLevel.h" 00012 #include "messagefacility/Utilities/exception.h" 00013 00014 #include <fstream> 00015 #include "trace.h" 00016 00017 namespace mfplugins 00018 { 00019 using mf::service::ELdestination; 00020 using mf::ELseverityLevel; 00021 using mf::ErrorObj; 00022 00027 class ELGenFileOutput : public ELdestination 00028 { 00029 struct Config 00030 { 00031 fhicl::TableFragment<ELdestination::Config> elDestConfig; 00032 fhicl::Atom<bool> append{ fhicl::Name{"append"},fhicl::Comment {"Whether to append to the file or recreate it"},true }; 00033 fhicl::Atom<std::string> baseDir{ fhicl::Name{"directory"},fhicl::Comment{"The directory into which files will be saved"},"/tmp" }; 00034 fhicl::Atom<std::string> sep{ fhicl::Name{"seperator"},fhicl::Comment{"Separator to use after optional replacement parameters"}, "-" }; 00035 fhicl::Atom<std::string> timePattern{ fhicl::Name{"timestamp_pattern"},fhicl::Comment{"Pattern to use for %t strftime replacement"},"%Y%m%d%H%M%S" }; 00036 fhicl::Atom<std::string> filePattern{ fhicl::Name{ "pattern" },fhicl::Comment{ "Pattern to use for file naming.\n" 00037 " Supported parameters are:\n" 00038 " %%: Print a % sign\n" 00039 " %N: Print the executable name, as retrieved from /proc/<pid>/exe\n" 00040 " %?N: Print the executable name only if it does not already appear in the parsed format. Format is parsed left-to-right.\n" 00041 " These options add a seperator AFTER if they are filled and if they are not the last token in the file pattern, before the last '.' character.\n" 00042 " %H: Print the hostname, without any domain specifiers (i.e. work.fnal.gov will become work)\n" 00043 " %?H: Print the hostname only if it does not already appear in the parsed format.\n" 00044 " %p: Print the PID of the application configuring MessageFacility\n" 00045 " %t: Print the timestamp using the format specified by timestamp_pattern\n" 00046 " %T: Print the timestamp in ISO format" 00047 },"%N-%?H%t-%p.log" }; 00048 00049 00050 }; 00051 using Parameters = fhicl::WrappedTable<Config>; 00052 00053 public: 00058 ELGenFileOutput(Parameters const& pset); 00059 00061 virtual ~ELGenFileOutput() {} 00062 00068 virtual void routePayload(const std::ostringstream& o, const ErrorObj& e) override; 00069 00073 virtual void flush() override; 00074 00075 private: 00076 std::unique_ptr<cet::ostream_handle> output_; 00077 }; 00078 00079 // END DECLARATION 00080 //====================================================================== 00081 // BEGIN IMPLEMENTATION 00082 00083 00084 //====================================================================== 00085 // ELGenFileOutput c'tor 00086 //====================================================================== 00087 00088 ELGenFileOutput::ELGenFileOutput(Parameters const& pset) : ELdestination(pset().elDestConfig()) 00089 { 00090 bool append = pset().append(); 00091 std::string baseDir = pset().baseDir(); 00092 std::string sep = pset().sep(); 00093 std::string timePattern = pset().timePattern(); 00094 std::string filePattern = pset().filePattern(); 00095 00096 auto pid = getpid(); 00097 std::string exeString = ""; 00098 std::string hostString = ""; 00099 std::string timeBuffISO = ""; // Using boost::posix_time::to_iso_string (%T) 00100 std::string timeBuff = ""; // Using timestamp_pattern (%t) 00101 00102 00103 // Determine image name 00104 if (filePattern.find("%N") != std::string::npos || filePattern.find("%?N") != std::string::npos) 00105 { 00106 // get process name from '/proc/pid/exe' 00107 std::string exe; 00108 std::ostringstream pid_ostr; 00109 pid_ostr << "/proc/" << pid << "/exe"; 00110 exe = std::string(realpath(pid_ostr.str().c_str(), NULL)); 00111 00112 size_t end = exe.find('\0'); 00113 size_t start = exe.find_last_of('/', end); 00114 exeString = exe.substr(start + 1, end - start - 1); 00115 } 00116 00117 // Get Host name 00118 if (filePattern.find("%H") != std::string::npos || filePattern.find("%?H") != std::string::npos) 00119 { 00120 char hostname[256]; 00121 if (gethostname(&hostname[0], 256) == 0) 00122 { 00123 std::string tmpString(hostname); 00124 hostString = tmpString; 00125 size_t pos = hostString.find("."); 00126 if (pos != std::string::npos && pos > 2) 00127 { 00128 hostString = hostString.substr(0, pos); 00129 } 00130 } 00131 } 00132 if (filePattern.find("%T") != std::string::npos) 00133 { 00134 timeBuffISO = boost::posix_time::to_iso_string(boost::posix_time::second_clock::universal_time()); 00135 } 00136 if (filePattern.find("%t") != std::string::npos) 00137 { 00138 00139 time_t rawtime; 00140 struct tm* timeinfo; 00141 char timeBuffC[256]; 00142 time(&rawtime); 00143 timeinfo = localtime(&rawtime); 00144 strftime(timeBuffC, 256, timePattern.c_str(), timeinfo); 00145 timeBuff = std::string(timeBuffC); 00146 } 00147 00148 size_t pos = 0; 00149 TLOG(TLVL_DEBUG) << "filePattern is: " << filePattern; 00150 while (filePattern.find("%", pos) != std::string::npos) 00151 { 00152 pos = filePattern.find("%", pos) + 1; 00153 TLOG(5,1) << "Found % at " << (pos - 1) << ", next char: " << filePattern[pos] << "."; 00154 switch (filePattern[pos]) 00155 { 00156 case '%': // "%%" 00157 filePattern = filePattern.replace(pos - 1, 2, "%"); 00158 pos--; 00159 break; 00160 case '?': 00161 { 00162 char next = filePattern[pos + 1]; 00163 switch (next) 00164 { 00165 case 'N': 00166 if (filePattern.find(exeString) != std::string::npos) 00167 { 00168 filePattern = filePattern.erase(pos - 1, 3); 00169 } 00170 else 00171 { 00172 std::string repString = exeString; 00173 // Only append separator if we're not at the end of the pattern 00174 if (!(pos + 1 == filePattern.size() - 1 || pos + 2 == filePattern.find_last_of('.'))) 00175 { 00176 repString += sep; 00177 } 00178 filePattern = filePattern.replace(pos - 1, 3, repString); 00179 } 00180 break; 00181 case 'H': 00182 if (filePattern.find(hostString) != std::string::npos) 00183 { 00184 filePattern = filePattern.erase(pos - 1, 3); 00185 } 00186 else 00187 { 00188 std::string repString = hostString; 00189 // Only append separator if we're not at the end of the pattern 00190 if (!(pos + 1 == filePattern.size() - 1 || pos + 2 == filePattern.find_last_of('.'))) 00191 { 00192 repString += sep; 00193 } 00194 filePattern = filePattern.replace(pos - 1, 3, repString); 00195 break; 00196 } 00197 } 00198 pos -= 3; 00199 } 00200 break; 00201 case 'N': 00202 filePattern = filePattern.replace(pos - 1, 2, exeString); 00203 pos -= 2; 00204 break; 00205 case 'H': 00206 filePattern = filePattern.replace(pos - 1, 2, hostString); 00207 pos -= 2; 00208 break; 00209 case 'p': 00210 filePattern = filePattern.replace(pos - 1, 2, std::to_string(pid)); 00211 pos -= 2; 00212 break; 00213 case 't': 00214 filePattern = filePattern.replace(pos - 1, 2, timeBuff); 00215 pos -= 2; 00216 break; 00217 case 'T': 00218 filePattern = filePattern.replace(pos - 1, 2, timeBuffISO); 00219 pos -= 2; 00220 break; 00221 } 00222 TLOG(6) << "filePattern is now: " << filePattern; 00223 } 00224 std::string fileName = baseDir + "/" + filePattern; 00225 TLOG(TLVL_DEBUG) << "fileName is: " << fileName; 00226 00227 output_ = std::make_unique<cet::ostream_handle>(fileName.c_str(), append ? std::ios::app : std::ios::trunc); 00228 } 00229 00230 //====================================================================== 00231 // Message router ( overriddes ELdestination::routePayload ) 00232 //====================================================================== 00233 void ELGenFileOutput::routePayload(const std::ostringstream& oss, const ErrorObj& 00234 ) 00235 { 00236 *output_ << oss.str(); 00237 flush(); 00238 } 00239 00240 void ELGenFileOutput::flush() 00241 { 00242 output_->flush(); 00243 } 00244 } // end namespace mfplugins 00245 00246 //====================================================================== 00247 // 00248 // makePlugin function 00249 // 00250 //====================================================================== 00251 00252 extern "C" 00253 { 00254 MAKE_PLUGIN_START(auto, std::string const&, fhicl::ParameterSet const& pset) 00255 { 00256 return std::make_unique<mfplugins::ELGenFileOutput>(pset); 00257 } MAKE_PLUGIN_END 00258 } 00259 00260 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)