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