artdaq_mfextensions  v1_03_02
MultiFile_mfPlugin.cc
1 #include "cetlib/PluginTypeDeducer.h"
2 #include "cetlib/ostream_handle.h"
3 #include "fhiclcpp/ParameterSet.h"
4 
5 #include "messagefacility/MessageService/ELdestination.h"
6 # include "messagefacility/Utilities/ELseverityLevel.h"
7 #include "messagefacility/Utilities/exception.h"
8 #include "cetlib/compiler_macros.h"
9 
10 #include <fstream>
11 
12 namespace mfplugins
13 {
14  using mf::service::ELdestination;
15  using mf::ELseverityLevel;
16  using mf::ErrorObj;
17 
21  class ELMultiFileOutput : public ELdestination
22  {
23 #if MESSAGEFACILITY_HEX_VERSION >= 0x20103
24  struct Config
25  {
26  fhicl::TableFragment<ELdestination::Config> elDestConfig;
27  fhicl::Atom<std::string> baseDir{ fhicl::Name{ "base_directory" },fhicl::Comment{ "Directory where log files will be created" },"/tmp" };
28  fhicl::Atom<bool> append{ fhicl::Name{ "append" },fhicl::Comment{ "Append to existing log files" },true };
29  fhicl::Atom<bool> useHostname{ fhicl::Name{ "use_hostname" },fhicl::Comment{ "Use the hostname when generating log file names" },true };
30  fhicl::Atom<bool> useApplication{ fhicl::Name{ "use_application" },fhicl::Comment{ "Use the application field when generating log file names" },true };
31  fhicl::Atom<bool> useCategory{ fhicl::Name{ "use_category" },fhicl::Comment{ "Use the category field when generating log file names" },false };
32  fhicl::Atom<bool> useModule{ fhicl::Name{ "use_module" },fhicl::Comment{ "Use the module field when generating log file names" },false };
33  };
34  using Parameters = fhicl::WrappedTable<Config>;
35 #endif
36  public:
41 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
42  ELMultiFileOutput(const fhicl::ParameterSet& pset);
43 #else
44  ELMultiFileOutput(Parameters const& pset);
45 #endif
46  virtual ~ELMultiFileOutput() {}
50 
56  virtual void routePayload(const std::ostringstream& oss, const ErrorObj& msg) override;
57 
61  virtual void flush() override;
62 
63  private:
64  std::string baseDir_;
65  bool append_;
66  std::unordered_map<std::string, std::unique_ptr<cet::ostream_handle>> outputs_;
67 
68  bool useHost_;
69  bool useApplication_;
70  bool useCategory_;
71  bool useModule_;
72  };
73 
74  // END DECLARATION
75  //======================================================================
76  // BEGIN IMPLEMENTATION
77 
78 
79  //======================================================================
80  // ELMultiFileOutput c'tor
81  //======================================================================
82 
83 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
84  ELMultiFileOutput::ELMultiFileOutput(const fhicl::ParameterSet& pset)
85  : ELdestination(pset)
86  , baseDir_(pset.get<std::string>("base_directory", "/tmp"))
87  , append_(pset.get<bool>("append", true))
88  , useHost_(pset.get<bool>("use_hostname", true))
89  , useApplication_(pset.get<bool>("use_application", true))
90  , useCategory_(pset.get<bool>("use_category", false))
91  , useModule_(pset.get<bool>("use_module", false))
92  {}
93 #else
94  ELMultiFileOutput::ELMultiFileOutput(Parameters const& pset)
95  : ELdestination(pset().elDestConfig())
96  , baseDir_(pset().baseDir())
97  , append_(pset().append())
98  , useHost_(pset().useHostname())
99  , useApplication_(pset().useApplication())
100  , useCategory_(pset().useCategory())
101  , useModule_(pset().useModule())
102  {}
103 #endif
104 
105  //======================================================================
106  // Message router ( overriddes ELdestination::routePayload )
107  //======================================================================
108  void ELMultiFileOutput::routePayload(const std::ostringstream& oss, const ErrorObj& msg)
109  {
110  const auto& xid = msg.xid();
111  std::string fileName = baseDir_ + "/";
112  if (useModule_) { fileName += xid.module() + "-"; }
113  if (useCategory_) { fileName += xid.id() + "-"; }
114  if (useApplication_) { fileName += xid.application() + "-"; }
115  if (useHost_) { fileName += xid.hostname() + "-"; }
116  fileName += std::to_string(xid.pid()) + ".log";
117  if (outputs_.count(fileName) == 0)
118  {
119  outputs_[fileName] = std::make_unique<cet::ostream_handle>(fileName.c_str(), append_ ? std::ios::app : std::ios::trunc);
120  }
121  *outputs_[fileName] << oss.str();
122  flush();
123  }
124 
126  {
127  for (auto i = outputs_.begin(); i != outputs_.end(); ++i)
128  {
129  (*i).second->flush();
130  }
131  }
132 } // end namespace mfplugins
133 
134 //======================================================================
135 //
136 // makePlugin function
137 //
138 //======================================================================
139 
140 #ifndef EXTERN_C_FUNC_DECLARE_START
141 #define EXTERN_C_FUNC_DECLARE_START extern "C" {
142 #endif
143 
144 EXTERN_C_FUNC_DECLARE_START
145 auto makePlugin(const std::string&,
146  const fhicl::ParameterSet& pset)
147 {
148  return std::make_unique<mfplugins::ELMultiFileOutput>(pset);
149 }
150 }
151 
152 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)
Message Facility Destination which automatically opens files and sorts messages into them based on gi...
ELMultiFileOutput(const fhicl::ParameterSet &pset)
ELMultiFileOutput Constructor
virtual ~ELMultiFileOutput()
Default virtual Destructor
virtual void routePayload(const std::ostringstream &oss, const ErrorObj &msg) override
Serialize a MessageFacility message to the output.
virtual void flush() override
Flush any text in the ostream buffer to disk.