artdaq_mfextensions  v1_03_02
Friendly_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/MessageService/ELostreamOutput.h"
7 #include "messagefacility/Utilities/ELseverityLevel.h"
8 #include "messagefacility/Utilities/exception.h"
9 #include "cetlib/compiler_macros.h"
10 
11 // C/C++ includes
12 #include <iostream>
13 #include <memory>
14 #include <algorithm>
15 
16 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
17 #define format_ format
18 #endif
19 
20 namespace mfplugins
21 {
22  using namespace mf::service;
23  using mf::ELseverityLevel;
24  using mf::ErrorObj;
25 
29  class ELFriendly : public ELostreamOutput
30  {
31 #if MESSAGEFACILITY_HEX_VERSION >= 0x20103
32  struct Config
33  {
34  fhicl::TableFragment<ELostreamOutput::Config> elOstrConfig;
35  fhicl::Atom<std::string> delimiter{ fhicl::Name{ "field_delimiter" },fhicl::Comment{ "String to print between each message field" }," " };
36  };
37  using Parameters = fhicl::WrappedTable<Config>;
38 #endif
39  public:
44 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
45  ELFriendly(const fhicl::ParameterSet& pset);
46 #else
47  ELFriendly(Parameters const& pset);
48 #endif
49 
55  virtual void fillPrefix(std::ostringstream& o, const ErrorObj& e) override;
61  virtual void fillUsrMsg(std::ostringstream& o, const ErrorObj& e) override;
67  virtual void fillSuffix(std::ostringstream& o, const ErrorObj& e) override;
68 
69  private:
70  std::string delimeter_;
71  };
72 
73  // END DECLARATION
74  //======================================================================
75  // BEGIN IMPLEMENTATION
76 
77 
78  //======================================================================
79  // ELFriendly c'tor
80  //======================================================================
81 
82 #if MESSAGEFACILITY_HEX_VERSION < 0x20103 // v2_01_03 is s58, pre v2_01_03 is s50
83  ELFriendly::ELFriendly(const fhicl::ParameterSet& pset)
84  : ELostreamOutput(pset, cet::ostream_handle{ std::cout }, false)
85  , delimeter_(pset.get<std::string>("field_delimeter", " "))
86 #else
87  ELFriendly::ELFriendly(Parameters const& pset)
88  : ELostreamOutput(pset().elOstrConfig(), cet::ostream_handle{ std::cout }, false)
89  , delimeter_(pset().delimiter())
90 #endif
91  {}
92 
93  //======================================================================
94  // Message prefix filler ( overriddes ELdestination::fillPrefix )
95  //======================================================================
96  void ELFriendly::fillPrefix(std::ostringstream& oss, const ErrorObj& msg)
97  {
98  //if (msg.is_verbatim()) return;
99 
100  // Output the prologue:
101  //
102 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
103  format_.preambleMode = true;
104 #endif
105 
106  auto const& xid = msg.xid();
107 
108  auto id = xid.id();
109  auto app = xid.application();
110  auto module = xid.module();
111  auto subroutine = xid.subroutine();
112  std::replace(id.begin(), id.end(), ' ', '-');
113  std::replace(app.begin(), app.end(), ' ', '-');
114  std::replace(module.begin(), module.end(), ' ', '-');
115  std::replace(subroutine.begin(), subroutine.end(), ' ', '-');
116 
117  emitToken(oss, "%MSG");
118  emitToken(oss, xid.severity().getSymbol());
119  emitToken(oss, delimeter_);
120  emitToken(oss, id);
121  emitToken(oss, msg.idOverflow());
122  emitToken(oss, ":");
123  emitToken(oss, delimeter_);
124 
125  // Output serial number of message:
126  //
127  if (format_.want(SERIAL))
128  {
129  std::ostringstream s;
130  s << msg.serial();
131  emitToken(oss, "[serial #" + s.str() + "]");
132  emitToken(oss, delimeter_);
133  }
134 
135  // Provide further identification:
136  //
137  bool needAspace = true;
138  if (format_.want(EPILOGUE_SEPARATE))
139  {
140  if (module.length() + subroutine.length() > 0)
141  {
142  emitToken(oss, "\n");
143  needAspace = false;
144  }
145  else if (format_.want(TIMESTAMP) && !format_.want(TIME_SEPARATE))
146  {
147  emitToken(oss, "\n");
148  needAspace = false;
149  }
150  }
151  if (format_.want(MODULE) && (module.length() > 0))
152  {
153  if (needAspace)
154  {
155  emitToken(oss, delimeter_);
156  needAspace = false;
157  }
158  emitToken(oss, module + " ");
159  }
160  if (format_.want(SUBROUTINE) && (subroutine.length() > 0))
161  {
162  if (needAspace)
163  {
164  emitToken(oss, delimeter_);
165  needAspace = false;
166  }
167  emitToken(oss, subroutine + "()");
168  emitToken(oss, delimeter_);
169  }
170 
171  // Provide time stamp:
172  //
173  if (format_.want(TIMESTAMP))
174  {
175  if (format_.want(TIME_SEPARATE))
176  {
177  emitToken(oss, "\n");
178  needAspace = false;
179  }
180  if (needAspace)
181  {
182  emitToken(oss, delimeter_);
183  needAspace = false;
184  }
185  emitToken(oss, format_.timestamp(msg.timestamp()));
186  emitToken(oss, delimeter_);
187  }
188 
189  // Provide the context information:
190  //
191  if (format_.want(SOME_CONTEXT))
192  {
193  if (needAspace)
194  {
195  emitToken(oss, delimeter_);
196  needAspace = false;
197  }
198  emitToken(oss, msg.context());
199  }
200 
201  }
202 
203 
204  //=============================================================================
205  void ELFriendly::fillUsrMsg(std::ostringstream& oss, ErrorObj const& msg)
206  {
207  if (!format_.want(TEXT)) return;
208 
209 #if MESSAGEFACILITY_HEX_VERSION < 0x20201 // format changed to format_ for s67
210  format_.preambleMode = false;
211 #endif
212  auto const usrMsgStart = std::next(msg.items().cbegin(), 4);
213  auto it = msg.items().cbegin();
214 
215  // Determine if file and line should be included
216  if (true || !msg.is_verbatim())
217  {
218 
219  // The first four items are { " ", "<FILENAME>", ":", "<LINE>" }
220  while (it != usrMsgStart)
221  {
222  if (!it->compare(" ") && !std::next(it)->compare("--"))
223  {
224  // Do not emit if " --:0" is the match
225  std::advance(it, 4);
226  }
227  else
228  {
229  // Emit if <FILENAME> and <LINE> are meaningful
230  emitToken(oss, *it++);
231  }
232  }
233 
234  // Check for user-requested line breaks
235  if (format_.want(NO_LINE_BREAKS)) emitToken(oss, " ==> ");
236  else emitToken(oss, "", true);
237  }
238 
239  // For verbatim (and user-supplied) messages, just print the contents
240  auto const end = msg.items().cend();
241  for (; it != end; ++it)
242  {
243  emitToken(oss, *it);
244  }
245 
246  }
247 
248 
249  //=============================================================================
250  void ELFriendly::fillSuffix(std::ostringstream& oss, ErrorObj const& msg)
251  {
252  if ((true || !msg.is_verbatim()) && !format_.want(NO_LINE_BREAKS))
253  {
254  emitToken(oss, "\n%MSG");
255  }
256  oss << '\n';
257  }
258 
259 
260 
261 } // end namespace mfplugins
262 
263 //======================================================================
264 //
265 // makePlugin function
266 //
267 //======================================================================
268 
269 #ifndef EXTERN_C_FUNC_DECLARE_START
270 #define EXTERN_C_FUNC_DECLARE_START extern "C" {
271 #endif
272 
273 EXTERN_C_FUNC_DECLARE_START
274 auto makePlugin(const std::string&,
275  const fhicl::ParameterSet& pset)
276 {
277  return std::make_unique<mfplugins::ELFriendly>(pset);
278 }
279 }
280 
281 DEFINE_BASIC_PLUGINTYPE_FUNC(mf::service::ELdestination)
Parser-Friendly Message Facility destination plugin
virtual void fillSuffix(std::ostringstream &o, const ErrorObj &e) override
Fill the &quot;Suffix&quot; portion of the message.
ELFriendly(const fhicl::ParameterSet &pset)
ELFriendly Constructor
virtual void fillUsrMsg(std::ostringstream &o, const ErrorObj &e) override
Fill the &quot;User Message&quot; portion of the message.
virtual void fillPrefix(std::ostringstream &o, const ErrorObj &e) override
Fill the &quot;Prefix&quot; portion of the message.