1 #define TRACE_NAME "GenFileOutput"
3 #include "cetlib/PluginTypeDeducer.h"
4 #include "cetlib/ostream_handle.h"
5 #include "cetlib/ProvideMakePluginMacros.h"
6 #include "fhiclcpp/ParameterSet.h"
8 #include "boost/date_time/posix_time/posix_time.hpp"
10 #include "messagefacility/MessageService/ELdestination.h"
11 # include "messagefacility/Utilities/ELseverityLevel.h"
12 #include "messagefacility/Utilities/exception.h"
18 using mf::ELseverityLevel;
20 using mf::service::ELdestination;
35 fhicl::Atom<bool>
append = fhicl::Atom<bool>{
36 fhicl::Name{
"append"}, fhicl::Comment{
"Whether to append to the file or recreate it"},
true};
38 fhicl::Atom<std::string>
baseDir = fhicl::Atom<std::string>{
39 fhicl::Name{
"directory"}, fhicl::Comment{
"The directory into which files will be saved"},
"/tmp"};
41 fhicl::Atom<std::string>
sep = fhicl::Atom<std::string>{
42 fhicl::Name{
"seperator"}, fhicl::Comment{
"Separator to use after optional replacement parameters"},
"-"};
44 fhicl::Atom<std::string>
timePattern = fhicl::Atom<std::string>{
45 fhicl::Name{
"timestamp_pattern"}, fhicl::Comment{
"Pattern to use for %t strftime replacement"},
"%Y%m%d%H%M%S"};
60 fhicl::Atom<std::string>
filePattern = fhicl::Atom<std::string>{ fhicl::Name{
"pattern"}, fhicl::Comment{
"Pattern to use for file naming.\n"
61 " Supported parameters are:\n"
62 " %%: Print a % sign\n"
63 " %N: Print the executable name, as retrieved from /proc/<pid>/exe\n"
64 " %?N: Print the executable name only if it does not already appear in the parsed format. "
65 "Format is parsed left-to-right.\n"
66 " These options add a seperator AFTER if they are filled and if they are not the last token in "
67 "the file pattern, before the last '.' character.\n"
68 " %H: Print the hostname, without any domain specifiers (i.e. work.fnal.gov will become work)\n"
69 " %?H: Print the hostname only if it does not already appear in the parsed format.\n"
70 " %p: Print the PID of the application configuring MessageFacility\n"
71 " %t: Print the timestamp using the format specified by timestamp_pattern\n"
72 " %T: Print the timestamp in ISO format"},
93 virtual void routePayload(
const std::ostringstream& o,
const ErrorObj& e)
override;
98 virtual void flush()
override;
101 std::unique_ptr<cet::ostream_handle> output_;
115 bool append = pset().append();
116 std::string baseDir = pset().baseDir();
117 std::string sep = pset().sep();
118 std::string timePattern = pset().timePattern();
119 std::string filePattern = pset().filePattern();
122 std::string exeString =
"";
123 std::string hostString =
"";
124 std::string timeBuffISO =
"";
125 std::string timeBuff =
"";
129 if (filePattern.find(
"%N") != std::string::npos || filePattern.find(
"%?N") != std::string::npos)
133 std::ostringstream pid_ostr;
134 pid_ostr <<
"/proc/" << pid <<
"/exe";
135 exe = std::string(realpath(pid_ostr.str().c_str(), NULL));
137 size_t end = exe.find(
'\0');
138 size_t start = exe.find_last_of(
'/', end);
139 exeString = exe.substr(start + 1, end - start - 1);
143 if (filePattern.find(
"%H") != std::string::npos || filePattern.find(
"%?H") != std::string::npos)
146 if (gethostname(&hostname[0], 256) == 0)
148 std::string tmpString(hostname);
149 hostString = tmpString;
150 size_t pos = hostString.find(
".");
151 if (pos != std::string::npos && pos > 2)
153 hostString = hostString.substr(0, pos);
157 if (filePattern.find(
"%T") != std::string::npos)
159 timeBuffISO = boost::posix_time::to_iso_string(boost::posix_time::second_clock::universal_time());
161 if (filePattern.find(
"%t") != std::string::npos)
168 timeinfo = localtime(&rawtime);
169 strftime(timeBuffC, 256, timePattern.c_str(), timeinfo);
170 timeBuff = std::string(timeBuffC);
174 TLOG(TLVL_DEBUG) <<
"filePattern is: " << filePattern;
175 while (filePattern.find(
"%", pos) != std::string::npos)
177 pos = filePattern.find(
"%", pos) + 1;
178 TLOG(5,1) <<
"Found % at " << (pos - 1) <<
", next char: " << filePattern[pos] <<
".";
179 switch (filePattern[pos])
182 filePattern = filePattern.replace(pos - 1, 2,
"%");
187 char next = filePattern[pos + 1];
191 if (filePattern.find(exeString) != std::string::npos)
193 filePattern = filePattern.erase(pos - 1, 3);
197 std::string repString = exeString;
199 if (!(pos + 1 == filePattern.size() - 1 || pos + 2 == filePattern.find_last_of(
'.')))
203 filePattern = filePattern.replace(pos - 1, 3, repString);
207 if (filePattern.find(hostString) != std::string::npos)
209 filePattern = filePattern.erase(pos - 1, 3);
213 std::string repString = hostString;
215 if (!(pos + 1 == filePattern.size() - 1 || pos + 2 == filePattern.find_last_of(
'.')))
219 filePattern = filePattern.replace(pos - 1, 3, repString);
227 filePattern = filePattern.replace(pos - 1, 2, exeString);
231 filePattern = filePattern.replace(pos - 1, 2, hostString);
235 filePattern = filePattern.replace(pos - 1, 2, std::to_string(pid));
239 filePattern = filePattern.replace(pos - 1, 2, timeBuff);
243 filePattern = filePattern.replace(pos - 1, 2, timeBuffISO);
247 TLOG(6) <<
"filePattern is now: " << filePattern;
249 std::string fileName = baseDir +
"/" + filePattern;
250 TLOG(TLVL_DEBUG) <<
"fileName is: " << fileName;
252 output_ = std::make_unique<cet::ostream_handle>(fileName.c_str(), append ? std::ios::app : std::ios::trunc);
261 *output_ << oss.str();
279 MAKE_PLUGIN_START(
auto, std::string
const&, fhicl::ParameterSet
const& pset)
281 return std::make_unique<mfplugins::ELGenFileOutput>(pset);
285 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)
fhicl::Atom< std::string > baseDir
"directory" (Default: "/tmp"): The directory into which files will be saved
virtual void routePayload(const std::ostringstream &o, const ErrorObj &e) override
Serialize a MessageFacility message to the output stream.
fhicl::TableFragment< ELdestination::Config > elDestConfig
ELDestination common configuration parameters.
Message Facility destination which generates the output file name based on some combination of PID...
fhicl::Atom< std::string > sep
"seperator" (Default: "-"): Separator to use after optional replacement parameters ...
Parameters used to configure GenFileOutput.
ELGenFileOutput(Parameters const &pset)
ELGenFileOutput Constructor.
virtual void flush() override
Flush any text in the ostream buffer to disk.
virtual ~ELGenFileOutput()
Default virtual destructor.
fhicl::Atom< bool > append
"append" (Default: true"): Whether to append to the file or recreate it
fhicl::Atom< std::string > filePattern
"pattern" (Default: "%N-%?H%t-%p.log"): Pattern to use for file naming.
fhicl::Atom< std::string > timePattern
"timestamp_pattern" (Default: "%Y%m%d%H%M%S"): Pattern to use for t strftime replacement ...
fhicl::WrappedTable< Config > Parameters
Used for ParameterSet validation.