1 #define TRACE_NAME "GenFileOutput"
3 #include "cetlib/PluginTypeDeducer.h"
4 #include "cetlib/ostream_handle.h"
5 #if MESSAGEFACILITY_HEX_VERSION >= 0x20106 // v2_01_06 => cetlib v3_02_00 => new clang support
6 #include "cetlib/ProvideMakePluginMacros.h"
8 #include "fhiclcpp/ParameterSet.h"
10 #include "boost/date_time/posix_time/posix_time.hpp"
12 #include "messagefacility/MessageService/ELdestination.h"
13 # include "messagefacility/Utilities/ELseverityLevel.h"
14 #include "messagefacility/Utilities/exception.h"
21 using mf::service::ELdestination;
22 using mf::ELseverityLevel;
31 #if MESSAGEFACILITY_HEX_VERSION >= 0x20103
34 fhicl::TableFragment<ELdestination::Config> elDestConfig;
35 fhicl::Atom<bool> append{ fhicl::Name{
"append"},fhicl::Comment {
"Whether to append to the file or recreate it"},
true };
36 fhicl::Atom<std::string> baseDir{ fhicl::Name{
"directory"},fhicl::Comment{
"The directory into which files will be saved"},
"/tmp" };
37 fhicl::Atom<std::string> sep{ fhicl::Name{
"seperator"},fhicl::Comment{
"Separator to use after optional replacement parameters"},
"-" };
38 fhicl::Atom<std::string> timePattern{ fhicl::Name{
"timestamp_pattern"},fhicl::Comment{
"Pattern to use for %t strftime replacement"},
"%Y%m%d%H%M%S" };
39 fhicl::Atom<std::string> filePattern{ fhicl::Name{
"pattern" },fhicl::Comment{
"Pattern to use for file naming.\n"
40 " Supported parameters are:\n"
41 " %%: Print a % sign\n"
42 " %N: Print the executable name, as retrieved from /proc/<pid>/exe\n"
43 " %?N: Print the executable name only if it does not already appear in the parsed format. Format is parsed left-to-right.\n"
44 " 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"
45 " %H: Print the hostname, without any domain specifiers (i.e. work.fnal.gov will become work)\n"
46 " %?H: Print the hostname only if it does not already appear in the parsed format.\n"
47 " %p: Print the PID of the application configuring MessageFacility\n"
48 " %t: Print the timestamp using the format specified by timestamp_pattern\n"
49 " %T: Print the timestamp in ISO format"
50 },
"%N-%?H%t-%p.log" };
54 using Parameters = fhicl::WrappedTable<Config>;
58 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
80 virtual void routePayload(
const std::ostringstream& o,
const ErrorObj& e)
override;
85 virtual void flush()
override;
88 std::unique_ptr<cet::ostream_handle> output_;
99 #if MESSAGEFACILITY_HEX_VERSION < 0x20103
101 : ELdestination(pset)
103 bool append = pset.get<
bool>(
"append",
true);
104 std::string baseDir = pset.get<std::string>(
"directory",
"/tmp");
105 std::string sep = pset.get<std::string>(
"separator",
"-");
106 std::string timePattern = pset.get<std::string>(
"timestamp_pattern",
"%Y%m%d%H%M%S");
107 std::string filePattern = pset.get<std::string>(
"pattern",
"%N-%?H%t-%p.log");
111 bool append = pset().append();
112 std::string baseDir = pset().baseDir();
113 std::string sep = pset().sep();
114 std::string timePattern = pset().timePattern();
115 std::string filePattern = pset().filePattern();
119 std::string exeString =
"";
120 std::string hostString =
"";
121 std::string timeBuffISO =
"";
122 std::string timeBuff =
"";
126 if (filePattern.find(
"%N") != std::string::npos || filePattern.find(
"%?N") != std::string::npos)
130 std::ostringstream pid_ostr;
131 pid_ostr <<
"/proc/" << pid <<
"/exe";
132 exe = std::string(realpath(pid_ostr.str().c_str(), NULL));
134 size_t end = exe.find(
'\0');
135 size_t start = exe.find_last_of(
'/', end);
136 exeString = exe.substr(start + 1, end - start - 1);
140 if (filePattern.find(
"%H") != std::string::npos || filePattern.find(
"%?H") != std::string::npos)
143 if (gethostname(&hostname[0], 256) == 0)
145 std::string tmpString(hostname);
146 hostString = tmpString;
147 size_t pos = hostString.find(
".");
148 if (pos != std::string::npos && pos > 2)
150 hostString = hostString.substr(0, pos);
154 if (filePattern.find(
"%T") != std::string::npos)
156 timeBuffISO = boost::posix_time::to_iso_string(boost::posix_time::second_clock::universal_time());
158 if (filePattern.find(
"%t") != std::string::npos)
165 timeinfo = localtime(&rawtime);
166 strftime(timeBuffC, 256, timePattern.c_str(), timeinfo);
167 timeBuff = std::string(timeBuffC);
171 TLOG(TLVL_DEBUG) <<
"filePattern is: " << filePattern;
172 while (filePattern.find(
"%", pos) != std::string::npos)
174 pos = filePattern.find(
"%", pos) + 1;
175 TLOG(5,1) <<
"Found % at " << (pos - 1) <<
", next char: " << filePattern[pos] <<
".";
176 switch (filePattern[pos])
179 filePattern = filePattern.replace(pos - 1, 2,
"%");
184 char next = filePattern[pos + 1];
188 if (filePattern.find(exeString) != std::string::npos)
190 filePattern = filePattern.erase(pos - 1, 3);
194 std::string repString = exeString;
196 if (!(pos + 1 == filePattern.size() - 1 || pos + 2 == filePattern.find_last_of(
'.')))
200 filePattern = filePattern.replace(pos - 1, 3, repString);
204 if (filePattern.find(hostString) != std::string::npos)
206 filePattern = filePattern.erase(pos - 1, 3);
210 std::string repString = hostString;
212 if (!(pos + 1 == filePattern.size() - 1 || pos + 2 == filePattern.find_last_of(
'.')))
216 filePattern = filePattern.replace(pos - 1, 3, repString);
224 filePattern = filePattern.replace(pos - 1, 2, exeString);
228 filePattern = filePattern.replace(pos - 1, 2, hostString);
232 filePattern = filePattern.replace(pos - 1, 2, std::to_string(pid));
236 filePattern = filePattern.replace(pos - 1, 2, timeBuff);
240 filePattern = filePattern.replace(pos - 1, 2, timeBuffISO);
244 TLOG(6) <<
"filePattern is now: " << filePattern;
246 std::string fileName = baseDir +
"/" + filePattern;
247 TLOG(TLVL_DEBUG) <<
"fileName is: " << fileName;
249 output_ = std::make_unique<cet::ostream_handle>(fileName.c_str(), append ? std::ios::app : std::ios::trunc);
258 *output_ << oss.str();
277 #if MESSAGEFACILITY_HEX_VERSION >= 0x20106 // v2_01_06 => cetlib v3_02_00 => new clang support
278 MAKE_PLUGIN_START(
auto, std::string
const&, fhicl::ParameterSet
const& pset)
280 return std::make_unique<mfplugins::ELGenFileOutput>(pset);
283 auto makePlugin(std::string
const&, fhicl::ParameterSet
const& pset)
285 return std::make_unique<mfplugins::ELGenFileOutput>(pset);
290 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)
virtual void routePayload(const std::ostringstream &o, const ErrorObj &e) override
Serialize a MessageFacility message to the output stream.
ELGenFileOutput(const fhicl::ParameterSet &pset)
ELGenFileOutput Constructor.
Message Facility destination which generates the output file name based on some combination of PID...
virtual void flush() override
Flush any text in the ostream buffer to disk.
virtual ~ELGenFileOutput()
Default virtual destructor.