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