00001 #include "cetlib/PluginTypeDeducer.h"
00002 #include "cetlib/ostream_handle.h"
00003 #include "fhiclcpp/ParameterSet.h"
00004
00005 #include "messagefacility/MessageService/ELdestination.h"
00006 # include "messagefacility/Utilities/ELseverityLevel.h"
00007 #if MESSAGEFACILITY_HEX_VERSION < 0x20002 // v2_00_02 is s50, pre v2_00_02 is s48
00008 # include "messagefacility/MessageService/ELcontextSupplier.h"
00009 # include "messagefacility/MessageLogger/MessageDrop.h"
00010 #endif
00011 #include "messagefacility/Utilities/exception.h"
00012
00013 #include <fstream>
00014
00015 namespace mfplugins
00016 {
00017 using mf::service::ELdestination;
00018 using mf::ELseverityLevel;
00019 using mf::ErrorObj;
00020 #if MESSAGEFACILITY_HEX_VERSION < 0x20002 // v2_00_02 is s50, pre v2_00_02 is s48
00021 using mf::service::ELcontextSupplier;
00022 #endif
00023
00027 class ELMultiFileOutput : public ELdestination
00028 {
00029 #if MESSAGEFACILITY_HEX_VERSION >= 0x20103
00030 struct Config
00031 {
00032 fhicl::TableFragment<ELdestination::Config> elDestConfig;
00033 fhicl::Atom<std::string> baseDir{ fhicl::Name{ "base_directory" },fhicl::Comment{ "Directory where log files will be created" },"/tmp" };
00034 fhicl::Atom<bool> append{ fhicl::Name{ "append" },fhicl::Comment{ "Append to existing log files" },true };
00035 fhicl::Atom<bool> useHostname{ fhicl::Name{ "use_hostname" },fhicl::Comment{ "Use the hostname when generating log file names" },true };
00036 fhicl::Atom<bool> useApplication{ fhicl::Name{ "use_application" },fhicl::Comment{ "Use the application field when generating log file names" },true };
00037 fhicl::Atom<bool> useCategory{ fhicl::Name{ "use_category" },fhicl::Comment{ "Use the category field when generating log file names" },false };
00038 fhicl::Atom<bool> useModule{ fhicl::Name{ "use_module" },fhicl::Comment{ "Use the module field when generating log file names" },false };
00039 };
00040 using Parameters = fhicl::WrappedTable<Config>;
00041 #endif
00042 public:
00043 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
00044 ELMultiFileOutput(const fhicl::ParameterSet& pset);
00045 #else
00046 ELMultiFileOutput(Parameters const& pset);
00047 #endif
00048
00049 virtual ~ELMultiFileOutput() {}
00050
00051 virtual void routePayload(const std::ostringstream&, const ErrorObj&
00052 # if MESSAGEFACILITY_HEX_VERSION < 0x20002
00053 , const ELcontextSupplier&
00054 #endif
00055 ) override;
00056
00057 virtual void flush(
00058 # if MESSAGEFACILITY_HEX_VERSION < 0x20002
00059 const ELcontextSupplier&
00060 #endif
00061 ) override;
00062
00063 private:
00064 std::string baseDir_;
00065 bool append_;
00066 std::unordered_map<std::string, std::unique_ptr<cet::ostream_handle>> outputs_;
00067
00068 bool useHost_;
00069 bool useApplication_;
00070 bool useCategory_;
00071 bool useModule_;
00072 };
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
00084 ELMultiFileOutput::ELMultiFileOutput(const fhicl::ParameterSet& pset)
00085 : ELdestination(pset)
00086 , baseDir_(pset.get<std::string>("base_directory", "/tmp"))
00087 , append_(pset.get<bool>("append", true))
00088 , useHost_(pset.get<bool>("use_hostname", true))
00089 , useApplication_(pset.get<bool>("use_application", true))
00090 , useCategory_(pset.get<bool>("use_category", false))
00091 , useModule_(pset.get<bool>("use_module", false)) { }
00092 #else
00093 ELMultiFileOutput::ELMultiFileOutput(Parameters const& pset)
00094 : ELdestination(pset().elDestConfig())
00095 , baseDir_(pset().baseDir())
00096 , append_(pset().append())
00097 , useHost_(pset().useHostname())
00098 , useApplication_(pset().useApplication())
00099 , useCategory_(pset().useCategory())
00100 , useModule_(pset().useModule()) { }
00101 #endif
00102
00103
00104
00105
00106 void ELMultiFileOutput::routePayload(const std::ostringstream& oss, const ErrorObj& msg
00107 # if MESSAGEFACILITY_HEX_VERSION < 0x20002
00108 , ELcontextSupplier const& sup
00109 #endif
00110 )
00111 {
00112 const auto& xid = msg.xid();
00113 std::string fileName = baseDir_ + "/";
00114 # if MESSAGEFACILITY_HEX_VERSION >= 0x20002 // an indication of a switch from s48 to s50
00115 if (useModule_) { fileName += xid.module() + "-"; }
00116 if (useCategory_) { fileName += xid.id() + "-"; }
00117 if (useApplication_) { fileName += xid.application() + "-"; }
00118 if (useHost_) { fileName += xid.hostname() + "-"; }
00119 fileName += std::to_string(xid.pid()) + ".log";
00120 # else
00121 if (useModule_) { fileName += xid.module + "-"; }
00122 if (useCategory_) { fileName += xid.id + "-"; }
00123 if (useApplication_) { fileName += xid.application + "-"; }
00124 if (useHost_) { fileName += xid.hostname + "-"; }
00125 fileName += std::to_string(xid.pid) + ".log";
00126 # endif
00127 if (outputs_.count(fileName) == 0)
00128 {
00129 #ifndef CETLIB_EXPOSES_OSTREAM_OWNER // New cetlib
00130 outputs_[fileName] = std::make_unique<cet::ostream_handle>(fileName.c_str(), append_ ? std::ios::app : std::ios::trunc);
00131 #else // Old cetlib
00132 outputs_[fileName] = std::make_unique<cet::ostream_owner>(fileName.c_str(), append_ ? std::ios::app : std::ios::trunc);
00133 #endif
00134 }
00135 *outputs_[fileName] << oss.str();
00136 flush(
00137 # if MESSAGEFACILITY_HEX_VERSION < 0x20002
00138 sup
00139 #endif
00140 );
00141 }
00142
00143 void ELMultiFileOutput::flush(
00144 # if MESSAGEFACILITY_HEX_VERSION < 0x20002
00145 ELcontextSupplier const&
00146 #endif
00147 )
00148 {
00149 for (auto i = outputs_.begin(); i != outputs_.end(); ++i)
00150 {
00151 #ifndef CETLIB_EXPOSES_OSTREAM_OWNER // New cetlib
00152 (*i).second->flush();
00153 #else // Old cetlib
00154 (*i).second->stream().flush();
00155 #endif
00156 }
00157 }
00158 }
00159
00160
00161
00162
00163
00164
00165
00166 extern "C"
00167 {
00168 auto makePlugin(const std::string&,
00169 const fhicl::ParameterSet& pset)
00170 {
00171 return std::make_unique<mfplugins::ELMultiFileOutput>(pset);
00172 }
00173 }
00174
00175 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)