artdaq_mfextensions  v1_02_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 #if MESSAGEFACILITY_HEX_VERSION < 0x20002 // v2_00_02 is s50, pre v2_00_02 is s48
8 # include "messagefacility/MessageService/ELcontextSupplier.h"
9 # include "messagefacility/MessageLogger/MessageDrop.h"
10 #endif
11 #include "messagefacility/Utilities/exception.h"
12 
13 #include <fstream>
14 
15 namespace mfplugins
16 {
17  using mf::service::ELdestination;
18  using mf::ELseverityLevel;
19  using mf::ErrorObj;
20 #if MESSAGEFACILITY_HEX_VERSION < 0x20002 // v2_00_02 is s50, pre v2_00_02 is s48
21  using mf::service::ELcontextSupplier;
22 #endif
23 
27  class ELMultiFileOutput : public ELdestination
28  {
29 #if MESSAGEFACILITY_HEX_VERSION >= 0x20103
30  struct Config
31  {
32  fhicl::TableFragment<ELdestination::Config> elDestConfig;
33  fhicl::Atom<std::string> baseDir{ fhicl::Name{ "base_directory" },fhicl::Comment{ "Directory where log files will be created" },"/tmp" };
34  fhicl::Atom<bool> append{ fhicl::Name{ "append" },fhicl::Comment{ "Append to existing log files" },true };
35  fhicl::Atom<bool> useHostname{ fhicl::Name{ "use_hostname" },fhicl::Comment{ "Use the hostname when generating log file names" },true };
36  fhicl::Atom<bool> useApplication{ fhicl::Name{ "use_application" },fhicl::Comment{ "Use the application field when generating log file names" },true };
37  fhicl::Atom<bool> useCategory{ fhicl::Name{ "use_category" },fhicl::Comment{ "Use the category field when generating log file names" },false };
38  fhicl::Atom<bool> useModule{ fhicl::Name{ "use_module" },fhicl::Comment{ "Use the module field when generating log file names" },false };
39  };
40  using Parameters = fhicl::WrappedTable<Config>;
41 #endif
42  public:
43 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
44  ELMultiFileOutput(const fhicl::ParameterSet& pset);
45 #else
46  ELMultiFileOutput(Parameters const& pset);
47 #endif
48 
49  virtual ~ELMultiFileOutput() {}
50 
51  virtual void routePayload(const std::ostringstream&, const ErrorObj&
52 # if MESSAGEFACILITY_HEX_VERSION < 0x20002 // v2_00_02 is s50, pre v2_00_02 is s48
53  , const ELcontextSupplier&
54 #endif
55  ) override;
56 
57  virtual void flush(
58 # if MESSAGEFACILITY_HEX_VERSION < 0x20002 // v2_00_02 is s50, pre v2_00_02 is s48
59  const ELcontextSupplier&
60 #endif
61  ) 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 #else
93  ELMultiFileOutput::ELMultiFileOutput(Parameters const& pset)
94  : ELdestination(pset().elDestConfig())
95  , baseDir_(pset().baseDir())
96  , append_(pset().append())
97  , useHost_(pset().useHostname())
98  , useApplication_(pset().useApplication())
99  , useCategory_(pset().useCategory())
100  , useModule_(pset().useModule()) { }
101 #endif
102 
103  //======================================================================
104  // Message router ( overriddes ELdestination::routePayload )
105  //======================================================================
106  void ELMultiFileOutput::routePayload(const std::ostringstream& oss, const ErrorObj& msg
107 # if MESSAGEFACILITY_HEX_VERSION < 0x20002 // v2_00_02 is s50, pre v2_00_02 is s48
108  , ELcontextSupplier const& sup
109 #endif
110  )
111  {
112  const auto& xid = msg.xid();
113  std::string fileName = baseDir_ + "/";
114 # if MESSAGEFACILITY_HEX_VERSION >= 0x20002 // an indication of a switch from s48 to s50
115  if (useModule_) { fileName += xid.module() + "-"; }
116  if (useCategory_) { fileName += xid.id() + "-"; }
117  if (useApplication_) { fileName += xid.application() + "-"; }
118  if (useHost_) { fileName += xid.hostname() + "-"; }
119  fileName += std::to_string(xid.pid()) + ".log";
120 # else
121  if (useModule_) { fileName += xid.module + "-"; }
122  if (useCategory_) { fileName += xid.id + "-"; }
123  if (useApplication_) { fileName += xid.application + "-"; }
124  if (useHost_) { fileName += xid.hostname + "-"; }
125  fileName += std::to_string(xid.pid) + ".log";
126 # endif
127  if (outputs_.count(fileName) == 0)
128  {
129 #ifndef CETLIB_EXPOSES_OSTREAM_OWNER // New cetlib
130  outputs_[fileName] = std::make_unique<cet::ostream_handle>(fileName.c_str(), append_ ? std::ios::app : std::ios::trunc);
131 #else // Old cetlib
132  outputs_[fileName] = std::make_unique<cet::ostream_owner>(fileName.c_str(), append_ ? std::ios::app : std::ios::trunc);
133 #endif
134  }
135  *outputs_[fileName] << oss.str();
136  flush(
137 # if MESSAGEFACILITY_HEX_VERSION < 0x20002 // v2_00_02 is s50, pre v2_00_02 is s48
138  sup
139 #endif
140  );
141  }
142 
143  void ELMultiFileOutput::flush(
144 # if MESSAGEFACILITY_HEX_VERSION < 0x20002 // v2_00_02 is s50, pre v2_00_02 is s48
145  ELcontextSupplier const&
146 #endif
147  )
148  {
149  for (auto i = outputs_.begin(); i != outputs_.end(); ++i)
150  {
151 #ifndef CETLIB_EXPOSES_OSTREAM_OWNER // New cetlib
152  (*i).second->flush();
153 #else // Old cetlib
154  (*i).second->stream().flush();
155 #endif
156  }
157  }
158 } // end namespace mfplugins
159 
160 //======================================================================
161 //
162 // makePlugin function
163 //
164 //======================================================================
165 
166 extern "C"
167 {
168  auto makePlugin(const std::string&,
169  const fhicl::ParameterSet& pset)
170  {
171  return std::make_unique<mfplugins::ELMultiFileOutput>(pset);
172  }
173 }
174 
175 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)
Message Facility Destination which automatically opens files and sorts messages into them based on gi...